diff options
139 files changed, 17464 insertions, 934 deletions
@@ -77,6 +77,7 @@ Backends: 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 (*) @@ -196,12 +197,14 @@ Jon Chambers <jon@jon.demon.co.uk> Jonathan Bravo Lopez <jkdsoft@gmail.com> Juergen G. Schimmer <schimmi@nbgm.siemens.de> Julien Blache <jb@jblache.org> +Jan Vleeshouwers <J.M.Vleeshouwers@tue.nl> Karl Anders Øygard <karlo@opera.no> Karl Heinz Kremer <khk@khk.net> Karsten Festag <karsten.festag@gmx.de> Kazuhiro Sasayama <kaz@hypercore.co.jp> Kazuya Fukuda <kaafuu@mug.biglobe.ne.jp> Kevin Charter <charter@cs.rice.edu> +Klaus Kämpf <kkaempf@suse.com> Louis Lagendijk <llagendijk-guest at users.alioth.debian.org> M.F. <massifr@tiscalinet.it> Manuel Panea <Manuel.Panea@rzg.mpg.de> @@ -216,6 +219,7 @@ Max Vorobiev <pcwizard@yandex.ru> Meino Christian Cramer <mccramer@s.netic.de> Michael Herder <crapmail@nurfuerspam.de> Michael K. Johnson <johnsonm@redhat.com> +Michael Rickmann <mrickma@gwdg.de> Michel Roelofs <michelr@stack.nl> Milon Firikis <milonf@ariadne-t.gr> Mitsuru Okaniwa <m-okaniwa@bea.hi-ho.ne.jp> @@ -1,3 +1,117 @@ +2015-09-26 Rolf Bensch <rolf at bensch hyphen online dot de> + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.23 + +2015-06-22 Louis Lagendijk <louis dot lagendijk at gmail dot com> + * doc/saned.man: updated to clarify systemd integration and + configuration for thecase where saned is compiled with systemd + glue. + +2015-09-18 Rolf Bensch <rolf at bensch hyphen online dot de> + * backend/pixma_imageclass.c: for all adf scanners restrict maximum page + height at flatbed scans + +2015-09-16 Stéphane Voltz <stef.dev@free.fr> + * backend/niash.c: merged pu/protect-niash-option-access-315132 and + ifdef'ed unused code + +2015-09-16 Stéphane Voltz <stef.dev@free.fr> + * backend/pieusb.c: include sane/config.h first + +2015-09-14 Stéphane Voltz <stef.dev@free.fr> + * backend/bh.c: replace mktemp by mkstemp #300134 + +2015-09-13 Paul Newall <p dot newalls at ntlworld dot com> + * backend/kodakaio.c: + redundant variable bitposn and redundant function kodakaio_rxflush + commented out. + +2015-09-09 Stéphane Voltz <stef.dev@free.fr> + * doc/sane-genesys.man, doc/descriptions/genesys.desc: No LiDE 120 + support. + +2015-09-08 m. allan noah <kitno455 at gmail dot com> + * backend/artec_eplus48u.c: fix HOME env bug #315071 (from Jörg Frings-Fürst) + +2015-09-03 Rolf Bensch <rolf at bensch hyphen online dot de> + * backend/pixma_mp810.c: Canon Pixma MP990 needs specific reordering pixels + for 4800 dpi, patch from Guillaume Courtois. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.22 + +2015-08-20 Rolf Bensch <rolf at bensch hyphen online dot de> + * README.linux: add mandatory and optional development environment to + install description + * frontend/scanimage.c: remove atexit() function. In some cases atexit() + doesn't work with libusb-compat. + +2015-08-10 Rolf Bensch <rolf at bensch hyphen online dot de> + * backend/pixma_io_sanei.c: EOF is a bjnp timeout error. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.21 + +2015-08-10 Stéphane Voltz <stef.dev@free.fr> + * backend/abaton.c, backend/agfafocus.c, backend/apple.c, + backend/bh.c, backend/coolscan.c, backend/dmc.c, backend/ricoh.c, + backend/s9036.c, backend/sp15c.[ch], backend/tamarack.c: + fix for memleak in sane_get_devices (bugs #300132 #300131 #300130 #300129 + #300127 #300126 #300124 #300122 #300121 #300120) + +2015-08-10 Klaus Kämpf <kkaempf@suse.com> + * backend/pieusb.c, doc/descriptions/pieusb.desc, doc/sane-pieusb.man, + backend/pieusb_buffer.c, backend/pieusb_scancmd.c, backend/pieusb_specific.c, + backend/pieusb_usb.c: + New scanners PIE PowerSlide 3600,3650,4000,5000 / Reflecta DigitDia 3600, + 4000, 5000, 6000; ProScan 7200; CrystalScan 7200. These scanners need + further testing. + +2015-08-08 Stéphane Voltz <stef.dev@free.fr> + * backend/test.c: fix memleaks (#313553) + * configure.in, configure: don not harcode -I/usr/local/include + (#315060) + + open/close tests. +2015-08-07 Rolf Bensch <rolf at bensch hyphen online dot de> + * README.linux: update development packages list. OpenSuse needs + libusb-compat-devel. Sane doesn't support libusb 1.0. + * backend/pixma_io_sanei.c: EOF isn't an usb timeout error; this fixes usb + communication problems, e.g. with OpenSuse. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.20 + +2015-08-06 Stéphane Voltz <stef.dev@free.fr> + * backend/genesys_devices.c, backend/genesys_gl841.c, backend/genesys_low.c: + fix GPIO setup for LiDE 33/40/50, add more usleep() for GL847 + scanning issues. Some GL841 LEDADD improvements. + +2015-07-31 Stéphane Voltz <stef.dev@free.fr> + * frontend/tstbackend.c: add an option to do tests scans during + open/close tests. + * backend/genesys.c, backend/genesys_low.c: fixes for + - #315104 + - #315105 + And a timing issue on USB3 hardware debugged and tracked by John S. + Weber <jweber53@gmail.com> + +2015-07-29 Rolf Bensch <rolf at bensch hyphen online dot de> + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanner Canon PIXMA MG3600 Series. This scanner needs further testing. + * backend/pixma_mp150.c: Canon PIXMA MG7500 Series doesn't need special + image format post processing. + * doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon PIXMA MG7500 Series is working, reported by Jonathan Anderson. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.19 + +2015-07-24 Rolf Bensch <rolf at bensch hyphen online dot de> + * doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon PIXMA MX470 Series is working, bug #314894. + +2015-06-27 Louis Lagendijk <louis dot lagendijk at gmail dot com> + * backend/pixma_bjnp.c: added missing return in case of no error + +2015-06-27 Louis Lagendijk <louis dot lagendijk at gmail dot com> + * backend/pixma_bjnp.c Added backend version in bjnp debug output + +2015-06-11 Stéphane Voltz <stef.dev@free.fr> + * backend/genesys.c backend/genesys_gl124.h: LiDE 120 support + improvement. + 2015-05-18 Rolf Bensch <rolf at bensch hyphen online dot de> * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: New scanner Canon i-SENSYS MF8300 Series, reported by Florian Nierhaus. diff --git a/Makefile.in b/Makefile.in index bee0461..f2a03a7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -317,6 +317,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -333,6 +334,7 @@ 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_LIBS = @USB_LIBS@ @@ -456,8 +458,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): include/sane/config.h: include/sane/stamp-h1 - @if test ! -f $@; then rm -f include/sane/stamp-h1; else :; fi - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) include/sane/stamp-h1; else :; fi + @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 @@ -687,10 +689,16 @@ dist-xz: distdir $(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) @@ -732,9 +740,10 @@ distcheck: dist && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -1,5 +1,5 @@ -*-Mode: outline-*- -New with 1.0.24, released 2012-09-30: +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. diff --git a/README.linux b/README.linux index 9011b72..6f7aec0 100644 --- a/README.linux +++ b/README.linux @@ -55,8 +55,12 @@ $ make install Step by step install on Linux 2.6.* and 3.*, both with udev: ------------------------------------------------------------ -1. Install missing development packages with your prefered package manager: - - libusb-dev or libusb-devel or libusb-1_0-devel +1. Install with your preferred package manager: + (a) the development environment for your Linux distibution + - mandatory: gcc, make, kernel header files + - optional: git + (b) missing development packages + - libusb-dev or libusb-devel or libusb-compat-devel 2. Get the latest SANE backend from git: You can download "daily git snapshot" from here: diff --git a/acinclude.m4 b/acinclude.m4 index 013c032..06687fc 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -312,6 +312,19 @@ AC_DEFUN([SANE_CHECK_TIFF], 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], @@ -592,14 +605,21 @@ for be in ${BACKENDS}; do mustek_pp) if test "${sane_cv_use_libieee1284}" != "yes" && test "${enable_parport_directio}" != "yes"; then - echo "*** $be backend requires libieee1284 and paraport-directio libraries - $DISABLE_MSG" + 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/or TIFF library - $DISABLE_MSG" + 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 ;; @@ -620,9 +640,9 @@ for be in ${BACKENDS}; do ;; qcam) - if test "${ac_cv_func_ioperm}" = "no" \ + 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 and portaccess functions - $DISABLE_MSG" + echo "*** $be backend requires (ioperm, inb and outb) or portaccess functions - $DISABLE_MSG" backend_supported="no" fi ;; @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.13.4 -*- Autoconf -*- +# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. @@ -232,10 +232,10 @@ m4_popdef([pkg_description]) # 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.13' +[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.13.4], [], +m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -251,7 +251,7 @@ m4_define([_AM_AUTOCONF_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.13.4])dnl +[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]))]) @@ -618,6 +618,12 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # 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]) # ----------------------------------------------- @@ -726,7 +732,48 @@ 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: <http://austingroupbugs.net/view.php?id=542> + +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: <http://www.gnu.org/software/coreutils/>. + +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 @@ -734,7 +781,6 @@ 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. @@ -882,38 +928,6 @@ AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) -# 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. -AC_DEFUN([AM_PROG_CC_C_O], -[AC_REQUIRE([AC_PROG_CC_C_O])dnl -AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([compile])dnl -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != 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 -dnl Make sure AC_PROG_CC is never called again, or it will override our -dnl setting of CC. -m4_define([AC_PROG_CC], - [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) -]) - # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. @@ -984,6 +998,70 @@ AC_DEFUN([_AM_SET_OPTIONS], 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. diff --git a/backend/Makefile.am b/backend/Makefile.am index 40ec6c6..cfa63b1 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -24,7 +24,7 @@ USB_LIBS = @USB_LIBS@ SCSI_LIBS = @SCSI_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ -AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -DLIBDIR="$(libdir)/sane" +AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -DLIBDIR="\"$(libdir)/sane\"" V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ @@ -90,7 +90,7 @@ BACKEND_CONFS= abaton.conf agfafocus.conf apple.conf artec.conf \ matsushita.conf microtek2.conf microtek.conf mustek.conf \ mustek_pp.conf mustek_usb.conf nec.conf net.conf \ p5.conf \ - pie.conf pixma.conf plustek.conf plustek_pp.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 \ @@ -182,7 +182,7 @@ be_convenience_libs = libabaton.la libagfafocus.la \ libmustek.la libmustek_pp.la libmustek_usb.la \ libmustek_usb2.la libnec.la libnet.la \ libniash.la libp5.la \ - libpie.la libpint.la libpixma.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 \ @@ -216,7 +216,7 @@ be_dlopen_libs = libsane-abaton.la libsane-agfafocus.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-pint.la libsane-pixma.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 \ @@ -462,7 +462,7 @@ 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 epson_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_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 @@ -815,6 +815,15 @@ 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 diff --git a/backend/Makefile.in b/backend/Makefile.in index b688e93..8dcb114 100644 --- a/backend/Makefile.in +++ b/backend/Makefile.in @@ -206,7 +206,7 @@ am_libepson_la_OBJECTS = libepson_la-epson.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-epson_usb.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 @@ -333,6 +333,11 @@ 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) @@ -1088,6 +1093,20 @@ 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 @@ -1540,7 +1559,8 @@ SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_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) $(libpint_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) \ @@ -1606,6 +1626,7 @@ SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_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) \ @@ -1674,7 +1695,8 @@ DIST_SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_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) $(libpint_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) \ @@ -1808,6 +1830,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -1824,6 +1847,7 @@ 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_LIBS = @USB_LIBS@ @@ -1887,7 +1911,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -DLIBDIR="$(libdir)/sane" +AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -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 @@ -1962,39 +1986,40 @@ EXTRA_DIST = sane_strstatus.c stubs.c saned.conf.in abaton.conf.in \ 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 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 + 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. @@ -2011,7 +2036,7 @@ BACKEND_CONFS = abaton.conf agfafocus.conf apple.conf artec.conf \ matsushita.conf microtek2.conf microtek.conf mustek.conf \ mustek_pp.conf mustek_usb.conf nec.conf net.conf \ p5.conf \ - pie.conf pixma.conf plustek.conf plustek_pp.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 \ @@ -2051,7 +2076,7 @@ be_convenience_libs = libabaton.la libagfafocus.la \ libmustek.la libmustek_pp.la libmustek_usb.la \ libmustek_usb2.la libnec.la libnet.la \ libniash.la libp5.la \ - libpie.la libpint.la libpixma.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 \ @@ -2086,7 +2111,7 @@ be_dlopen_libs = libsane-abaton.la libsane-agfafocus.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-pint.la libsane-pixma.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 \ @@ -2258,7 +2283,7 @@ 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 epson_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_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 @@ -2486,6 +2511,12 @@ 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 @@ -2988,6 +3019,9 @@ libp5.la: $(libp5_la_OBJECTS) $(libp5_la_DEPENDENCIES) $(EXTRA_libp5_la_DEPENDEN 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) @@ -3198,6 +3232,9 @@ libsane-p5.la: $(libsane_p5_la_OBJECTS) $(libsane_p5_la_DEPENDENCIES) $(EXTRA_li 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) @@ -3381,7 +3418,7 @@ distclean-compile: @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-epson_usb.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@ @@ -3447,6 +3484,11 @@ distclean-compile: @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@ @@ -3527,6 +3569,7 @@ distclean-compile: @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@ @@ -3817,12 +3860,12 @@ libepson2_la-epson2_scsi.lo: epson2_scsi.c @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-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) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson_usb.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson_usb.Tpo -c -o libepson2_la-epson_usb.lo `test -f 'epson_usb.c' || echo '$(srcdir)/'`epson_usb.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson_usb.Tpo $(DEPDIR)/libepson2_la-epson_usb.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson_usb.c' object='libepson2_la-epson_usb.lo' libtool=yes @AMDEPBACKSLASH@ +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-epson_usb.lo `test -f 'epson_usb.c' || echo '$(srcdir)/'`epson_usb.c +@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 @@ -4293,6 +4336,41 @@ libpie_la-pie.lo: pie.c @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 @@ -4846,6 +4924,13 @@ libsane_pie_la-pie-s.lo: pie-s.c @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 diff --git a/backend/abaton.c b/backend/abaton.c index 6187166..4008c62 100644 --- a/backend/abaton.c +++ b/backend/abaton.c @@ -82,6 +82,7 @@ +static const SANE_Device **devlist = 0; static int num_devices; static Abaton_Device *first_dev; static Abaton_Scanner *first_handle; @@ -905,12 +906,14 @@ sane_exit (void) 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) { - static const SANE_Device **devlist = 0; Abaton_Device *dev; int i; diff --git a/backend/agfafocus.c b/backend/agfafocus.c index bc21558..45d103f 100644 --- a/backend/agfafocus.c +++ b/backend/agfafocus.c @@ -51,6 +51,7 @@ #undef Byte #define Byte SANE_Byte +static const SANE_Device **devlist = 0; static int num_devices; static AgfaFocus_Device *agfafocus_devices; @@ -1323,12 +1324,14 @@ sane_exit (void) sane_close (dev->handle); free (dev); } + + if (devlist) + free (devlist); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { - static const SANE_Device **devlist = 0; AgfaFocus_Device *dev; int i; diff --git a/backend/apple.c b/backend/apple.c index 86d5cde..a8e9979 100644 --- a/backend/apple.c +++ b/backend/apple.c @@ -136,6 +136,7 @@ #include "apple.h" +static const SANE_Device **devlist = 0; static int num_devices; static Apple_Device *first_dev; static Apple_Scanner *first_handle; @@ -1921,12 +1922,13 @@ sane_exit (void) 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) { - static const SANE_Device **devlist = 0; Apple_Device *dev; int i; diff --git a/backend/artec.c b/backend/artec.c index 9adaa39..46aa8b6 100644 --- a/backend/artec.c +++ b/backend/artec.c @@ -1305,7 +1305,7 @@ artec_set_scan_window (SANE_Handle handle) { /* top left X value */ /* the select area is flipped across the page, so we have to do some */ - /* calculation here to get the the real starting X value */ + /* 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; diff --git a/backend/artec_eplus48u.c b/backend/artec_eplus48u.c index c26fbb0..bc3b2f8 100644 --- a/backend/artec_eplus48u.c +++ b/backend/artec_eplus48u.c @@ -67,7 +67,7 @@ Updates (C) 2001 by Henning Meier-Geinitz. whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ -#define BUILD 11 +#define BUILD 12 #include "../include/sane/config.h" @@ -3580,6 +3580,14 @@ load_calibration_data (Artec48U_Scanner * s) 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 @@ -3690,6 +3698,14 @@ save_calibration_data (Artec48U_Scanner * s) 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 diff --git a/backend/bh.c b/backend/bh.c index 58c8caa..9424bd6 100644 --- a/backend/bh.c +++ b/backend/bh.c @@ -66,6 +66,7 @@ #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; @@ -1862,10 +1863,9 @@ start_scan (BH_Scanner *s) strncpy(s->barfname, "/tmp/bhXXXXXX", sizeof(s->barfname)); s->barfname[sizeof(s->barfname)-1] = '\0'; + fd = mkstemp(s->barfname); - if ((mktemp(s->barfname) == NULL) && - ((fd = open(s->barfname, O_CREAT | O_EXCL | O_WRONLY, 0600)) != -1) && - ((fp = fdopen(fd, "w")) != NULL)) + if (fd !=-1 && (fp = fdopen(fd, "w")) != NULL) { fprintf(fp, "<xml-stream>\n"); @@ -3231,7 +3231,6 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) SANE_Status sane_get_devices (const SANE_Device ***device_list, SANE_Bool local) { - static const SANE_Device **devlist = 0; BH_Device *dev; int i; DBG(3, "sane_get_devices called\n"); @@ -3879,5 +3878,8 @@ sane_exit (void) next = dev->next; free (dev); } + + if (devlist) + free (devlist); } diff --git a/backend/canon_dr.c b/backend/canon_dr.c index 0b120fa..381cfd6 100644 --- a/backend/canon_dr.c +++ b/backend/canon_dr.c @@ -311,6 +311,11 @@ - 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 + - DR-C125 does not invert_tly, does need sw_lut SANE FLOW DIAGRAM @@ -360,7 +365,7 @@ #include "canon_dr.h" #define DEBUG 1 -#define BUILD 49 +#define BUILD 51 /* values for SANE_DEBUG_CANON_DR env var: - errors 5 @@ -1544,9 +1549,7 @@ init_model (struct scanner *s) s->can_monochrome=0; } - else if (strstr (s->model_name,"DR-C125") - || strstr (s->model_name,"DR-C225") - ){ + else if (strstr (s->model_name,"DR-C125")){ /*confirmed settings*/ s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_2510; @@ -1554,6 +1557,36 @@ init_model (struct scanner *s) 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->can_color = 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; diff --git a/backend/coolscan.c b/backend/coolscan.c index d3c7749..6828a16 100644 --- a/backend/coolscan.c +++ b/backend/coolscan.c @@ -1987,6 +1987,7 @@ static const SANE_Range shift_range = 0 }; +static const SANE_Device **devlist = 0; static int num_devices; static Coolscan_t *first_dev; @@ -3287,6 +3288,9 @@ sane_exit (void) free (dev->obuffer); free (dev); } + + if (devlist) + free (devlist); } /* ----------------------------- SANE GET DEVICES -------------------------- */ @@ -3294,8 +3298,6 @@ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { - - static const SANE_Device **devlist = 0; Coolscan_t *dev; int i; diff --git a/backend/dll.c b/backend/dll.c index 619ee55..5264f11 100644 --- a/backend/dll.c +++ b/backend/dll.c @@ -430,7 +430,7 @@ load (struct backend *be) if (path) { - src_len = strlen (path) + strlen (STRINGIFY (LIBDIR)) + 1 + 1; + src_len = strlen (path) + strlen (LIBDIR) + 1 + 1; src = malloc (src_len); if (!src) { @@ -438,11 +438,11 @@ load (struct backend *be) return SANE_STATUS_NO_MEM; } orig_src = src; - snprintf (src, src_len, "%s:%s", path, STRINGIFY (LIBDIR)); + snprintf (src, src_len, "%s:%s", path, LIBDIR); } else { - src = STRINGIFY (LIBDIR); + src = LIBDIR; src = strdup (src); if (!src) { diff --git a/backend/dmc.c b/backend/dmc.c index 96f9186..7fc2ae9 100644 --- a/backend/dmc.c +++ b/backend/dmc.c @@ -75,6 +75,7 @@ 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", @@ -867,6 +868,9 @@ sane_exit(void) free(dev); dev = next; } + + if (devlist) + free (devlist); } /********************************************************************** @@ -882,7 +886,6 @@ sane_exit(void) SANE_Status sane_get_devices(SANE_Device const ***device_list, SANE_Bool local_only) { - static SANE_Device const **devlist = 0; DMC_Device *dev; int i = 0; diff --git a/backend/epson.c b/backend/epson.c index 3b063b9..6b111f2 100644 --- a/backend/epson.c +++ b/backend/epson.c @@ -2347,7 +2347,7 @@ attach (const char *dev_name, Epson_Device * *devp, int type) /* * Extended status flag request (ESC f). - * this also requests the scanner device name from the the scanner + * this also requests the scanner device name from the scanner */ /* * because we are also using the device name from this command, diff --git a/backend/epson2-ops.c b/backend/epson2-ops.c index 5d8c84d..eac01b0 100644 --- a/backend/epson2-ops.c +++ b/backend/epson2-ops.c @@ -240,6 +240,21 @@ e2_dev_post_init(struct Epson_Device *dev) 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; @@ -581,7 +596,7 @@ e2_discover_capabilities(Epson_Scanner *s) /* * Extended status flag request (ESC f). - * this also requests the scanner device name from the the scanner. + * this also requests the scanner device name from the scanner. * It seems unsupported on the network transport (CX11NF/LP-A500). */ @@ -720,7 +735,7 @@ e2_discover_capabilities(Epson_Scanner *s) } /* TPU2 */ - if (e2_model(s, "GT-X800") || e2_model(s, "GT-X900")) { + 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]), @@ -1272,7 +1287,7 @@ e2_setup_block_mode(Epson_Scanner * s) 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"))) { + 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", diff --git a/backend/epson2.c b/backend/epson2.c index 63ab045..df84b1d 100644 --- a/backend/epson2.c +++ b/backend/epson2.c @@ -990,7 +990,7 @@ init_options(Epson_Scanner *s) 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")) + 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 */ diff --git a/backend/epson2.conf.in b/backend/epson2.conf.in index a996487..797df2d 100644 --- a/backend/epson2.conf.in +++ b/backend/epson2.conf.in @@ -16,7 +16,7 @@ scsi EPSON usb # For libusb support for unknown scanners use the following command -# usb <product ID> <device ID> +# usb <vendor ID> <product ID> # e.g.: # usb 0x4b8 0x110 diff --git a/backend/epson2_usb.c b/backend/epson2_usb.c new file mode 100644 index 0000000..8e29943 --- /dev/null +++ b/backend/epson2_usb.c @@ -0,0 +1,182 @@ +#include <sys/types.h> +#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 <vendor> <product>" */ +}; + +int +sanei_epson_getNumberOfUSBProductIds (void) +{ + return sizeof (sanei_epson_usb_product_ids) / sizeof (SANE_Word); +} diff --git a/backend/epson_usb.c b/backend/epson_usb.c index 8ba8efa..520b49f 100644 --- a/backend/epson_usb.c +++ b/backend/epson_usb.c @@ -2,156 +2,45 @@ #include "../include/sane/sanei_usb.h" #include "epson_usb.h" -/* generated with epson2usb.pl doc/descriptions/epson2.desc */ +/* generated with epson2usb.pl doc/descriptions/epson.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 */ - 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 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 */ - 0x8aa, /* M200 Series */ - 0x8ab, /* WF-M1560 Series */ - 0x8ad, /* LP-M8040, LP-M8040A, LP-M8040F */ - 0x8ae, /* XP-211, XP-212, XP-215 */ - 0x8af, /* XP-310 Series */ - 0x8b0, /* XP-410 Series */ - 0x8b3, /* EP-976A3, XP-950 */ - 0x8b4, /* EP-906F, XP-810 */ - 0x8b5, /* EP-806A, XP-710 */ - 0x8b6, /* EP-776A, XP-610 */ - 0x8b7, /* EP-706A, XP-510 */ + 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 <vendor> <product>" */ }; diff --git a/backend/epsonds-cmd.c b/backend/epsonds-cmd.c index ba80c23..b91f3f1 100644 --- a/backend/epsonds-cmd.c +++ b/backend/epsonds-cmd.c @@ -146,7 +146,7 @@ static SANE_Status esci2_cmd(epsonds_scanner* s, sprintf(rbuf, "%4.4sx%07x", cmd, (unsigned int)plen); - DBG(8, " %s (%d)\n", rbuf, plen); + DBG(8, " %s (%lu)\n", rbuf, plen); eds_send(s, rbuf, 12, &status); @@ -225,9 +225,11 @@ static SANE_Status esci2_cmd_simple(epsonds_scanner* s, char *cmd, SANE_Status ( SANE_Status esci2_fin(epsonds_scanner *s) { + SANE_Status status; + DBG(5, "%s\n", __func__); - SANE_Status status = esci2_cmd_simple(s, "FIN x0000000", NULL); + status = esci2_cmd_simple(s, "FIN x0000000", NULL); s->locked = 0; return status; } @@ -261,6 +263,7 @@ static int decode_value(char *buf, int len) static char *decode_binary(char *buf) { char tmp[6]; + int hl; memcpy(tmp, buf, 4); tmp[4] = '\0'; @@ -268,7 +271,7 @@ static char *decode_binary(char *buf) if (buf[0] != 'h') return NULL; - int hl = strtol(tmp + 1, NULL, 16); + hl = strtol(tmp + 1, NULL, 16); if (hl) { char *v = malloc(hl + 1); @@ -283,12 +286,12 @@ static char *decode_binary(char *buf) static char *decode_string(char *buf) { - char *s = decode_binary(buf); + char *p, *s = decode_binary(buf); if (s == NULL) return NULL; /* trim white space at the end */ - char *p = s + strlen(s); + p = s + strlen(s); while (*--p == ' ') *p = '\0'; @@ -309,13 +312,14 @@ static void debug_token(int level, const char *func, char *token, int len) 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 */ - char *value = token + 3; + value = token + 3; /* nrd / nrdBUSY */ @@ -537,11 +541,11 @@ static SANE_Status info_cb(void *userdata, char *token, int len) SANE_Status esci2_info(epsonds_scanner *s) { - DBG(1, "= gathering device information\n"); - 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) { @@ -800,11 +804,11 @@ static SANE_Status img_cb(void *userdata, char *token, int len) if (strncmp("err", token, 3) == 0) { - s->scanning = 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); @@ -839,6 +843,9 @@ 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; @@ -859,13 +866,13 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length) } /* check if we need to read any image data */ - unsigned int more = 0; + more = 0; if (!esci2_check_header("IMG ", (char *)s->buf, &more)) { return SANE_STATUS_IO_ERROR; } /* this handles eof and errors */ - SANE_Status parse_status = esci2_parse_block((char *)s->buf + 12, 64 - 12, s, &img_cb); + 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. @@ -875,7 +882,7 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length) } /* ALWAYS read image data */ - ssize_t read = eds_recv(s, s->buf, more, &status); + read = eds_recv(s, s->buf, more, &status); if (status != SANE_STATUS_GOOD) { return status; } diff --git a/backend/epsonds-jpeg.c b/backend/epsonds-jpeg.c index d825d99..76a52cb 100644 --- a/backend/epsonds-jpeg.c +++ b/backend/epsonds-jpeg.c @@ -48,16 +48,17 @@ 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 */ - int avail = eds_ring_avail(src->s->current); + avail = eds_ring_avail(src->s->current); if (avail == 0) { return FALSE; } /* read from scanner if no data? */ - int size = min(1024, avail); + size = min(1024, avail); eds_ring_read(src->s->current, src->buffer, size); @@ -129,12 +130,14 @@ eds_jpeg_read_header(epsonds_scanner *s) 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); - int size = s->jpeg_cinfo.output_width * s->jpeg_cinfo.output_components * 1; + 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); @@ -168,11 +171,13 @@ eds_jpeg_read(SANE_Handle handle, SANE_Byte *data, { epsonds_scanner *s = handle; - *length = 0; - 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) { @@ -196,7 +201,7 @@ eds_jpeg_read(SANE_Handle handle, SANE_Byte *data, * only one line at time is supported */ - int l = jpeg_read_scanlines(&cinfo, s->jdst->buffer, 1); + l = jpeg_read_scanlines(&cinfo, s->jdst->buffer, 1); if (l == 0) { return; } diff --git a/backend/epsonds-ops.c b/backend/epsonds-ops.c index 94f1071..403cd58 100644 --- a/backend/epsonds-ops.c +++ b/backend/epsonds-ops.c @@ -48,9 +48,10 @@ eds_dev_init(epsonds_device *dev) SANE_Status eds_dev_post_init(struct epsonds_device *dev) { + SANE_String_Const *source_list_add = source_list; + DBG(10, "%s\n", __func__); - SANE_String_Const *source_list_add = source_list; if (dev->has_fb) *source_list_add++ = FBF_STR; @@ -337,12 +338,13 @@ eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_lengt 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); - int i; - - SANE_Byte *p = s->line_buffer; + p = s->line_buffer; for (i = 0; i < s->params.bytes_per_line; i++) { *data++ = ~*p++; @@ -379,12 +381,14 @@ SANE_Status eds_ring_init(ring_buffer *ring, SANE_Int size) 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; } - SANE_Int tail = ring->end - ring->wp; + tail = ring->end - ring->wp; if (size < tail) { memcpy(ring->wp, buf, size); @@ -409,6 +413,8 @@ SANE_Status eds_ring_write(ring_buffer *ring, SANE_Byte *buf, SANE_Int size) 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 */ @@ -417,7 +423,7 @@ SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size) size = ring->fill; } - SANE_Int tail = ring->end - ring->rp; + tail = ring->end - ring->rp; if (size < tail) { memcpy(buf, ring->rp, size); @@ -444,11 +450,12 @@ SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size) 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; - SANE_Int tail = ring->end - ring->rp; + tail = ring->end - ring->rp; if (size < tail) { ring->rp += size; } else { diff --git a/backend/epsonds.c b/backend/epsonds.c index 8db070b..2f85312 100644 --- a/backend/epsonds.c +++ b/backend/epsonds.c @@ -330,10 +330,11 @@ 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); - epsonds_scanner *s = device_detect(name, type, &status); + s = device_detect(name, type, &status); if (s == NULL) return status; @@ -1041,6 +1042,7 @@ sane_start(SANE_Handle handle) { epsonds_scanner *s = (epsonds_scanner *)handle; char buf[64]; + char cmd[100]; /* take care not to overflow */ SANE_Status status = 0; s->pages++; @@ -1103,8 +1105,6 @@ sane_start(SANE_Handle handle) /* set scanning parameters */ - char cmd[100]; /* take care not to overflow */ - /* document source */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { @@ -1194,6 +1194,7 @@ 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; @@ -1208,7 +1209,7 @@ sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, } /* anything in the buffer? pass it to the frontend */ - SANE_Int available = eds_ring_avail(s->current); + available = eds_ring_avail(s->current); if (available) { DBG(18, "reading from ring buffer, %d left\n", available); diff --git a/backend/epsonds.conf.in b/backend/epsonds.conf.in index bd032f3..23dc461 100644 --- a/backend/epsonds.conf.in +++ b/backend/epsonds.conf.in @@ -6,7 +6,7 @@ usb # For libusb support for unknown scanners use the following command -# usb <product ID> <device ID> +# usb <vendor ID> <product ID> # e.g.: # usb 0x4b8 0x14c diff --git a/backend/fujitsu.c b/backend/fujitsu.c index 7f008d0..9fddb1c 100644 --- a/backend/fujitsu.c +++ b/backend/fujitsu.c @@ -571,6 +571,12 @@ - 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 + - separate iX100 from iX500 settings + - iX100 has gray and lineart SANE FLOW DIAGRAM @@ -620,7 +626,7 @@ #include "fujitsu.h" #define DEBUG 1 -#define BUILD 125 +#define BUILD 127 /* values for SANE_DEBUG_FUJITSU env var: - errors 5 @@ -2271,6 +2277,7 @@ init_model (struct fujitsu *s) /* 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; @@ -2287,6 +2294,26 @@ init_model (struct fujitsu *s) 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")){ @@ -6899,6 +6926,13 @@ sane_start (SANE_Handle handle) 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 */ + if (!s->late_lut && (!s->brightness_steps || !s->contrast_steps)){ + 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) { @@ -6907,10 +6941,10 @@ sane_start (SANE_Handle handle) } /* send lut if scanner has no hardware brightness/contrast */ - if (!s->brightness_steps || !s->contrast_steps){ + if (s->late_lut && (!s->brightness_steps || !s->contrast_steps)){ ret = send_lut(s); if (ret != SANE_STATUS_GOOD) - DBG (5, "sane_start: WARNING: cannot send_lut %d\n", ret); + DBG (5, "sane_start: WARNING: cannot late send_lut %d\n", ret); } /* some scanners need the q table sent, even when not scanning jpeg */ diff --git a/backend/fujitsu.conf.in b/backend/fujitsu.conf.in index dc7a131..b3895ea 100644 --- a/backend/fujitsu.conf.in +++ b/backend/fujitsu.conf.in @@ -139,6 +139,9 @@ usb 0x04c5 0x11fc #fi-5950 usb 0x04c5 0x1213 +#ScanSnap SV600 +usb 0x04c5 0x128e + #ScanSnap iX500 usb 0x04c5 0x132b @@ -153,3 +156,7 @@ usb 0x04c5 0x132e #fi-7260 usb 0x04c5 0x132f + +#ScanSnap iX100 +usb 0x04c5 0x13f4 + diff --git a/backend/fujitsu.h b/backend/fujitsu.h index e1f7d68..6ce1a56 100644 --- a/backend/fujitsu.h +++ b/backend/fujitsu.h @@ -332,6 +332,7 @@ struct fujitsu 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 */ diff --git a/backend/genesys.c b/backend/genesys.c index 548d0da..984cead 100644 --- a/backend/genesys.c +++ b/backend/genesys.c @@ -2,7 +2,7 @@ Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de> Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de> - Copyright (C) 2004-2013 Stéphane Voltz <stef.dev@free.fr> + Copyright (C) 2004-2015 Stéphane Voltz <stef.dev@free.fr> Copyright (C) 2005-2009 Pierre Willenbrock <pierre@pirsoft.dnsalias.org> Copyright (C) 2006 Laurent Charpentier <laurent_pubs@yahoo.com> Copyright (C) 2007 Luke <iceyfor@gmail.com> @@ -58,7 +58,7 @@ * SANE backend for Genesys Logic GL646/GL841/GL842/GL843/GL846/GL847/GL124 based scanners */ -#define BUILD 2506 +#define BUILD 2508 #define BACKEND_NAME genesys #include "genesys.h" @@ -744,7 +744,7 @@ sanei_genesys_create_gamma_table (uint16_t * gamma_table, int size, if(gamma_table==NULL) { - DBG (DBG_proc, "sanei_genesys_create_gamma_table: gamma tbale is NULL\n"); + DBG (DBG_proc, "sanei_genesys_create_gamma_table: gamma table is NULL\n"); return; } DBG (DBG_proc, @@ -3890,7 +3890,7 @@ genesys_warmup_lamp (Genesys_Device * dev) { first_average /= pixel; second_average /= pixel; - difference = abs (first_average - second_average); + difference = fabs (first_average - second_average); DBG (DBG_info, "genesys_warmup_lamp: average = %.2f, diff = %.3f\n", 100 * ((second_average) / (256 * 256)), @@ -3917,7 +3917,7 @@ genesys_warmup_lamp (Genesys_Device * dev) } 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 (abs (first_average - second_average) < 15 + if (fabs (first_average - second_average) < 15 && second_average > 55) break; } @@ -5749,7 +5749,7 @@ init_options (Genesys_Scanner * s) 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; + 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 */ @@ -5914,8 +5914,8 @@ init_options (Genesys_Scanner * s) /* 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 used. A negative value means cache never expires."); + 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; diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c index 4358e94..775ffb6 100644 --- a/backend/genesys_devices.c +++ b/backend/genesys_devices.c @@ -880,7 +880,7 @@ static Genesys_Gpo Gpo[] = { , /* CANONLIDE35 */ {GPO_CANONLIDE35, - {0x12, 0x80} + {0x02, 0x80} , {0xef, 0x80} , diff --git a/backend/genesys_gl124.h b/backend/genesys_gl124.h index ae8016c..25f99c3 100644 --- a/backend/genesys_gl124.h +++ b/backend/genesys_gl124.h @@ -621,9 +621,9 @@ static Sensor_Profile sensors[]={ {CIS_CANONLIDE110, 2400, 0, 20864, 0x1e, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24}, /* LiDE 120 */ - {CIS_CANONLIDE120, 600, 1, 2768, 0x0f, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21}, - {CIS_CANONLIDE120, 600, 0, 5360, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21}, - {CIS_CANONLIDE120, 1200, 0, 10528, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22}, + {CIS_CANONLIDE120, 600, 1, 2768, 0x0f, 0x9f, 0x55, 2552, 112, 94, 388, 574, 393, NULL , 0x00, 0x02, 0x20, 0x21}, + {CIS_CANONLIDE120, 600, 0, 5360, 0x0f, 0x9f, 0x55, 5168, 163, 94, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21}, + {CIS_CANONLIDE120, 1200, 0, 10528, 0x0f, 0x9f, 0x55, 5168, 163, 94, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22}, {CIS_CANONLIDE120, 2400, 0, 20864, 0x0f, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24}, /* LiDE 210 */ diff --git a/backend/genesys_gl841.c b/backend/genesys_gl841.c index 318def8..2b16c67 100644 --- a/backend/genesys_gl841.c +++ b/backend/genesys_gl841.c @@ -2381,56 +2381,60 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, /* AFEMOD should depend on FESET, and we should set these * bits separately */ r->value &= ~(REG04_FILTER | REG04_AFEMOD); - if (channels == 1) + 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 - { + { + 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 + 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_EXPG,&expb); - - /* use minimal expousre 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); + 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 */ @@ -2451,7 +2455,7 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, sanei_genesys_set_double(reg, REG_ENDPIXEL, end); DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d\n",__FUNCTION__,start,end); -/* words(16bit) before gamma, conversion to 8 bit or lineart*/ + /* words(16bit) before gamma, conversion to 8 bit or lineart*/ words_per_line = (pixels * dpiset) / gl841_get_dpihw(dev); words_per_line *= channels; @@ -4487,6 +4491,7 @@ gl841_init_regs_for_scan (Genesys_Device * dev) if(dev->model->is_cis && dev->settings.true_gray && dev->settings.scan_mode != SCAN_MODE_COLOR) { + DBG (DBG_io, "%s: activating LEDADD\n", __FUNCTION__); flags |= SCAN_FLAG_ENABLE_LEDADD; } diff --git a/backend/genesys_low.c b/backend/genesys_low.c index 0af2149..f28b72c 100644 --- a/backend/genesys_low.c +++ b/backend/genesys_low.c @@ -943,13 +943,18 @@ sanei_genesys_get_triple(Genesys_Register_Set *regs, uint16_t addr, uint32_t *va return SANE_STATUS_GOOD; } -/* Checks if the scan buffer is empty */ +/** @brief Check if the scanner's internal data buffer is empty + * @param *dev device to test for data + * @param *empty return value + * @return empty will be set to SANE_TRUE if there is no scanned data. + **/ SANE_Status sanei_genesys_test_buffer_empty (Genesys_Device * dev, SANE_Bool * empty) { uint8_t val = 0; SANE_Status status; + usleep(1000); status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { @@ -961,6 +966,10 @@ sanei_genesys_test_buffer_empty (Genesys_Device * dev, SANE_Bool * empty) if (dev->model->cmd_set->test_buffer_empty_bit (val)) { + /* fix timing issue on USB3 (or just may be too fast) hardware + * spotted by John S. Weber <jweber53@gmail.com> + */ + usleep(1000); DBG (DBG_io2, "sanei_genesys_test_buffer_empty: buffer is empty\n"); *empty = SANE_TRUE; return SANE_STATUS_GOOD; @@ -1317,10 +1326,14 @@ sanei_genesys_send_gamma_table (Genesys_Device * dev) } /** @brief initialize device - * initialize backend and ASIC : registers, motor tables, and gamma tables - * then ensure scanner's head is at home. Designed for gl846+ ASICs + * Initialize backend and ASIC : registers, motor tables, and gamma tables + * then ensure scanner's head is at home. Designed for gl846+ ASICs. + * Detects cold boot (ie first boot since device plugged) in this case + * an extensice setup up is done at hardware level. + * * @param dev device to initialize * @param max_regs umber of maximum used registers + * @return SANE_STATUS_GOOD in case of success */ SANE_Status sanei_genesys_asic_init (Genesys_Device * dev, int max_regs) @@ -1328,7 +1341,8 @@ sanei_genesys_asic_init (Genesys_Device * dev, int max_regs) SANE_Status status; uint8_t val; SANE_Bool cold = SANE_TRUE; - int size, i; + int size; /**< size of the device's gamma table */ + int i; DBGSTART; @@ -1354,6 +1368,25 @@ sanei_genesys_asic_init (Genesys_Device * dev, int max_regs) } } + /* setup gamma tables */ + size = 256; + for(i=0;i<3;i++) + { + FREE_IFNOT_NULL (dev->sensor.gamma_table[i]); + dev->sensor.gamma_table[i] = (uint16_t *) malloc (2 * size); + if (dev->sensor.gamma_table[i] == NULL) + { + DBG (DBG_error, "%s: could not allocate memory for gamma table %d\n", + __FUNCTION__, i); + return SANE_STATUS_NO_MEM; + } + sanei_genesys_create_gamma_table (dev->sensor.gamma_table[i], + size, + 65535, + 65535, + dev->sensor.gamma[i]); + } + /* check if the device has already been initialized and powered up * we read register 6 and check PWRBIT, if reset scanner has been * freshly powered up. This bit will be set to later so that following @@ -1380,9 +1413,6 @@ sanei_genesys_asic_init (Genesys_Device * dev, int max_regs) /* now hardware part is OK, set up device struct */ FREE_IFNOT_NULL (dev->white_average_data); FREE_IFNOT_NULL (dev->dark_average_data); - FREE_IFNOT_NULL (dev->sensor.gamma_table[0]); - FREE_IFNOT_NULL (dev->sensor.gamma_table[1]); - FREE_IFNOT_NULL (dev->sensor.gamma_table[2]); dev->settings.color_filter = 0; @@ -1392,28 +1422,6 @@ sanei_genesys_asic_init (Genesys_Device * dev, int max_regs) /* Set analog frontend */ RIE (dev->model->cmd_set->set_fe (dev, AFE_INIT)); - /* init 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, "%s: could not allocate memory for gamma table %d\n", - __FUNCTION__, i); - return SANE_STATUS_NO_MEM; - } - sanei_genesys_create_gamma_table (dev->sensor.gamma_table[i], - size, - 65535, - 65535, - dev->sensor.gamma[i]); - } - } - dev->oe_buffer.buffer = NULL; dev->already_initialized = SANE_TRUE; diff --git a/backend/hs2p-scsi.c b/backend/hs2p-scsi.c index 82640e9..a14e6cb 100644 --- a/backend/hs2p-scsi.c +++ b/backend/hs2p-scsi.c @@ -1283,9 +1283,9 @@ hs2p_send_gamma (HS2P_Scanner * s) _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 = 2; i < 2 + GAMMA_LENGTH; i++) + for (i = 0; i < GAMMA_LENGTH; i++) { - out.gamma[i] = s->gamma_table[i]; + out.gamma[i + 2] = s->gamma_table[i]; } status = sanei_scsi_cmd (s->fd, &out, sizeof (out), NULL, NULL); diff --git a/backend/ibm.c b/backend/ibm.c index 729c140..3ab7890 100644 --- a/backend/ibm.c +++ b/backend/ibm.c @@ -248,11 +248,13 @@ attach (const char *devnam, Ibm_Device ** devp) dev->sane.name = strdup (devnam); dev->sane.vendor = "IBM"; - str = malloc (16 + 1); - memset (str, 0, sizeof (str)); - strncpy (str, (char *)ibuf.product, sizeof(ibuf.product)); - strncpy (str + sizeof(ibuf.revision), (char *)ibuf.revision, sizeof(ibuf.revision)); - str[sizeof(ibuf.product) + sizeof(ibuf.revision)] = '\0'; + 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"; diff --git a/backend/kodakaio.c b/backend/kodakaio.c index e98208f..42b59a5 100644 --- a/backend/kodakaio.c +++ b/backend/kodakaio.c @@ -240,7 +240,7 @@ 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; /* used to pack bits into bytes in lineart mode */ +/* 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 */ @@ -632,7 +632,7 @@ static SANE_String_Const source_list[] = { }; 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}; +/*static const SANE_Range percent_range_int = {0, 100, 1};*/ /* prototypes */ static SANE_Status attach_one_usb(SANE_String_Const devname); @@ -719,7 +719,7 @@ That is probably if the scanner disconnected the network connection } else if((fds[0].revents & POLLIN) && !(fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))) { while (read < wanted) { - DBG(50, "reading: read %d, wanted %d\n",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"); @@ -1029,12 +1029,13 @@ and returns appropriate status 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]; @@ -1047,6 +1048,7 @@ and returns number of bytes read DBG(5, "%s: flushed, %d bytes\n", __func__, (int)n); return n; } +*/ /* * high-level communication commands diff --git a/backend/lexmark_low.c b/backend/lexmark_low.c index ae0db2c..821b621 100644 --- a/backend/lexmark_low.c +++ b/backend/lexmark_low.c @@ -1965,7 +1965,7 @@ sanei_lexmark_low_search_home_bwd (Lexmark_Device * dev) 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 the size of the data available from the scanner. + 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 diff --git a/backend/magicolor.c b/backend/magicolor.c index e3cd80d..660f517 100644 --- a/backend/magicolor.c +++ b/backend/magicolor.c @@ -103,7 +103,8 @@ * | | | | | | | | | | | | | | | */ static struct MagicolorCmd magicolor_cmd[] = { - {"mc1690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03} + {"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}; @@ -121,7 +122,20 @@ static struct MagicolorCap magicolor_cap[] = { {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}, + }, }; @@ -373,6 +387,7 @@ sanei_magicolor_net_close(struct Magicolor_Scanner *s) 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 <vendor> <product>" */ }; @@ -1176,7 +1191,12 @@ mc_set_scanning_parameters(Magicolor_Scanner * s) /* ADF used? */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { /* Use ADF */ - source = 0x01; + if (s->val[OPT_ADF_MODE].w == 0) { + source = 0x01; + } else { + /* Use duplex */ + source = 0x02; + } } else { source = 0x00; } @@ -1670,6 +1690,7 @@ detect_usb(struct Magicolor_Scanner *s) DBG(2, "found valid Magicolor scanner: 0x%x/0x%x (vendorID/productID)\n", vendor, product); + mc_set_device(s, product); return SANE_STATUS_GOOD; } diff --git a/backend/microtek2.c b/backend/microtek2.c index d56e568..f21789b 100644 --- a/backend/microtek2.c +++ b/backend/microtek2.c @@ -4013,7 +4013,7 @@ get_scan_mode_and_depth(Microtek2_Scanner *ms, /* 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 the scanner, bits_perpixel_out is the */ + /* 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 */ diff --git a/backend/mustek_pp_cis.c b/backend/mustek_pp_cis.c index 026734f..d5ef86d 100644 --- a/backend/mustek_pp_cis.c +++ b/backend/mustek_pp_cis.c @@ -2086,7 +2086,7 @@ cis_calibrate (Mustek_PP_CIS_dev * dev) * 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 the width of the black border is then being + * 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. * diff --git a/backend/net.c b/backend/net.c index 16fba2f..a3ebded 100644 --- a/backend/net.c +++ b/backend/net.c @@ -140,7 +140,7 @@ static int hang_over; 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 the correct byte order, but could not be returned, + 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; diff --git a/backend/niash.c b/backend/niash.c index 7bc8a25..950df21 100644 --- a/backend/niash.c +++ b/backend/niash.c @@ -81,15 +81,14 @@ typedef enum optGroupEnhancement, optThreshold, - - optLast, -/* put temporarily disabled options here after optLast */ - +#ifdef EXPERIMENTAL optGroupMisc, optLamp, optCalibrate, - optGamma /* analog gamma = single number */ + optGamma, /* analog gamma = single number */ +#endif + optLast } EOptionIndex; @@ -150,10 +149,12 @@ 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 */ @@ -260,18 +261,15 @@ _bytesPerLineColor (int pixelsPerLine) /* dummy*/ static void -_rgb2rgb (unsigned char *buffer, int pixels, int threshold) +_rgb2rgb (unsigned char __sane_unused__ *buffer, int __sane_unused__ pixels, int __sane_unused__ threshold) { /* make the compiler content */ - buffer = buffer; - pixels = pixels; - threshold = threshold; } /* convert 24bit RGB to 8bit GRAY */ static void -_rgb2gray (unsigned char *buffer, int pixels, int threshold) +_rgb2gray (unsigned char *buffer, int pixels, int __sane_unused__ threshold) { #define WEIGHT_R 27 #define WEIGHT_G 54 @@ -283,9 +281,6 @@ _rgb2gray (unsigned char *buffer, int pixels, int threshold) int acc = 0; int x; - /* make the compiler content */ - threshold = threshold; - for (x = 0; x < nbyte; ++x) { acc += aWeight[x % BYTES_PER_PIXEL_COLOR] * buffer[x]; @@ -685,6 +680,7 @@ _InitOptions (TScanner * s) pDesc->size = 0; break; +#ifdef EXPERIMENTAL case optGamma: pDesc->name = SANE_NAME_ANALOG_GAMMA; pDesc->title = SANE_TITLE_ANALOG_GAMMA; @@ -695,6 +691,7 @@ _InitOptions (TScanner * s) pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = startUpGamma; break; +#endif case optGammaTable: pDesc->name = SANE_NAME_GAMMA_VECTOR; @@ -707,6 +704,7 @@ _InitOptions (TScanner * s) pVal->wa = s->aGammaTable; break; +#ifdef EXPERIMENTAL case optGroupMisc: pDesc->title = SANE_I18N ("Miscellaneous"); pDesc->type = SANE_TYPE_GROUP; @@ -731,7 +729,7 @@ _InitOptions (TScanner * s) pDesc->cap = SANE_CAP_SOFT_SELECT; pDesc->size = 0; break; - +#endif case optGroupMode: pDesc->title = SANE_I18N ("Scan Mode"); pDesc->desc = ""; @@ -824,11 +822,8 @@ _ReportDevice (TScannerModel * pModel, const char *pszDeviceName) /*****************************************************************************/ SANE_Status -sane_init (SANE_Int * piVersion, SANE_Auth_Callback pfnAuth) +sane_init (SANE_Int * piVersion, SANE_Auth_Callback __sane_unused__ pfnAuth) { - /* prevent compiler from complaing about unused parameters */ - pfnAuth = pfnAuth; - DBG_INIT (); DBG (DBG_MSG, "sane_init\n"); @@ -869,15 +864,13 @@ sane_exit (void) SANE_Status -sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) +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"); - local_only = local_only; - if (_pSaneDevList) { free (_pSaneDevList); @@ -984,17 +977,32 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, void *pVal, SANE_Int * pInfo) { TScanner *s; - SANE_Bool fVal; static char szTable[100]; int *pi; int i; SANE_Int info; - SANE_Bool fLampIsOn; 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; @@ -1007,7 +1015,9 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, /* Get options of type SANE_Word */ case optCount: case optDPI: +#ifdef EXPERIMENTAL case optGamma: +#endif case optTLX: case optTLY: case optBRX: @@ -1031,6 +1041,7 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, strcpy ((char *) pVal, modeList[s->aValues[optMode].w]); break; +#ifdef EXPERIMENTAL /* Get options of type SANE_Bool */ case optLamp: GetLamp (&s->HWParams, &fLampIsOn); @@ -1041,6 +1052,7 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, /* 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); @@ -1061,7 +1073,9 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, case optCount: return SANE_STATUS_INVAL; +#ifdef EXPERIMENTAL case optGamma: +#endif case optThreshold: case optDPI: @@ -1081,14 +1095,17 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, 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) @@ -1097,6 +1114,7 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, } _SetScalarGamma (s->aGammaTable, s->aValues[n].w); } +#endif break; case optGammaTable: @@ -1159,6 +1177,7 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, +#ifdef EXPERIMENTAL case optLamp: fVal = *(SANE_Bool *) pVal; DBG (DBG_MSG, "lamp %s\n", fVal ? "on" : "off"); @@ -1171,6 +1190,7 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, case optCalibrate: /* SimpleCalib(&s->HWParams); */ break; +#endif default: DBG (DBG_ERR, "SANE_ACTION_SET_VALUE: Invalid option (%d)\n", n); @@ -1458,13 +1478,10 @@ sane_cancel (SANE_Handle h) SANE_Status -sane_set_io_mode (SANE_Handle h, SANE_Bool m) +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"); - /* prevent compiler from complaining about unused parameters */ - h = h; - if (m) { return SANE_STATUS_UNSUPPORTED; @@ -1474,13 +1491,8 @@ sane_set_io_mode (SANE_Handle h, SANE_Bool m) SANE_Status -sane_get_select_fd (SANE_Handle h, SANE_Int * fd) +sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int * __sane_unused__ fd) { DBG (DBG_MSG, "sane_select_fd\n"); - - /* prevent compiler from complaining about unused parameters */ - h = h; - fd = fd; - return SANE_STATUS_UNSUPPORTED; } diff --git a/backend/pieusb.c b/backend/pieusb.c new file mode 100644 index 0000000..4b07304 --- /dev/null +++ b/backend/pieusb.c @@ -0,0 +1,1422 @@ +/* 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 <stdio.h> /* for FILE */ +#include <string.h> /* for strlen */ +#include <stdlib.h> /* for NULL */ +#include <stdint.h> +#include <math.h> + +/* 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 */ + +/* -------------------------------------------------------------------------- + * + * 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_Word model_number; + 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; + /* 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; + /* Reflecta 6000 Multiple Slide Scanner */ + pieusb_supported_usb_device_list[2].vendor = 0x05e3; + pieusb_supported_usb_device_list[2].product = 0x0142; + pieusb_supported_usb_device_list[2].model = 0x3a; + /* 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; + + /* 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); + if (status == SANE_STATUS_GOOD) { + DBG (DBG_info_sane, "sane_init() config file lists device %04x %04x %02x\n",vendor_id, product_id, model_number); + if (!sanei_pieusb_supported_device_list_contains(vendor_id, product_id, model_number)) { + DBG (DBG_info_sane, "sane_init() adding device %04x %04x %02x\n",vendor_id, product_id, model_number); + sanei_pieusb_supported_device_list_add(vendor_id, product_id, model_number); + } else { + DBG (DBG_info_sane, "sane_init() list already contains %04x %04x %02x\n", vendor_id, product_id, model_number); + } + } 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.device_number = -1; /* No device number (yet) */ + DBG( DBG_info_sane, "sane_init() looking for Reflecta scanner %04x %04x model %02x\n", pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product, pieusb_supported_usb_device.model); + 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.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 + * + * ---------------------------------------------------------------------- */ + + 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; + } + + /* ---------------------------------------------------------------------- + * + * Lamp on + * + * ---------------------------------------------------------------------- */ + sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_LAMP_ON, &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->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; +} diff --git a/backend/pieusb.conf.in b/backend/pieusb.conf.in new file mode 100644 index 0000000..ec5ba7e --- /dev/null +++ b/backend/pieusb.conf.in @@ -0,0 +1,9 @@ +# pieusb.conf: Configuration file for PIE/Reflecta USB scanner +# Read man sane-pieusb for documentation + +# Autodetect +# Reflecta 6000 Multiple Slide Scanner +usb 0x05e3 0x0142 +# Reflecta CrystalScan 7200 +# Reflecta ProScan 7200 +usb 0x05e3 0x0145 diff --git a/backend/pieusb.h b/backend/pieusb.h new file mode 100644 index 0000000..10ce106 --- /dev/null +++ b/backend/pieusb.h @@ -0,0 +1,105 @@ +/* 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#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 */ +}; + +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 */ diff --git a/backend/pieusb_buffer.c b/backend/pieusb_buffer.c new file mode 100644 index 0000000..53bd867 --- /dev/null +++ b/backend/pieusb_buffer.c @@ -0,0 +1,644 @@ +/* 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 <alloca.h> +#endif + +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <endian.h> + +/* When creating the release backend, make complains about unresolved external + * le16toh, although it finds the include <endian.h> */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + #define le16toh(x) (x) +#else + #define le16toh(x) __bswap_16 (x) +#endif + +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 = mkostemp(buffer->buffer_name, O_RDWR | O_CREAT | O_EXCL | O_TRUNC); + 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 diff --git a/backend/pieusb_buffer.h b/backend/pieusb_buffer.h new file mode 100644 index 0000000..3724a40 --- /dev/null +++ b/backend/pieusb_buffer.h @@ -0,0 +1,93 @@ +/* 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 */ diff --git a/backend/pieusb_scancmd.c b/backend/pieusb_scancmd.c new file mode 100644 index 0000000..a86f8fe --- /dev/null +++ b/backend/pieusb_scancmd.c @@ -0,0 +1,1329 @@ +/* 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 <alloca.h> +#endif + +#include <time.h> /* 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<count; k++) { + *dst++ = *src++; + } +} + + +/* + * Get count unsigned short values in the array at given offset. + * All data in structures is little-endian, so the MSB comes first. + * SANE_Word is 4 bytes, but that is not a problem. + */ +static void +_get_shorts(SANE_Word* dst, SANE_Byte* src, SANE_Byte count) { + SANE_Byte k; + for (k=0; k<count; k++) { + *dst = *(src+2*k+1); + *dst <<= 8; + *dst++ += *(src+2*k); + } +} + +/* + * Copy an unsigned short array of given size + * All data in structures is little-endian, so start with MSB of each short. + * SANE_Word is 4 bytes, but that is not a problem. All MSB 2 bytes are ignored. + */ +static void +_set_shorts(SANE_Word* src, SANE_Byte* dst, SANE_Byte count) { + SANE_Byte k; + for (k=0; k<count; k++) { + *(dst+2*k) = *src & 0xFF; + *(dst+2*k+1) = ((*src++)>>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_LAMP_ON, 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 halftone pattern 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 index index of halftone pattern + * @param pattern Halftone pattern (not implemented) + * @return Pieusb_Command_Status + * @see Pieusb_Halftone_Pattern + */ +void +sanei_pieusb_cmd_get_halftone_pattern(SANE_Int device_number, SANE_Int index, struct Pieusb_Halftone_Pattern* pattern, struct Pieusb_Command_Status *status) +{ + SANE_Byte command[SCSI_COMMAND_LEN]; +#define PATTERN_SIZE 256 /* Assumed maximum pattern size */ + SANE_Int size = PATTERN_SIZE; + SANE_Byte data[PATTERN_SIZE]; + int psize; + SANE_Char* desc; + PIEUSB_Status st; + + DBG (DBG_info_scan, "sanei_pieusb_cmd_get_halftone_pattern()\n"); + + /* Ask scanner to prepare the pattern 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_HALFTONE_PATTERN | 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 pattern */ + _prep_scsi_cmd(command, SCSI_READ, size); + + memset(data, '\0', size); + status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); + + /*FIXME: analyse */ + fprintf(stderr, "Halftone pattern %d:\n", index); + psize = (data[3]<<8) + data[2]; + desc = (SANE_Char*)(data + 4 + psize); + data[4 + psize + 16] = '\0'; + fprintf(stderr,"Descr. offset from byte 4 = %d, %16s, index = %d, size = %dx%d\n", psize, desc, data[4]&0x7F, data[6], data[7]); +#undef PATTERN_SIZE +} + +/** + * 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 relative exposure time for the specified colorbits. This requires two + * commands, one to ask the device to prepare the value, and one to read it. + * + * @param device_number Device number + * @param time Relative exposure time(s) + * @return Pieusb_Command_Status + * @see Pieusb_Exposure_Time + */ +void +sanei_pieusb_cmd_get_exposure_time(SANE_Int device_number, SANE_Int colorbits, struct Pieusb_Exposure_Time* time, struct Pieusb_Command_Status *status) +{ + DBG (DBG_info_scan, "sanei_pieusb_cmd_get_exposure_time(): not implemented\n"); + status->pieusb_status = PIEUSB_STATUS_INVAL; +} + +/** + * Read the highlight and shadow levels with the specified colorbits. This requires two + * commands, one to ask the device to prepare the value, and one to read it. + * + * @param device_number Device number + * @param hgltshdw Highlight and shadow level(s) + * @return Pieusb_Command_Status + * @see Pieusb_Highlight_Shadow + */ +void +sanei_pieusb_cmd_get_highlight_shadow(SANE_Int device_number, SANE_Int colorbits, struct Pieusb_Highlight_Shadow* hgltshdw, struct Pieusb_Command_Status *status) +{ + DBG (DBG_info_scan, "sanei_pieusb_cmd_get_highlight_shadow(): not implemented\n"); + status->pieusb_status = PIEUSB_STATUS_INVAL; +} + +/** + * 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 halftone pattern with the given index to the specified pattern. The + * command is a SCSI WRITE command (code 0x0A, write code 0x11). + * + * @param device_number Device number + * @param index Pattern index (0-7) + * @param pattern Halftone pattern (not implemented) + * @return Pieusb_Command_Status + * @see Pieusb_Halftone_Pattern + */ +void +sanei_pieusb_cmd_set_halftone_pattern(SANE_Int device_number, SANE_Int index, struct Pieusb_Halftone_Pattern* pattern, struct Pieusb_Command_Status *status) +{ + DBG (DBG_info_scan, "sanei_pieusb_cmd_set_halftone_pattern(): not implemented\n"); + status->pieusb_status = PIEUSB_STATUS_INVAL; +} + +/** + * 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 +} + +/** + * Set the CCD-mask for the colors set in the given color bit mask. The mask + * array must contain mask_size. The command is a SCSI WRITE command + * (code 0x0A, write code 0x16). + * (The command is able to handle more masks at once, but that is not implemented.) + * + * @param device_number Device number + * @param colorbits 0000RGB0 color bit mask; at least one color bit must be set + * @param mask CCD mask to use + * @return Pieusb_Command_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) +{ + DBG (DBG_info_scan, "sanei_pieusb_cmd_set_ccd_mask(): not implemented\n"); + status->pieusb_status = PIEUSB_STATUS_INVAL; +} + +/* 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; +} diff --git a/backend/pieusb_scancmd.h b/backend/pieusb_scancmd.h new file mode 100644 index 0000000..0dee646 --- /dev/null +++ b/backend/pieusb_scancmd.h @@ -0,0 +1,378 @@ +/* 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_LAMP_ON = 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 */ diff --git a/backend/pieusb_specific.c b/backend/pieusb_specific.c new file mode 100644 index 0000000..8231075 --- /dev/null +++ b/backend/pieusb_specific.c @@ -0,0 +1,2509 @@ +/* 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 <stdlib.h> +#include <unistd.h> +#include <string.h> +#include "../include/sane/sane.h" +#include "../include/sane/saneopts.h" +#include "../include/sane/sanei_config.h" + +#include <errno.h> +#include <math.h> +#include <time.h> + +#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; + } + + /* 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 and a model number + * + * @param config_line Text to parse + * @param vendor_id + * @param product_id + * @param model_number + * @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_Word* model_number) +{ + char *vendor_id_string, *product_id_string, *model_number_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 product-id */ + 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 = 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; + } + return SANE_STATUS_GOOD; +} + +/** + * Check if current list of supported devices contains the given specifications. + * + * @param vendor_id + * @param product_id + * @param model_number + * @return + */ +SANE_Bool +sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Word model_number) +{ + 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) { + 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 + * @return + */ +SANE_Status +sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Word model_number) +{ + 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\n", i, + pieusb_supported_usb_device_list[k].vendor, + pieusb_supported_usb_device_list[k].product, + pieusb_supported_usb_device_list[k].model); + } + + 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+1].vendor = 0; + pieusb_supported_usb_device_list[i+1].product = 0; + pieusb_supported_usb_device_list[i+1].model = 0; + for (k=0; k<=i+1; k++) { + DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add() add: %03d: %04x %04x %02x\n", i, + pieusb_supported_usb_device_list[k].vendor, + pieusb_supported_usb_device_list[k].product, + pieusb_supported_usb_device_list[k].model); + } + 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; m<shading_width; m++) { + scanner->shading_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]); +} diff --git a/backend/pieusb_specific.h b/backend/pieusb_specific.h new file mode 100644 index 0000000..3928adf --- /dev/null +++ b/backend/pieusb_specific.h @@ -0,0 +1,346 @@ +/* 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 */ + + /* 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_Word* model_number); +/* 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_Word model_number); +SANE_Status sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Word model_number); +/* 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 */ diff --git a/backend/pieusb_usb.c b/backend/pieusb_usb.c new file mode 100644 index 0000000..71b6bcf --- /dev/null +++ b/backend/pieusb_usb.c @@ -0,0 +1,679 @@ +/* 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 <unistd.h> /* usleep */ +#include <time.h> /* 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; +} diff --git a/backend/pieusb_usb.h b/backend/pieusb_usb.h new file mode 100644 index 0000000..dee3212 --- /dev/null +++ b/backend/pieusb_usb.h @@ -0,0 +1,114 @@ +/* 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 */ diff --git a/backend/pixma.h b/backend/pixma.h index 4be43bd..620f038 100644 --- a/backend/pixma.h +++ b/backend/pixma.h @@ -114,7 +114,7 @@ typedef uint32_t uint32_t; /**@{*/ #define PIXMA_VERSION_MAJOR 0 #define PIXMA_VERSION_MINOR 17 -#define PIXMA_VERSION_BUILD 18 +#define PIXMA_VERSION_BUILD 23 /**@}*/ /** \name Error codes */ diff --git a/backend/pixma_bjnp.c b/backend/pixma_bjnp.c index dece926..7d2d541 100644 --- a/backend/pixma_bjnp.c +++ b/backend/pixma_bjnp.c @@ -1802,6 +1802,8 @@ static void add_scanner(SANE_Int *dev_no, 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 at %s added!\n", + uri)); } break; case BJNP_STATUS_ALREADY_ALLOCATED: @@ -1875,7 +1877,8 @@ sanei_bjnp_find_devices (const char **conf_devices, memset( broadcast_addr, 0, sizeof( broadcast_addr) ); memset( &scanner_sa, 0 ,sizeof( scanner_sa ) ); - PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_find_devices:\n")); + 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++) @@ -2108,8 +2111,10 @@ sanei_bjnp_open (SANE_String_Const devname, SANE_Int * dn) 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 ) ) + if ( (result != BJNP_STATUS_GOOD) && (result != BJNP_STATUS_ALREADY_ALLOCATED ) ) { return SANE_STATUS_INVAL; + } + return SANE_STATUS_GOOD; } /** Close a BJNP device. diff --git a/backend/pixma_common.c b/backend/pixma_common.c index 0945a69..9d41f7a 100644 --- a/backend/pixma_common.c +++ b/backend/pixma_common.c @@ -383,7 +383,7 @@ pixma_binarize_line(pixma_scan_param_t * sp, uint8_t * dst, uint8_t * src, unsig unsigned char mask; uint8_t min, max; - /* PDBG (pixma_dbg (4, "*pixma_binarize_line***** src = %u, dst = %u, width = %u, c = %u, threshold = %u, thershold_curve = %u *****\n", + /* 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 */ diff --git a/backend/pixma_common.h b/backend/pixma_common.h index 069f8b8..dbaa23f 100644 --- a/backend/pixma_common.h +++ b/backend/pixma_common.h @@ -147,7 +147,7 @@ struct pixma_scan_ops_t * -# 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 the beginning and + * -# 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. diff --git a/backend/pixma_imageclass.c b/backend/pixma_imageclass.c index f4bad37..b2d45ee 100644 --- a/backend/pixma_imageclass.c +++ b/backend/pixma_imageclass.c @@ -518,11 +518,8 @@ iclass_check_param (pixma_t * s, pixma_scan_param_t * sp) /* Some exceptions here for particular devices */ /* Those devices can scan up to Legal 14" with ADF, but A4 11.7" in flatbed */ - if (sp->source == PIXMA_SOURCE_FLATBED - && ( s->cfg->pid == MF4700_PID || - s->cfg->pid == MF4800_PID || - s->cfg->pid == MF8200_PID || - s->cfg->pid == MF8500_PID)) + /* 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); return 0; diff --git a/backend/pixma_io_sanei.c b/backend/pixma_io_sanei.c index 08ec525..9e4a2fa 100644 --- a/backend/pixma_io_sanei.c +++ b/backend/pixma_io_sanei.c @@ -575,7 +575,8 @@ pixma_wait_interrupt (pixma_io_t * io, void *buf, unsigned size, int timeout) #endif error = map_error (sanei_usb_read_int (io->dev, buf, &count)); } - if (error == PIXMA_EIO || error == PIXMA_EOF) + 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; diff --git a/backend/pixma_mp150.c b/backend/pixma_mp150.c index 79711fe..4f8b232 100644 --- a/backend/pixma_mp150.c +++ b/backend/pixma_mp150.c @@ -227,6 +227,7 @@ /* 2015 new devices (untested) */ #define MX490_PID 0x1787 #define E480_PID 0x1789 +#define MG3600_PID 0x178a /* Generation 4 XML messages that encapsulates the Pixma protocol messages */ @@ -1154,7 +1155,8 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib) && s->cfg->pid != MG5500_PID && s->cfg->pid != MG6300_PID && s->cfg->pid != MG6400_PID - && s->cfg->pid != MG7100_PID) + && s->cfg->pid != MG7100_PID + && s->cfg->pid != MG7500_PID) reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->wx, line_size); /* Crop line to selected borders */ @@ -1825,6 +1827,7 @@ const pixma_config_t pixma_mp150_devices[] = { /* 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), END_OF_DEVICE_LIST }; diff --git a/backend/pixma_mp810.c b/backend/pixma_mp810.c index e8bf75f..5f9043e 100644 --- a/backend/pixma_mp810.c +++ b/backend/pixma_mp810.c @@ -1708,7 +1708,8 @@ static unsigned post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib) /* 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->param->xdpi == 4800)) + || 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); diff --git a/backend/plustek-pp_dac.c b/backend/plustek-pp_dac.c index dd35ce7..f89d814 100644 --- a/backend/plustek-pp_dac.c +++ b/backend/plustek-pp_dac.c @@ -338,7 +338,7 @@ static void dacP98SetInitialGainRegister( pScanData ps ) dacP98FillGainInitialRestRegister( ps );/* Model Control2, LED, Correct.*/ } -/** Find the the most ideal intensity for each color (RGB) +/** Find the most ideal intensity for each color (RGB) */ static void dacP98SetRGBGainRegister( pScanData ps ) { @@ -451,7 +451,7 @@ static void dacP98SetInitialGainRAM( pScanData ps ) dacP98DownloadMapTable( ps, ps->pScanBuffer1 ); } -/** Find the the most ideal intensity for each color (RGB) +/** Find the most ideal intensity for each color (RGB) */ static void dacP98AdjustRGBGain( pScanData ps ) { diff --git a/backend/plustek-pp_scan.h b/backend/plustek-pp_scan.h index 3b977bf..5a8f9d7 100644 --- a/backend/plustek-pp_scan.h +++ b/backend/plustek-pp_scan.h @@ -152,7 +152,7 @@ /* * WARNING - never use the _SECOND define with the _DODELAY macro !! - * they are for use the the MiscStartTimer function and the _DO_UDELAY macro + * they are for use the MiscStartTimer function and the _DO_UDELAY macro */ #ifndef __KERNEL__ typedef double TimerDef, *pTimerDef; diff --git a/backend/plustek-usbcalfile.c b/backend/plustek-usbcalfile.c index 5638b2e..afea3f9 100644 --- a/backend/plustek-usbcalfile.c +++ b/backend/plustek-usbcalfile.c @@ -89,7 +89,7 @@ typedef struct { static u_short a_wWhiteShading[_SHADING_BUF] = {0}; static u_short a_wDarkShading[_SHADING_BUF] = {0}; -/* the version the the calibration files */ +/* the version the calibration files */ #define _PT_CF_VERSION 0x0002 /** function to read a text file and returns the string which starts which diff --git a/backend/ricoh.c b/backend/ricoh.c index a349179..88f33d1 100644 --- a/backend/ricoh.c +++ b/backend/ricoh.c @@ -73,6 +73,7 @@ #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; @@ -221,11 +222,13 @@ attach (const char *devnam, Ricoh_Device ** devp) dev->sane.name = strdup (devnam); dev->sane.vendor = "RICOH"; - str = malloc (16 + 1); - memset (str, 0, sizeof (str)); - strncpy (str, (char *)ibuf.product, sizeof(ibuf.product)); - strncpy (str + sizeof(ibuf.revision), (char *)ibuf.revision, sizeof(ibuf.revision)); - str[sizeof(ibuf.product) + sizeof(ibuf.revision)] = '\0'; + 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"; @@ -535,6 +538,9 @@ sane_exit (void) free ((void *) dev->sane.model); free (dev); } + + if (devlist) + free (devlist); DBG (11, "<< sane_exit\n"); } @@ -542,7 +548,6 @@ sane_exit (void) SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { - static const SANE_Device **devlist = 0; Ricoh_Device *dev; int i; diff --git a/backend/s9036.c b/backend/s9036.c index 9313622..1b97f80 100644 --- a/backend/s9036.c +++ b/backend/s9036.c @@ -45,6 +45,7 @@ #undef Byte #define Byte SANE_Byte +static const SANE_Device **devlist = NULL; static int num_devices; static S9036_Device *s9036_devices; @@ -870,12 +871,14 @@ sane_exit (void) sane_close (dev->handle); free (dev); } + + if (devlist) + free (devlist); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { - static const SANE_Device **devlist = 0; S9036_Device *dev; int i; diff --git a/backend/snapscan-options.c b/backend/snapscan-options.c index 15f3a4a..52fee81 100644 --- a/backend/snapscan-options.c +++ b/backend/snapscan-options.c @@ -44,7 +44,7 @@ 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 the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ + of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ SANE SnapScan backend */ diff --git a/backend/snapscan-scsi.c b/backend/snapscan-scsi.c index ac0efea..861ff32 100644 --- a/backend/snapscan-scsi.c +++ b/backend/snapscan-scsi.c @@ -44,7 +44,7 @@ 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 the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ + of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ diff --git a/backend/snapscan-sources.c b/backend/snapscan-sources.c index d91060e..63eadb2 100644 --- a/backend/snapscan-sources.c +++ b/backend/snapscan-sources.c @@ -44,7 +44,7 @@ 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 the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ + of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ diff --git a/backend/snapscan-sources.h b/backend/snapscan-sources.h index 53b705b..a5ed3df 100644 --- a/backend/snapscan-sources.h +++ b/backend/snapscan-sources.h @@ -44,7 +44,7 @@ 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 the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ + of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ diff --git a/backend/snapscan.c b/backend/snapscan.c index 44b757b..3c0fb81 100644 --- a/backend/snapscan.c +++ b/backend/snapscan.c @@ -45,7 +45,7 @@ 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 the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ + of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ diff --git a/backend/snapscan.h b/backend/snapscan.h index 2795d88..19a9fb5 100644 --- a/backend/snapscan.h +++ b/backend/snapscan.h @@ -44,7 +44,7 @@ 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 the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ + of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ SANE SnapScan backend */ diff --git a/backend/sp15c.c b/backend/sp15c.c index 7a3808e..3937a30 100644 --- a/backend/sp15c.c +++ b/backend/sp15c.c @@ -311,7 +311,6 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { - static const SANE_Device **devlist = 0; struct sp15c *dev; int i; @@ -990,6 +989,9 @@ sane_exit (void) free (dev->buffer); free (dev); } + + if (devlist) + free (devlist); } /* sane_exit */ /* }################ internal (support) routines ################{ */ diff --git a/backend/sp15c.h b/backend/sp15c.h index 52535e0..e078316 100644 --- a/backend/sp15c.h +++ b/backend/sp15c.h @@ -97,6 +97,7 @@ static const char RCSid_h[] = "$Header$"; * */ +static const SANE_Device **devlist = NULL; static int num_devices; static struct sp15c *first_dev; diff --git a/backend/tamarack.c b/backend/tamarack.c index 9baec51..e7073af 100644 --- a/backend/tamarack.c +++ b/backend/tamarack.c @@ -77,6 +77,7 @@ #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; @@ -950,12 +951,14 @@ sane_exit (void) 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) { - static const SANE_Device **devlist = 0; Tamarack_Device *dev; int i; diff --git a/backend/test.c b/backend/test.c index 505c821..d5b7365 100644 --- a/backend/test.c +++ b/backend/test.c @@ -1120,7 +1120,10 @@ read_option (SANE_String line, SANE_String option_string, return SANE_STATUS_INVAL; if (strcmp (word, option_string) != 0) - return SANE_STATUS_INVAL; + { + free(word); + return SANE_STATUS_INVAL; + } free (word); word = 0; @@ -1240,7 +1243,6 @@ read_option (SANE_String line, SANE_String option_string, if (word) free (word); - word = 0; return SANE_STATUS_GOOD; } @@ -1453,7 +1455,7 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un { FILE *fp; SANE_Int linenumber; - SANE_Char line[PATH_MAX], *word; + SANE_Char line[PATH_MAX], *word = NULL; SANE_String_Const cp; SANE_Device *sane_device; Test_Device *test_device, *previous_device; @@ -1481,7 +1483,9 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un DBG (4, "sane_init: reading config file `%s'\n", TEST_CONFIG_FILE); while (sanei_config_read (line, sizeof (line), fp)) { - word = 0; + if (word) + free (word); + word = NULL; linenumber++; cp = sanei_config_get_string (line, &word); @@ -1490,8 +1494,6 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un DBG (5, "sane_init: config file line %3d: ignoring empty line\n", linenumber); - if (word) - free (word); continue; } if (word[0] == '#') @@ -1499,7 +1501,6 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un DBG (5, "sane_init: config file line %3d: ignoring comment line\n", linenumber); - free (word); continue; } @@ -1599,6 +1600,8 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un DBG (3, "sane-init: I don't know how to handle option `%s'\n", word); } /* while */ + if (word) + free (word); fclose (fp); } /* if */ else diff --git a/backend/v4l.c b/backend/v4l.c index 38595ed..519bf01 100644 --- a/backend/v4l.c +++ b/backend/v4l.c @@ -290,6 +290,13 @@ init_options (V4L_Scanner * s) 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"; @@ -305,6 +312,13 @@ init_options (V4L_Scanner * 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"; @@ -644,6 +644,8 @@ 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 @@ -678,6 +680,7 @@ USB_LIBS LIBUSB_1_0_LIBS LIBUSB_1_0_CFLAGS SYSTEMD_LIBS +SYSTEMD_CFLAGS ALLOCA LIBOBJS SOCKET_LIBS @@ -695,6 +698,7 @@ LOCKPATH_GROUP INSTALL_LOCKPATH PTHREAD_LIBS IEEE1284_LIBS +PNG_LIBS TIFF_LIBS JPEG_LIBS SYSLOG_LIBS @@ -834,6 +838,7 @@ with_gphoto2 with_v4l enable_avahi with_snmp +with_systemd enable_libusb_1_0 enable_libusb enable_scsibuffersize @@ -870,6 +875,8 @@ LIBV4L_CFLAGS LIBV4L_LIBS AVAHI_CFLAGS AVAHI_LIBS +SYSTEMD_CFLAGS +SYSTEMD_LIBS LIBUSB_1_0_CFLAGS LIBUSB_1_0_LIBS BACKENDS @@ -1542,6 +1549,7 @@ Optional Packages: --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-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] @@ -1569,6 +1577,10 @@ Some influential environment variables: 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 LIBUSB_1_0_CFLAGS C compiler flags for LIBUSB_1_0, overriding pkg-config LIBUSB_1_0_LIBS @@ -2607,7 +2619,7 @@ is_release=no -am__api_version='1.13' +am__api_version='1.14' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -3173,6 +3185,47 @@ 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: <http://austingroupbugs.net/view.php?id=542> + +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: <http://www.gnu.org/software/coreutils/>. + +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 { $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; } @@ -4107,6 +4160,65 @@ 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" @@ -4299,131 +4411,6 @@ else fi -if test "x$CC" != xcc; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 -$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } -else - { $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; } -fi -set dummy $CC; ac_cc=`$as_echo "$2" | - sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -if eval \${ac_cv_prog_cc_${ac_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. -# We do the test twice because some compilers refuse to overwrite an -# existing .o file with -o, though they will create one. -ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' -rm -f conftest2.* -if { { 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; } && - test -f conftest2.$ac_objext && { { 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 - eval ac_cv_prog_cc_${ac_cc}_c_o=yes - if test "x$CC" != xcc; then - # Test first that cc exists at all. - if { ac_try='cc -c conftest.$ac_ext >&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_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' - rm -f conftest2.* - if { { 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; } && - test -f conftest2.$ac_objext && { { 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 - # cc works too. - : - else - # cc exists but doesn't like -o. - eval ac_cv_prog_cc_${ac_cc}_c_o=no - fi - fi - fi -else - eval ac_cv_prog_cc_${ac_cc}_c_o=no -fi -rm -f core conftest* - -fi -if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; 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 NO_MINUS_C_MINUS_O 1" >>confdefs.h - -fi - -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != 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 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 @@ -5192,7 +5179,6 @@ else fi -INCLUDES="${INCLUDES} -I/usr/local/include" if test "${ac_cv_c_compiler_gnu}" = "yes"; then @@ -7252,6 +7238,61 @@ 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 : @@ -9616,6 +9657,42 @@ fi +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 <sys/io.h> +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 + @@ -9649,31 +9726,168 @@ $as_echo "#define HAVE_DEV_URANDOM 1" >>confdefs.h fi -$as_echo "checking for cups" -if test -e /usr/include/cups/cups.h ; then -$as_echo "#define HAVE_CUPS 1" >>confdefs.h - with_cups="yes" - LIBS="-lcups $LIBS" +# 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 - $as_echo "cups.h not found, you may want to install a cups development package" - $as_echo "in order to autodetect network scanners in kodakaio." - with_cups="no" + pkg_failed=yes +fi + else + pkg_failed=untried fi -$as_echo_n "Checking for systemd..." -if test -e /usr/include/systemd/sd-daemon.h ; then -$as_echo "#define HAVE_SYSTEMD 1" >>confdefs.h - with_systemd="yes" - SYSTEMD_LIBS=" -lsystemd-daemon" +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } - $as_echo "yes" +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes else - with_systemd="no" - $as_echo "no" + _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 @@ -17857,12 +18071,12 @@ 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 fujitsu genesys \ + 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 pint \ + 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 @@ -17922,14 +18136,21 @@ for be in ${BACKENDS}; do mustek_pp) if test "${sane_cv_use_libieee1284}" != "yes" && test "${enable_parport_directio}" != "yes"; then - echo "*** $be backend requires libieee1284 and paraport-directio libraries - $DISABLE_MSG" + 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/or TIFF library - $DISABLE_MSG" + 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 ;; @@ -17950,9 +18171,9 @@ for be in ${BACKENDS}; do ;; qcam) - if test "${ac_cv_func_ioperm}" = "no" \ + 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 and portaccess functions - $DISABLE_MSG" + echo "*** $be backend requires (ioperm, inb and outb) or portaccess functions - $DISABLE_MSG" backend_supported="no" fi ;; @@ -18021,8 +18242,19 @@ 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 @@ -18089,14 +18321,21 @@ for be in ${BACKENDS}; do mustek_pp) if test "${sane_cv_use_libieee1284}" != "yes" && test "${enable_parport_directio}" != "yes"; then - echo "*** $be backend requires libieee1284 and paraport-directio libraries - $DISABLE_MSG" + 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/or TIFF library - $DISABLE_MSG" + 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 ;; @@ -18117,9 +18356,9 @@ for be in ${BACKENDS}; do ;; qcam) - if test "${ac_cv_func_ioperm}" = "no" \ + 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 and portaccess functions - $DISABLE_MSG" + echo "*** $be backend requires (ioperm, inb and outb) or portaccess functions - $DISABLE_MSG" backend_supported="no" fi ;; @@ -18411,6 +18650,10 @@ 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 "${ENABLE_TRANSLATIONS_TRUE}" && test -z "${ENABLE_TRANSLATIONS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_TRANSLATIONS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -21180,7 +21423,6 @@ 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 "CUPS support: `eval eval echo ${with_cups}`" echo "-> The following backends will be built:" for backend in ${BACKENDS} ; do echo $ECHO_N "${backend} " diff --git a/configure.in b/configure.in index 48953d2..7d56514 100644 --- a/configure.in +++ b/configure.in @@ -82,7 +82,6 @@ AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) dnl *********************************************************************** dnl set compiler/linker flags dnl *********************************************************************** -INCLUDES="${INCLUDES} -I/usr/local/include" AC_SUBST(INCLUDES) SANE_SET_CFLAGS([$is_release]) SANE_SET_LDFLAGS @@ -123,6 +122,7 @@ AC_SUBST(SYSLOG_LIBS) SANE_CHECK_JPEG SANE_CHECK_TIFF +SANE_CHECK_PNG SANE_CHECK_IEEE1284 SANE_CHECK_PTHREAD SANE_CHECK_LOCKING @@ -314,6 +314,25 @@ AC_CHECK_FUNCS(atexit ioperm i386_set_ioperm \ AC_REPLACE_FUNCS(getenv isfdtype sigprocmask snprintf \ strcasestr strdup strndup strsep usleep sleep syslog vsyslog) +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 <sys/io.h>]], + [[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 <sys/io.h> 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 @@ -344,17 +363,21 @@ dnl $as_echo "in order to autodetect network scanners in kodakaio." dnl with_cups="no" dnl fi -dnl added by llagendijk 12/7/2012 to detect systemd for saned -$as_echo_n "Checking for systemd..." -if test -e /usr/include/systemd/sd-daemon.h ; then +AC_ARG_WITH(systemd, + AC_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?]) - with_systemd="yes" - SYSTEMD_LIBS=" -lsystemd-daemon" AC_SUBST(SYSTEMD_LIBS) - $as_echo "yes" -else - with_systemd="no" - $as_echo "no" + else + if test "x$with_systemd" = xyes; then + AC_MSG_ERROR([Systemd support was requested but systemd was not found]) + fi + fi fi dnl *********** @@ -615,7 +638,7 @@ ALL_BACKENDS="abaton agfafocus apple artec artec_eplus48u as6e \ 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 pint \ + 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 @@ -663,8 +686,12 @@ 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 diff --git a/doc/Makefile.am b/doc/Makefile.am index 5b450e0..a7e47af 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -21,7 +21,7 @@ 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-pint.5 sane-pnm.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 \ @@ -44,7 +44,7 @@ EXTRA_DIST += sane-abaton.man sane-agfafocus.man sane-apple.man sane-as6e.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-pint.man sane-pnm.man sane-umax.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 \ @@ -183,7 +183,7 @@ DESC_FILES = descriptions/abaton.desc descriptions/agfafocus.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/pint.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 \ diff --git a/doc/Makefile.in b/doc/Makefile.in index cb8757d..225d285 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -253,6 +253,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -269,6 +270,7 @@ 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_LIBS = @USB_LIBS@ @@ -340,9 +342,9 @@ EXTRA_DIST = scanimage.man sane-config.man sane-find-scanner.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-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-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 \ @@ -376,7 +378,7 @@ 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-pint.5 sane-pnm.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 \ @@ -466,7 +468,7 @@ DESC_FILES = descriptions/abaton.desc descriptions/agfafocus.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/pint.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 \ diff --git a/doc/descriptions-external/epkowa.desc b/doc/descriptions-external/epkowa.desc index 55f4eb2..9217aaf 100644 --- a/doc/descriptions-external/epkowa.desc +++ b/doc/descriptions-external/epkowa.desc @@ -1,5 +1,5 @@ ;;; epkowa.desc -*- emacs-lisp -*- (eh, sort of) -;;; Copyright (C) 2004--2013 Olaf Meeuwissen +;;; Copyright (C) 2004--2015 Olaf Meeuwissen ;;; ;;; This file is part of the "Image Scan!" documentation. ;;; @@ -40,7 +40,7 @@ ;; Backend data. ;; :backend "epkowa" -:version "iscan 2.29.1/iscan-data 1.23.0" +:version "iscan 2.30.1/iscan-data 1.36.0" :url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" @@ -80,6 +80,18 @@ ;; 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<br>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<br>all-in-one" + :model "Actionscanner II" :interface "parallel SCSI" :status :good @@ -125,7 +137,7 @@ :interface "USB" :usbid "0x04b8" "0x0878" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-704A" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-704A" :model "Artisan 700" :interface "USB" @@ -221,37 +233,67 @@ :interface "USB" :usbid "0x04b8" "0x0862" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-704A" :interface "USB" :usbid "0x04b8" "0x0878" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-705A" :interface "USB" :usbid "0x04b8" "0x089f" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>all-in-one" :model "EP-774A" :interface "USB" :usbid "0x04b8" "0x0893" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-775A" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-775AW" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>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<br>all-in-one" :model "EP-801A" :interface "USB" @@ -313,6 +355,42 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>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<br>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<br>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<br>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<br>all-in-one" + :model "EP-901A" :interface "USB" :usbid "0x04b8" "0x0844" @@ -367,6 +445,30 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>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<br>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<br>all-in-one" + :model "ES-300C" :interface "SCSI parallel" :status :good @@ -425,7 +527,7 @@ :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good -:comment "network interface unsupported<br>IEEE1394 untested" +:comment "network interface not supported<br>IEEE1394 untested" :model "ES-8000" :interface "SCSI" @@ -446,7 +548,7 @@ :interface "USB" :usbid "0x04b8" "0x0129" :status :good -:comment "network interface unsupported<br>IEEE1394 untested" +:comment "network interface not supported<br>IEEE1394 untested" :model "ES-D200" :interface "USB" @@ -890,6 +992,12 @@ :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" @@ -920,11 +1028,18 @@ :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" @@ -932,6 +1047,11 @@ :status :good :comment "IEEE1394 untested" +:model "GT-X980" +:interface "USB" +:usbid "0x04b8" "0x0151" +:status :good + :model "K200 Series" :interface "USB" :usbid "0x04b8" "0x0871" @@ -980,12 +1100,18 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" -:model "L550" +:model "L550 Series" :interface "USB" :usbid "0x04b8" "0x08a9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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" @@ -1068,6 +1194,24 @@ :status :good :comment "network interface not supported<br>business all-in-one" +:model "LP-M8040" +:interface "USB" +:usbid "0x04b8" "0x08ad" +:status :good +:comment "network interface not supported<br>business all-in-one" + +:model "LP-M8040A" +:interface "USB" +:usbid "0x04b8" "0x08ad" +:status :good +:comment "network interface not supported<br>business all-in-one" + +:model "LP-M8040F" +:interface "USB" +:usbid "0x04b8" "0x08ad" +:status :good +:comment "network interface not supported<br>business all-in-one" + :model "M200 Series" :interface "USB" :usbid "0x04b8" "0x08aa" @@ -1126,7 +1270,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "ME OFFICE 570W Series" :interface "USB" @@ -1138,13 +1282,13 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "ME OFFICE 620F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "ME OFFICE 650FN Series" :interface "USB" @@ -1296,6 +1440,18 @@ :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<br>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<br>all-in-one" + :model "PX-1600F" :interface "USB" :usbid "0x04b8" "0x0869" @@ -1350,6 +1506,18 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>all-in-one" + :model "PX-501A" :interface "USB" :usbid "0x04b8" "0x084a" @@ -1462,7 +1630,7 @@ :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "PX-FA700" :interface "USB" @@ -1470,6 +1638,54 @@ :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<br>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<br>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<br>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<br>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<br>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<br>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<br>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<br>all-in-one" + :model "Perfection 600" :interface "SCSI" :status :unsupported @@ -1690,6 +1906,12 @@ :status :good :comment "requires DFSG non-free iscan-plugin-gt-s600<br>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" @@ -1708,6 +1930,12 @@ :status :good :comment "requires DFSG non-free iscan-plugin-perfection-v370<br>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<br>overseas version of the GT-S650" + :model "Perfection V100 Photo" :interface "USB" :usbid "0x04b8" "0x012d" @@ -1750,6 +1978,12 @@ :status :good :comment "requires DFSG non-free iscan-plugin-gt-x770<br>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" @@ -1761,12 +1995,25 @@ :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested<br>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<br>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" @@ -2125,13 +2372,13 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office BX305F" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office BX305FW" :interface "USB" @@ -2215,13 +2462,13 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office TX320F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office TX510FN Series" :interface "USB" @@ -2263,7 +2510,7 @@ :interface "USB" :usbid "0x04b8" "0x0862" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-703A" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-703A" :model "Stylus Photo PX700W" :interface "USB" @@ -2545,7 +2792,7 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus NX330 Series" :interface "USB" @@ -2569,7 +2816,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus NX430W Series" :interface "USB" @@ -2683,7 +2930,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus SX430W Series" :interface "USB" @@ -2827,7 +3074,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus TX430W Series" :interface "USB" @@ -2877,6 +3124,24 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>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<br>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<br>all-in-one" + :model "WF-3520 Series" :interface "USB" :usbid "0x04b8" "0x0899" @@ -2895,6 +3160,42 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>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<br>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<br>all-in-one<br>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<br>all-in-one" + :model "WF-7510 Series" :interface "USB" :usbid "0x04b8" "0x0869" @@ -2907,47 +3208,77 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>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<br>all-in-one<br>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<br>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<br>all-in-one" + :model "WP-4511" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4515" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "WP-4521" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4525" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4530 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4540 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4590 Series" :interface "USB" @@ -2965,7 +3296,7 @@ :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface (option) supported via DFSG non-free iscan-network-nt package<br>some models in the series have a built-in network interface<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>some models in the series have a built-in network interface<br>all-in-one" :model "WorkForce 435" :interface "USB" @@ -3055,19 +3386,25 @@ :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete -:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one<br>overseas version of the PX-047A" :model "XP-300 Series" :interface "USB" @@ -3079,7 +3416,13 @@ :interface "USB" :usbid "0x04b8" "0x08af" :status :complete -:comment "network interface supported via DFSG non-free iscan-network-nt package" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one<br>overseas version of the PX-437A" :model "XP-400 Series" :interface "USB" @@ -3093,32 +3436,104 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>overseas version of the EP-976A3" diff --git a/doc/descriptions-external/utsushi.desc b/doc/descriptions-external/utsushi.desc new file mode 100644 index 0000000..911ad95 --- /dev/null +++ b/doc/descriptions-external/utsushi.desc @@ -0,0 +1,237 @@ +;;; utsushi.desc -*- emacs-lisp -*- (sort of) +;;; Copyright (C) 2015 Olaf 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 <http://www.gnu.org/licenses/>. + +;; 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-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 "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-M860F" +:interface "USB" +:usbid "0x04b8" "0x08ce" +:status :good + +:model "PX-M7050" +:interface "USB" +:usbid "0x04b8" "0x08bc" +:status :good + +:model "PX-M7050FX" +:interface "USB" +:usbid "0x04b8" "0x08cc" +: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 diff --git a/doc/descriptions/canon_dr.desc b/doc/descriptions/canon_dr.desc index 149ca4c..86a8507 100644 --- a/doc/descriptions/canon_dr.desc +++ b/doc/descriptions/canon_dr.desc @@ -11,7 +11,7 @@ :backend "canon_dr" ; name of backend :url "http://www.thebility.com/canon/" -:version "49" ; version of backend +: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.... @@ -284,7 +284,7 @@ :interface "USB" :usbid "0x1083" "0x1658" :status :untested -:comment "Perhaps similar to DR-C125?" +:comment "" :model "DR-F120" :interface "USB" diff --git a/doc/descriptions/epson.desc b/doc/descriptions/epson.desc index d5fd896..1c9d8a2 100644 --- a/doc/descriptions/epson.desc +++ b/doc/descriptions/epson.desc @@ -190,9 +190,7 @@ :model "FilmScan 200" :interface "SCSI" -:comment "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>" :status :unsupported -:url "http://www.vjet.demon.co.uk/scanner/" :model "CX-3200" :interface "USB" diff --git a/doc/descriptions/epson2.desc b/doc/descriptions/epson2.desc index 82030b1..de61b76 100644 --- a/doc/descriptions/epson2.desc +++ b/doc/descriptions/epson2.desc @@ -19,11 +19,23 @@ :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<br>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<br>all-in-one" + :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" @@ -38,10 +50,10 @@ :comment "network interface supported<br>AcuLaser CX11 with network interface and fax" :model "AcuLaser CX21" -:interface "USB" +:interface "USB Network" :usbid "0x04b8" "0x0835" :status :good -:comment "network interface probably supported" +:comment "network interface supported" :model "AcuLaser MX20DN" :interface "USB" @@ -65,7 +77,7 @@ :interface "USB" :usbid "0x04b8" "0x0878" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-704A" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-704A" :model "Artisan 700" :interface "USB Network" @@ -161,37 +173,67 @@ :interface "USB" :usbid "0x04b8" "0x0862" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-704A" :interface "USB" :usbid "0x04b8" "0x0878" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-705A" :interface "USB" :usbid "0x04b8" "0x089f" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>all-in-one" :model "EP-774A" :interface "USB" :usbid "0x04b8" "0x0893" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-775A" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "EP-775AW" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>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<br>all-in-one" :model "EP-801A" :interface "USB Network" @@ -253,6 +295,42 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>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<br>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<br>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<br>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<br>all-in-one" + :model "EP-901A" :interface "USB" :usbid "0x04b8" "0x0844" @@ -307,6 +385,30 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>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<br>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<br>all-in-one" + :model "ES-300C" :interface "SCSI parallel" :status :good @@ -365,7 +467,7 @@ :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good -:comment "network interface unsupported<br>IEEE1394 untested" +:comment "network interface probably supported<br>IEEE1394 untested" :model "ES-8000" :interface "SCSI" @@ -386,7 +488,7 @@ :interface "USB" :usbid "0x04b8" "0x0129" :status :good -:comment "network interface unsupported<br>IEEE1394 untested" +:comment "network interface probably supported<br>IEEE1394 untested" :model "ES-D200" :interface "USB" @@ -430,6 +532,7 @@ :model "Expression 800" ; command spec :interface "SCSI" +:scsi "EPSON" "Expression800" "processor" :status :complete :comment "overseas version of the GT-9600" @@ -500,7 +603,7 @@ :model "FilmScan 200" :interface "SCSI" :status :minimal -:comment "will be supported" +:comment "missing documentation" :model "GT-1500" :interface "USB" @@ -532,6 +635,7 @@ :model "GT-5500" :interface "SCSI" +:scsi "EPSON" "SCANNER GT-5500" "processor" :status :good :model "GT-6000" @@ -555,6 +659,7 @@ :model "GT-7000S" :interface "SCSI" +:scsi "EPSON" "SCANNER GT-7000" "processor" :status :complete :model "GT-7000U" @@ -665,11 +770,13 @@ :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 @@ -825,6 +932,12 @@ :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" @@ -855,8 +968,15 @@ :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" @@ -867,6 +987,11 @@ :status :good :comment "IEEE1394 untested" +:model "GT-X980" +:interface "USB" +:usbid "0x04b8" "0x0151" +:status :good + :model "K200 Series" :interface "USB" :usbid "0x04b8" "0x0871" @@ -915,12 +1040,18 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" -:model "L550" +:model "L550 Series" :interface "USB" :usbid "0x04b8" "0x08a9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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" @@ -1003,6 +1134,24 @@ :status :good :comment "network interface probably supported<br>business all-in-one" +:model "LP-M8040" +:interface "USB" +:usbid "0x04b8" "0x08ad" +:status :good +:comment "network interface probably supported<br>business all-in-one" + +:model "LP-M8040A" +:interface "USB" +:usbid "0x04b8" "0x08ad" +:status :good +:comment "network interface probably supported<br>business all-in-one" + +:model "LP-M8040F" +:interface "USB" +:usbid "0x04b8" "0x08ad" +:status :good +:comment "network interface probably supported<br>business all-in-one" + :model "M200 Series" :interface "USB" :usbid "0x04b8" "0x08aa" @@ -1061,7 +1210,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "ME OFFICE 570W Series" :interface "USB" @@ -1073,13 +1222,13 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "ME OFFICE 620F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "ME OFFICE 650FN Series" :interface "USB" @@ -1231,6 +1380,18 @@ :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<br>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<br>all-in-one" + :model "PX-1600F" :interface "USB" :usbid "0x04b8" "0x0869" @@ -1285,6 +1446,18 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>all-in-one" + :model "PX-501A" :interface "USB" :usbid "0x04b8" "0x084a" @@ -1397,7 +1570,7 @@ :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "PX-FA700" :interface "USB" @@ -1405,6 +1578,54 @@ :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<br>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<br>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<br>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<br>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<br>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<br>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<br>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<br>all-in-one" + :model "Perfection 600" :interface "SCSI" :status :unsupported @@ -1413,11 +1634,12 @@ :model "Perfection 610" ; command spec :interface "USB" :usbid "0x04b8" "0x0103" -:status :complete +: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" @@ -1441,6 +1663,7 @@ :model "Perfection 1200S" ; command spec :interface "SCSI" +:scsi "EPSON" "Perfection1200" "processor" :status :complete :comment "overseas version of the GT-7600S" @@ -1546,6 +1769,7 @@ :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" @@ -1570,6 +1794,7 @@ :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" @@ -1621,6 +1846,12 @@ :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" @@ -1639,6 +1870,12 @@ :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" @@ -1681,6 +1918,12 @@ :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" @@ -1689,16 +1932,29 @@ :model "Perfection V700 Photo" :interface "USB" +:scsi "EPSON" "GT-X900" "processor" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested<br>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<br>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" @@ -1761,7 +2017,8 @@ :model "Stylus CX3810" :interface "USB" -:status :untested +:usbid "0x04b8" "0x0818" +:status :good :comment "all-in-one" :model "Stylus CX3900" @@ -2055,13 +2312,13 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office BX305F" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office BX305FW" :interface "USB" @@ -2145,13 +2402,13 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office TX320F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus Office TX510FN Series" :interface "USB" @@ -2193,7 +2450,7 @@ :interface "USB" :usbid "0x04b8" "0x0862" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-703A" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the EP-703A" :model "Stylus Photo PX700W" :interface "USB Network" @@ -2475,7 +2732,7 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus NX330 Series" :interface "USB" @@ -2499,7 +2756,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus NX430W Series" :interface "USB" @@ -2613,7 +2870,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus SX430W Series" :interface "USB" @@ -2757,7 +3014,7 @@ :interface "USB" :usbid "0x04b8" "0x0864" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "Stylus TX430W Series" :interface "USB" @@ -2807,6 +3064,24 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>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<br>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<br>all-in-one" + :model "WF-3520 Series" :interface "USB" :usbid "0x04b8" "0x0899" @@ -2825,6 +3100,42 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>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<br>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<br>all-in-one<br>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<br>all-in-one" + :model "WF-7510 Series" :interface "USB" :usbid "0x04b8" "0x0869" @@ -2837,47 +3148,77 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>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<br>all-in-one<br>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<br>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<br>all-in-one" + :model "WP-4511" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4515" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" :model "WP-4521" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4525" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4530 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4540 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete -:comment "network interface option supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>overseas version of the PX-B750F" :model "WP-4590 Series" :interface "USB" @@ -2895,7 +3236,7 @@ :interface "USB" :usbid "0x04b8" "0x0863" :status :complete -:comment "network interface (option) supported via DFSG non-free iscan-network-nt package<br>some models in the series have a built-in network interface<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>some models in the series have a built-in network interface<br>all-in-one" :model "WorkForce 435" :interface "USB" @@ -2985,19 +3326,25 @@ :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete -:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one<br>overseas version of the PX-047A" :model "XP-300 Series" :interface "USB" @@ -3009,7 +3356,13 @@ :interface "USB" :usbid "0x04b8" "0x08af" :status :complete -:comment "network interface supported via DFSG non-free iscan-network-nt package" +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one<br>overseas version of the PX-437A" :model "XP-400 Series" :interface "USB" @@ -3023,73 +3376,115 @@ :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package<br>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<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>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<br>all-in-one<br>overseas version of the EP-905F" -: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 - -:model "EP-976A3, XP-950" -:interface "USB" -:usbid "0x04b8" "0x08b3" -:status :good - -:model "EP-906F, XP-810" -:interface "USB" -:usbid "0x04b8" "0x08b4" -:status :good - -:model "EP-806A, XP-710" -:interface "USB" -:usbid "0x04b8" "0x08b5" -:status :good - -:model "EP-776A, XP-610" -:interface "USB" -:usbid "0x04b8" "0x08b6" -:status :good - -:model "EP-706A, XP-510" -:interface "USB" -:usbid "0x04b8" "0x08b7" -:status :good - -:model "LP-M8040, LP-M8040A, LP-M8040F" -:interface "USB" -:usbid "0x04b8" "0x08ad" -:status :good +:model "XP-860 Series" +:interface "USB" +:usbid "0x04b8" "0x08c6" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package<br>all-in-one<br>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<br>all-in-one<br>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 diff --git a/doc/descriptions/fujitsu.desc b/doc/descriptions/fujitsu.desc index e74a7f6..d4e232b 100644 --- a/doc/descriptions/fujitsu.desc +++ b/doc/descriptions/fujitsu.desc @@ -12,7 +12,7 @@ :backend "fujitsu" ; name of backend :url "http://www.thebility.com/fujitsu/" -:version "118" ; version of backend +:version "127" ; version of backend :manpage "sane-fujitsu" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.25, see sane-fujitsu manpage" :devicetype :scanner ; start of a list of devices.... @@ -167,9 +167,14 @@ :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 N1800" +:model "ScanSnap N7100" :interface "Ethernet" :status :untested :comment "small, current, integrated touchscreen and keyboard" @@ -203,6 +208,18 @@ :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" @@ -302,25 +319,25 @@ :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" +:comment "medium, recent, discontinued" :model "fi-6240Z" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x11f2" +:comment "medium, recent, discontinued" + +;================================================== +; CURRENT MODELS, MEDIUM + +:model "fi-5530C2" +:interface "SCSI USB" +:status :complete +:usbid "0x04c5" "0x114a" :comment "medium, current" :model "fi-7180" @@ -466,3 +483,8 @@ :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 :untested +;:usbid "0x04c5" "0x" diff --git a/doc/descriptions/genesys.desc b/doc/descriptions/genesys.desc index cb91476..6d400f2 100644 --- a/doc/descriptions/genesys.desc +++ b/doc/descriptions/genesys.desc @@ -148,7 +148,7 @@ :model "CanoScan LiDE 120" :interface "USB" :usbid "0x04a9" "0x190e" -:status :untested +:status :unsupported :comment "GL124+ based, resolution from 75 to 2400 dpi" :model "CanoScan LiDE 200" diff --git a/doc/descriptions/hp.desc b/doc/descriptions/hp.desc index 8a662c5..24f4f4a 100644 --- a/doc/descriptions/hp.desc +++ b/doc/descriptions/hp.desc @@ -10,9 +10,8 @@ ; :backend "hp" ; name of backend -:version "1.06" ; version of backend +:version "unmaintained" ; 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, @@ -58,27 +57,30 @@ :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" +: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" +:comment "Parallel interface requires ppscsi driver and epst module. Buttons may not work on some scanners" :model "ScanJet 6100C" :interface "SCSI" @@ -89,27 +91,32 @@ :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" diff --git a/doc/descriptions/magicolor.desc b/doc/descriptions/magicolor.desc index 3a7d9b0..be785e9 100644 --- a/doc/descriptions/magicolor.desc +++ b/doc/descriptions/magicolor.desc @@ -22,6 +22,12 @@ :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" diff --git a/doc/descriptions/mustek_usb2.desc b/doc/descriptions/mustek_usb2.desc index 011cef9..011cef9 100755..100644 --- a/doc/descriptions/mustek_usb2.desc +++ b/doc/descriptions/mustek_usb2.desc diff --git a/doc/descriptions/pieusb.desc b/doc/descriptions/pieusb.desc new file mode 100644 index 0000000..d3855a3 --- /dev/null +++ b/doc/descriptions/pieusb.desc @@ -0,0 +1,85 @@ +; +; 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" ; version of backend +: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" +:status :untested +:comment "Identical to Reflecta DigitDia 3600" + +:model "PowerSlide 3650" +:interface "USB" +:status :untested +:comment "Identical to Reflecta DigitDia 4000" + +:model "PowerSlide 4000" +:interface "USB" +:status :untested +:comment "Identical to Reflecta DigitDia 5000" + +:model "PowerSlide 5000" +:interface "USB" +:status :untested +:comment "Identical to Reflecta DigitDia 6000" + +:mfg "Reflecta" +:url "https://reflecta.de" + +:model "Reflecta ProScan 7200" +:interface "USB" +:usbid "0x05e3" "0x0145" +:status :basic +:comment "Similar to PrimeFilm 7250 scanner from Pacific Image Electronics" + +: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" +:status :untested +:comment "Identical to Pacific Image Electronics PowerSlide 3600 scanner" + +:model "DigitDia 4000" +:interface "USB" +:status :untested +:comment "Identical to Pacific Image Electronics PowerSlide 3650 scanner" + +:model "DigitDia 5000" +:interface "USB" +: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. diff --git a/doc/descriptions/pixma.desc b/doc/descriptions/pixma.desc index d34859a..5e38e76 100644 --- a/doc/descriptions/pixma.desc +++ b/doc/descriptions/pixma.desc @@ -11,7 +11,7 @@ ; See doc/descriptions.txt for details. :backend "pixma" ; name of backend -:version "0.17.18" ; version of backend (or "unmaintained") +:version "0.17.23" ; 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." @@ -118,6 +118,12 @@ :status :complete :comment "All resolutions supported (up to 1200DPI)." +:model "PIXMA MG3600 Series" +:interface "USB Ethernet WiFi" +:usbid "0x04a9" "0x178a" +:status :untested +:comment "Testers needed!" + :model "PIXMA MG4100 Series" :interface "USB" :usbid "0x04a9" "0x1753" @@ -209,10 +215,10 @@ :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG7500 Series" -:interface "USB" +:interface "USB Ethernet WiFi" :usbid "0x04a9" "0x177c" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG8100 Series" :interface "USB" @@ -632,8 +638,8 @@ :model "PIXMA MX470 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1774" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX490 Series" :interface "USB WiFi" diff --git a/doc/descriptions/stv680.desc b/doc/descriptions/stv680.desc index fee96d7..fee96d7 100755..100644 --- a/doc/descriptions/stv680.desc +++ b/doc/descriptions/stv680.desc diff --git a/doc/sane-apple.man b/doc/sane-apple.man index 2d388bf..7c55a5a 100644 --- a/doc/sane-apple.man +++ b/doc/sane-apple.man @@ -121,6 +121,7 @@ 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 @@ -240,8 +241,8 @@ and .TP .B Scan Make scanning possible for all models in all supported modes. -.TP -.B Missing Functionality +.PP +Add other missing functionality .SH "SEE ALSO" sane(7), sane\-scsi(5) diff --git a/doc/sane-canon_dr.man b/doc/sane-canon_dr.man index 6ac3fc3..3e8ac06 100644 --- a/doc/sane-canon_dr.man +++ b/doc/sane-canon_dr.man @@ -1,4 +1,4 @@ -.TH sane\-canon_dr 5 "16 Sep 2013" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" +.TH sane\-canon_dr 5 "31 Aug 2015" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-canon_dr .SH NAME @@ -10,7 +10,7 @@ The library implements a SANE (Scanner Access Now Easy) backend which provides access to some Canon DR-series scanners. -This document describes backend version 41, which shipped with SANE 1.0.24. +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 diff --git a/doc/sane-fujitsu.man b/doc/sane-fujitsu.man index e996802..29004d9 100644 --- a/doc/sane-fujitsu.man +++ b/doc/sane-fujitsu.man @@ -1,4 +1,4 @@ -.TH sane\-fujitsu 5 "17 Sep 2013" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" +.TH sane\-fujitsu 5 "31 Aug 2015" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-fujitsu .SH NAME @@ -10,13 +10,13 @@ The library implements a SANE (Scanner Access Now Easy) backend which provides access to most Fujitsu flatbed and ADF scanners. -This document describes backend version 117, which shipped with SANE 1.0.24. +This document describes backend version 127, which shipped with SANE 1.0.25. .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 iX5xx series scanners are supported. Please see the list at +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 @@ -215,7 +215,7 @@ Automatic length detection support funded by: Martin G. Miller mgmiller at optonline.net -Hardware donated, software image enhancement and fi-6xxx support funded by: +Hardware donated, software image enhancement and fi-6/7xxx support funded by: Fujitsu Computer Products of America, Inc. www.fcpa.com diff --git a/doc/sane-genesys.man b/doc/sane-genesys.man index 2acd717..ee3e0af 100644 --- a/doc/sane-genesys.man +++ b/doc/sane-genesys.man @@ -10,7 +10,7 @@ access to USB flatbed scanners based on the Genesys GL646, GL841, GL843, GL847 a 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 +Canon LiDE 35/40/50/60/100/110/200/210/220/700 .br Hewlett-Packard HP2300C/HP2400/HP3670/HP3690/G4010/G4050 .br diff --git a/doc/sane-mustek_pp.man b/doc/sane-mustek_pp.man index 1316cf2..253759d 100644 --- a/doc/sane-mustek_pp.man +++ b/doc/sane-mustek_pp.man @@ -486,5 +486,3 @@ also a worthy information. Please also include the optical resolution and lamp t .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. -.TP -.I some nice greetings diff --git a/doc/sane-pieusb.man b/doc/sane-pieusb.man new file mode 100644 index 0000000..e38e8e1 --- /dev/null +++ b/doc/sane-pieusb.man @@ -0,0 +1,111 @@ +.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 <kkaempf@suse.com> + +.SH AUTHORS +The pieusb backend is based on work by Jan Vleeshouwers, Michael +Rickmann, and Klaus Kämpf diff --git a/doc/sane-pixma.man b/doc/sane-pixma.man index ac1627e..8051688 100644 --- a/doc/sane-pixma.man +++ b/doc/sane-pixma.man @@ -1,4 +1,4 @@ -.TH "sane\-pixma" "5" "18 Mai 2015" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" +.TH "sane\-pixma" "5" "29 Jul 2015" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-pixma .SH NAME sane\-pixma \- SANE backend for Canon Multi-Function Printers and CanoScan Scanners @@ -19,7 +19,7 @@ PIXMA MG2100, MG2200, MG2400, MG2500, MG2900, MG3100, MG3200 .br PIXMA MG3500, MG4200, MG5100, MG5200, MG5300, MG5500, MG6100 .br -PIXMA MG6200, MG6300, MG6400, MG7100, MG8200 +PIXMA MG6200, MG6300, MG6400, MG7100, MG7500, MG8200 .br PIXMA MP140, MP150, MP160, MP170, MP180, MP190 .br @@ -41,9 +41,9 @@ PIXMA MP960, MP970, MP980, MP990 .br PIXMA MX300, MX310, MX330, MX340, MX350, MX360, MX370 .br -PIXMA MX410, MX420, MX510, MX520, MX530, MX700, MX720, MX7600 +PIXMA MX410, MX420, MX470, MX510, MX520, MX530, MX700, MX720 .br -PIXMA MX850, MX860, MX870, MX882, MX885, MX890, MX920 +PIXMA MX850, MX860, MX870, MX882, MX885, MX890, MX920, MX7600 .br imageCLASS MF3110, MF3240, MF4010, MF4018 .br @@ -81,11 +81,11 @@ Feedback in the sane\-devel mailing list welcome. .RS PIXMA E400, E460, E480, E500, E510, E560, E600, E610 .br -PIXMA MG4100, MG5400, MG5600, MG6500, MG6600, MG7500, MG8100 +PIXMA MG3600, MG4100, MG5400, MG5600, MG6500, MG6600, MG8100 .br PIXMA MP375R, MP493, MP495, MP740 .br -PIXMA MX320, MX390, MX430, MX450, MX470, MX490, MX710 +PIXMA MX320, MX390, MX430, MX450, MX490, MX710 .br imageCLASS MF810/820, MF5630, MF5650, MF5750, MF8030, MF8170c .br diff --git a/doc/saned.man b/doc/saned.man index 8721b15..5f7bc20 100644 --- a/doc/saned.man +++ b/doc/saned.man @@ -214,7 +214,19 @@ service sane\-port .ft R .RE .SH SYSTEMD CONFIGURATION -for systemd we need to add 2 configuation files in +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 configuation files in .I /etc/systemd/system. .PP The first file we need to add here is called @@ -257,23 +269,89 @@ Group=saned StandardInput=null StandardOutput=syslog StandardError=syslog -# Environment=SANE_CONFIG_DIR=@CONFIGDIR@ SANE_DEBUG_DLL=255 +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 -Is you need to set an environment variable for saned like +You need to set an environment variable for .B SANE_CONFIG_DIR -you will have to remove the # on the last line and set the variable -appropriately. Multiple variables can be set by separating the assignments -by spaces as shown in the example above. +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_<backend_name> -to be captured. With the service unit as described above, the debugging output is +, 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 configuation 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 diff --git a/doc/scanimage.man b/doc/scanimage.man index 79a1251..4d47eb8 100644 --- a/doc/scanimage.man +++ b/doc/scanimage.man @@ -42,7 +42,8 @@ command-line options. After command-line processing, 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) or in TIFF (black-and-white, grayscale or 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 @@ -103,9 +104,11 @@ The option selects how image data is written to standard output. .I format can be -.B pnm +.BR pnm , +.BR tiff , +.BR png , or -.BR tiff. +.BR jpeg . If .B \-\-format is not used, PNM is written. @@ -164,8 +167,8 @@ feeders. 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) -will be used. +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 @@ -262,9 +265,9 @@ level. .PP The .B \-B -or -.B \-\-buffer-size -changes the input buffer size from 32KB to the number kB specified or 1M. +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 diff --git a/frontend/Makefile.am b/frontend/Makefile.am index a501931..23061b3 100644 --- a/frontend/Makefile.am +++ b/frontend/Makefile.am @@ -18,7 +18,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include scanimage_SOURCES = scanimage.c stiff.c stiff.h scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ - ../lib/libfelib.la + ../lib/libfelib.la @PNG_LIBS@ @JPEG_LIBS@ saned_SOURCES = saned.c saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ diff --git a/frontend/Makefile.in b/frontend/Makefile.in index 18b9877..c157a8c 100644 --- a/frontend/Makefile.in +++ b/frontend/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -275,6 +275,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -291,6 +292,7 @@ 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_LIBS = @USB_LIBS@ @@ -357,7 +359,7 @@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include scanimage_SOURCES = scanimage.c stiff.c stiff.h scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ - ../lib/libfelib.la + ../lib/libfelib.la @PNG_LIBS@ @JPEG_LIBS@ saned_SOURCES = saned.c saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ @@ -533,14 +535,14 @@ distclean-compile: @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/frontend/scanimage.c b/frontend/scanimage.c index b1d2481..7f7c1f0 100644 --- a/frontend/scanimage.c +++ b/frontend/scanimage.c @@ -1,5 +1,6 @@ /* scanimage -- command line scanning utility Uses the SANE library. + Copyright (C) 2015 Rolf Bensch <rolf at bensch hyphen online dot de> Copyright (C) 1996, 1997, 1998 Andreas Beck and David Mosberger Copyright (C) 1999 - 2009 by the SANE Project -- See AUTHORS and ChangeLog @@ -41,6 +42,14 @@ #include <sys/types.h> #include <sys/stat.h> +#ifdef HAVE_LIBPNG +#include <png.h> +#endif + +#ifdef HAVE_LIBJPEG +#include <jpeglib.h> +#endif + #include "../include/_stdint.h" #include "../include/sane/sane.h" @@ -55,10 +64,6 @@ #define PATH_MAX 1024 #endif -#ifndef HAVE_ATEXIT -# define atexit(func) on_exit(func, 0) /* works for SunOS, at least */ -#endif - typedef struct { uint8_t *data; @@ -107,6 +112,8 @@ static struct option basic_options[] = { #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 */ @@ -135,7 +142,7 @@ static int accept_only_md5_auth = 0; static const char *icc_profile = NULL; static void fetch_options (SANE_Device * device); -static void scanimage_exit (void); +static void scanimage_exit (int); static SANE_Word tl_x = 0; static SANE_Word tl_y = 0; @@ -687,7 +694,7 @@ parse_scalar (const SANE_Option_Descriptor * opt, const char *str, fprintf (stderr, "%s: option --%s: bad option value (rest of option: %s)\n", prog_name, opt->name, str); - exit (1); + scanimage_exit (1); } str = end; @@ -796,7 +803,7 @@ parse_vector (const SANE_Option_Descriptor * opt, const char *str, { fprintf (stderr, "%s: option --%s: closing bracket missing " "(rest of option: %s)\n", prog_name, opt->name, str); - exit (1); + scanimage_exit (1); } str = end + 1; } @@ -808,20 +815,20 @@ parse_vector (const SANE_Option_Descriptor * opt, const char *str, fprintf (stderr, "%s: option --%s: index %d out of range [0..%ld]\n", prog_name, opt->name, index, (long) vector_length - 1); - exit (1); + scanimage_exit (1); } /* read value */ str = parse_scalar (opt, str, &value); if (!str) - exit (1); + scanimage_exit (1); if (*str && *str != '-' && *str != ',') { fprintf (stderr, "%s: option --%s: illegal separator (rest of option: %s)\n", prog_name, opt->name, str); - exit (1); + scanimage_exit (1); } /* store value: */ @@ -874,7 +881,7 @@ fetch_options (SANE_Device * device) if (opt == NULL) { fprintf (stderr, "Could not get option descriptor for option 0\n"); - exit (1); + scanimage_exit (1); } status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE, @@ -883,7 +890,7 @@ fetch_options (SANE_Device * device) { fprintf (stderr, "Could not get value for option 0: %s\n", sane_strstatus (status)); - exit (1); + scanimage_exit (1); } /* build the full table of long options */ @@ -894,7 +901,7 @@ fetch_options (SANE_Device * device) if (opt == NULL) { fprintf (stderr, "Could not get option descriptor for option %d\n",i); - exit (1); + scanimage_exit (1); } /* create command line option only for settable options */ @@ -1013,7 +1020,7 @@ set_option (SANE_Handle device, int optnum, void *valuep) { fprintf (stderr, "%s: setting of option --%s failed (%s)\n", prog_name, opt->name, sane_strstatus (status)); - exit (1); + scanimage_exit (1); } if ((info & SANE_INFO_INEXACT) && opt->size == sizeof (SANE_Word)) @@ -1048,7 +1055,7 @@ process_backend_option (SANE_Handle device, int optnum, const char *optarg) { fprintf (stderr, "%s: attempted to set inactive option %s\n", prog_name, opt->name); - exit (1); + scanimage_exit (1); } if ((opt->cap & SANE_CAP_AUTOMATIC) && optarg && @@ -1061,7 +1068,7 @@ process_backend_option (SANE_Handle device, int optnum, const char *optarg) fprintf (stderr, "%s: failed to set option --%s to automatic (%s)\n", prog_name, opt->name, sane_strstatus (status)); - exit (1); + scanimage_exit (1); } return; } @@ -1081,7 +1088,7 @@ process_backend_option (SANE_Handle device, int optnum, const char *optarg) { fprintf (stderr, "%s: option --%s: bad option value `%s'\n", prog_name, opt->name, optarg); - exit (1); + scanimage_exit (1); } } break; @@ -1097,7 +1104,7 @@ process_backend_option (SANE_Handle device, int optnum, const char *optarg) if (!vector) { fprintf (stderr, "%s: out of memory\n", prog_name); - exit (1); + scanimage_exit (1); } } parse_vector (opt, optarg, vector, vector_length); @@ -1109,7 +1116,7 @@ process_backend_option (SANE_Handle device, int optnum, const char *optarg) if (!valuep) { fprintf (stderr, "%s: out of memory\n", prog_name); - exit (1); + scanimage_exit (1); } strncpy (valuep, optarg, opt->size); ((char *) valuep)[opt->size - 1] = 0; @@ -1156,6 +1163,79 @@ write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp #endif } +#ifdef HAVE_LIBPNG +static void +write_png_header (SANE_Frame format, int width, int height, int depth, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr) +{ + int color_type; + + *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_write_info(*png_ptr, *info_ptr); +} +#endif + +#ifdef HAVE_LIBJPEG +static void +write_jpeg_header (SANE_Frame format, int width, int height, 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_quality(cinfo, 75, TRUE); + jpeg_start_compress(cinfo, TRUE); +} +#endif + static void * advance (Image * image) { @@ -1199,6 +1279,18 @@ scan_it (FILE *ofp) }; 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 { @@ -1237,12 +1329,12 @@ scan_it (FILE *ofp) fprintf (stderr, "%s: scanning image of size %dx%d pixels at " "%d bits/pixel\n", prog_name, parm.pixels_per_line, parm.lines, - 8 * parm.bytes_per_line / parm.pixels_per_line); + 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, - 8 * parm.bytes_per_line / parm.pixels_per_line); + parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1)); } fprintf (stderr, "%s: acquiring %s frame\n", prog_name, @@ -1272,21 +1364,44 @@ scan_it (FILE *ofp) offset = 0; } else - { - if (output_format == OUTPUT_TIFF) + 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); - else + 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, ofp, &png_ptr, &info_ptr); + break; +#endif +#ifdef HAVE_LIBJPEG + case OUTPUT_JPEG: + write_jpeg_header (parm.format, parm.pixels_per_line, + parm.lines, 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) { @@ -1400,6 +1515,59 @@ scan_it (FILE *ofp) } 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]; + } + 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 @@ -1454,13 +1622,29 @@ scan_it (FILE *ofp) { image.height = image.y; - if (output_format == OUTPUT_TIFF) + 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); - else + 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, ofp, &png_ptr, &info_ptr); + break; +#endif +#ifdef HAVE_LIBJPEG + case OUTPUT_JPEG: + write_jpeg_header (parm.format, parm.pixels_per_line, + parm.lines, ofp, &cinfo, &jerr); + break; +#endif + } #if !defined(WORDS_BIGENDIAN) /* multibyte pnm file may need byte swap to LE */ @@ -1480,11 +1664,31 @@ scan_it (FILE *ofp) 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); @@ -1565,12 +1769,12 @@ test_it (void) 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, - 8 * parm.bytes_per_line / parm.pixels_per_line); + 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, - 8 * parm.bytes_per_line / 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); @@ -1648,7 +1852,7 @@ get_resolution (void) } static void -scanimage_exit (void) +scanimage_exit (int status) { if (device) { @@ -1666,6 +1870,7 @@ scanimage_exit (void) free (option_number); if (verbose > 1) fprintf (stderr, "scanimage: finished\n"); + exit (status); } /** @brief print device options to stdout @@ -1721,8 +1926,6 @@ main (int argc, char **argv) SANE_Int version_code; FILE *ofp = NULL; - atexit (scanimage_exit); - buffer_size = (32 * 1024); /* default size */ prog_name = strrchr (argv[0], '/'); @@ -1803,6 +2006,24 @@ main (int argc, char **argv) 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; @@ -1819,7 +2040,7 @@ main (int argc, char **argv) { fprintf (stderr, "%s: sane_get_devices() failed: %s\n", prog_name, sane_strstatus (status)); - exit (1); + scanimage_exit (1); } if (ch == 'L') @@ -1916,7 +2137,7 @@ main (int argc, char **argv) if (defdevname) printf ("default device is `%s'\n", defdevname); - exit (0); + scanimage_exit (0); } case 'V': @@ -1924,7 +2145,7 @@ main (int argc, char **argv) VERSION, SANE_VERSION_MAJOR (version_code), SANE_VERSION_MINOR (version_code), SANE_VERSION_BUILD (version_code)); - exit (0); + scanimage_exit (0); default: break; /* ignore device specific options for now */ @@ -1941,7 +2162,7 @@ standard output.\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 file format of output file\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\ @@ -1949,8 +2170,8 @@ Parameters are separated by a blank from single-character options (e.g.\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' or\n\ - `out%%d.tif' by default depending on --format\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\ @@ -1985,12 +2206,12 @@ Parameters are separated by a blank from single-character options (e.g.\n\ { fprintf (stderr, "%s: sane_get_devices() failed: %s\n", prog_name, sane_strstatus (status)); - exit (1); + scanimage_exit (1); } if (!device_list[0]) { fprintf (stderr, "%s: no SANE devices found\n", prog_name); - exit (1); + scanimage_exit (1); } devname = device_list[0]->name; } @@ -2012,7 +2233,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ if (help) device = 0; else - exit (1); + scanimage_exit (1); } if (device) @@ -2025,7 +2246,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ { fprintf (stderr, "%s: unable to get option count descriptor\n", prog_name); - exit (1); + scanimage_exit (1); } /* We got a device, find out how many options it has */ @@ -2035,7 +2256,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ { fprintf (stderr, "%s: unable to determine option count\n", prog_name); - exit (1); + scanimage_exit (1); } /* malloc global option lists */ @@ -2047,7 +2268,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ { fprintf (stderr, "%s: out of memory in main()\n", prog_name); - exit (1); + scanimage_exit (1); } /* load global option lists */ @@ -2078,7 +2299,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ if (!full_optstring) { fprintf (stderr, "%s: out of memory\n", prog_name); - exit (1); + scanimage_exit (1); } strcpy (full_optstring, BASE_OPTSTRING); @@ -2099,7 +2320,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ { case ':': case '?': - exit (1); /* error message is printed by getopt_long() */ + scanimage_exit (1); /* error message is printed by getopt_long() */ case 'd': case 'h': @@ -2139,7 +2360,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ fprintf (stderr, "%s: argument without option: `%s'; ", prog_name, argv[argc - 1]); fprintf (stderr, "try %s --help\n", prog_name); - exit (1); + scanimage_exit (1); } free (full_optstring); @@ -2172,7 +2393,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\ { printf ("\nAll options specific to device `%s':\n", devname); print_options(device, num_dev_options, SANE_TRUE); - exit (0); + scanimage_exit (0); } } @@ -2205,11 +2426,11 @@ List of available devices:", prog_name); } } fputc ('\n', stdout); - exit (0); + scanimage_exit (0); } if (dont_scan) - exit (0); + scanimage_exit (0); if (output_format != OUTPUT_PNM) resolution_value = get_resolution (); @@ -2229,10 +2450,24 @@ List of available devices:", prog_name); if (batch && NULL == format) { - if (output_format == OUTPUT_TIFF) + switch(output_format) { + case OUTPUT_TIFF: format = "out%d.tif"; - else + 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) @@ -2245,7 +2480,7 @@ List of available devices:", prog_name); else if(isatty(fileno(ofp))){ fprintf (stderr,"%s: output is not a file, exiting\n", prog_name); - exit (1); + scanimage_exit (1); } buffer = malloc (buffer_size); @@ -2388,5 +2623,7 @@ List of available devices:", prog_name); else status = test_it (); + scanimage_exit (status); + /* the line below avoids compiler warnings */ return status; } diff --git a/frontend/tstbackend.c b/frontend/tstbackend.c index 6dcd940..82c54dc 100644 --- a/frontend/tstbackend.c +++ b/frontend/tstbackend.c @@ -46,6 +46,7 @@ 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'} @@ -1134,7 +1135,7 @@ static void test_scan(SANE_Handle device) unsigned char *image = NULL; SANE_Parameters params; size_t to_read; - SANE_Int len; + SANE_Int len=0; int ask_len; int rc; int fd; @@ -1660,12 +1661,22 @@ SANE_Status status; 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] [-r recursion_level] [-g time (s)]\n", 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"); } @@ -1684,6 +1695,7 @@ main (int argc, char **argv) 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"); @@ -1696,8 +1708,9 @@ main (int argc, char **argv) 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", basic_options, + while ((ch = getopt_long (argc, argv, "-v:d:l:r:g:h:s", basic_options, &index)) != EOF) { switch(ch) { case 'v': @@ -1716,6 +1729,10 @@ main (int argc, char **argv) } break; + case 's': + default_scan = 1; + break; + case 'r': recursion_level = atoi(optarg); break; @@ -1824,6 +1841,10 @@ main (int argc, char **argv) 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); } diff --git a/include/Makefile.am b/include/Makefile.am index 5650e7f..c949491 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -15,4 +15,4 @@ EXTRA_DIST += sane/config.h.in sane/sanei.h sane/sanei_ab306.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_wire.h sane/sanei_magic.h sane/sanei_ir.h diff --git a/include/Makefile.in b/include/Makefile.in index a445d84..a542068 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -253,6 +253,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -269,6 +270,7 @@ 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_LIBS = @USB_LIBS@ @@ -342,7 +344,8 @@ EXTRA_DIST = lalloca.h lassert.h lgetopt.h md5.h font_6x11.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_usb.h sane/sanei_wire.h sane/sanei_magic.h \ + sane/sanei_ir.h all: all-am .SUFFIXES: diff --git a/include/sane/config.h.in b/include/sane/config.h.in index c62938b..8549c46 100644 --- a/include/sane/config.h.in +++ b/include/sane/config.h.in @@ -61,9 +61,6 @@ /* Define to 1 if you have the `cfmakeraw' function. */ #undef HAVE_CFMAKERAW -/* Is /usr/include/cups/cups.h available? */ -#undef HAVE_CUPS - /* Define to 1 if you have the <ddk/ntddscsi.h> header file. */ #undef HAVE_DDK_NTDDSCSI_H @@ -454,9 +451,6 @@ */ #undef LT_OBJDIR -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - /* Define to the name of the distribution. */ #undef PACKAGE @@ -490,6 +484,9 @@ /* SANE DLL minor number */ #undef SANE_DLL_V_MINOR +/* Define to 1 if you have the <sys/io.h> providing inb,outb. */ +#undef SANE_HAVE_SYS_IO_H_WITH_INB_OUTB + /* SCSI command buffer size */ #undef SCSIBUFFERSIZE diff --git a/include/sane/sanei_ir.h b/include/sane/sanei_ir.h new file mode 100644 index 0000000..aaca524 --- /dev/null +++ b/include/sane/sanei_ir.h @@ -0,0 +1,393 @@ +/** @file sanei_ir.h + * + * This file provides an interface to the + * sanei_ir functions for utilizing the infrared plane + * + * Copyright (C) 2012 Michael Rickmann <mrickma@gwdg.de> + * + * 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 <stdint.h> + +#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 */ diff --git a/japi/Makefile.in b/japi/Makefile.in index 550bd8d..85d6283 100644 --- a/japi/Makefile.in +++ b/japi/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -291,6 +291,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -307,6 +308,7 @@ 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_LIBS = @USB_LIBS@ @@ -481,14 +483,14 @@ distclean-compile: @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/lib/Makefile.in b/lib/Makefile.in index ee46c65..affdb74 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -260,6 +260,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -276,6 +277,7 @@ 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_LIBS = @USB_LIBS@ @@ -428,14 +430,14 @@ distclean-compile: @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -10,6 +10,7 @@ es fi fr gl +hu it ja nb diff --git a/po/Makefile.am b/po/Makefile.am index c79b149..d757b11 100644 --- a/po/Makefile.am +++ b/po/Makefile.am @@ -69,7 +69,7 @@ clean-local: $(GETTEXT_PACKAGE).pot: $(SRC_FILES) @echo "creating $@ from $^" - @$(XGETTEXT) -d$(GETTEXT_PACKAGE) -kSANE_I18N --flag=SANE_I18N:1:no-c-format -f POTFILES + @$(XGETTEXT) -d$(GETTEXT_PACKAGE) -kSANE_I18N --flag=SANE_I18N:1:no-c-format -f $(srcdir)/POTFILES -D$(srcdir) @mv $(GETTEXT_PACKAGE).po $(GETTEXT_PACKAGE).pot update: $(GETTEXT_PACKAGE).pot diff --git a/po/Makefile.in b/po/Makefile.in index c9a984d..a0fa1af 100644 --- a/po/Makefile.in +++ b/po/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -208,6 +208,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -224,6 +225,7 @@ 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_LIBS = @USB_LIBS@ @@ -527,7 +529,7 @@ clean-local: $(GETTEXT_PACKAGE).pot: $(SRC_FILES) @echo "creating $@ from $^" - @$(XGETTEXT) -d$(GETTEXT_PACKAGE) -kSANE_I18N --flag=SANE_I18N:1:no-c-format -f POTFILES + @$(XGETTEXT) -d$(GETTEXT_PACKAGE) -kSANE_I18N --flag=SANE_I18N:1:no-c-format -f $(srcdir)/POTFILES -D$(srcdir) @mv $(GETTEXT_PACKAGE).po $(GETTEXT_PACKAGE).pot update: $(GETTEXT_PACKAGE).pot diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000..9a6391c --- /dev/null +++ b/po/hu.po @@ -0,0 +1,4742 @@ +# 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 <saga@chello.hu>, 2003, 2004. +# Németh Tamás <ntomasz@uhuklub.hu>, 2011. +msgid "" +msgstr "" +"Project-Id-Version: sane-backends\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-04-06 19:07+0200\n" +"PO-Revision-Date: 2011-04-06 19:50+0200\n" +"Last-Translator: Németh Tamás <ntomasz@uhuklub.hu>\n" +"Language-Team: Hungarian <NONE>\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:3284 ../backend/epson2.c:1269 ../backend/genesys.c:6024 +#: ../backend/gt68xx.c:703 ../backend/hp3500.c:975 ../backend/hp-option.c:3297 +#: ../backend/leo.c:823 ../backend/lexmark.c:199 ../backend/ma1509.c:551 +#: ../backend/matsushita.c:1135 ../backend/microtek2.h:599 +#: ../backend/mustek.c:4363 ../backend/mustek_usb.c:305 +#: ../backend/mustek_usb2.c:465 ../backend/pixma_sane_options.c:144 +#: ../backend/plustek.c:807 ../backend/plustek_pp.c:746 +#: ../backend/sceptre.c:702 ../backend/snapscan-options.c:494 +#: ../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:1492 ../backend/genesys.c:6084 ../backend/gt68xx.c:672 +#: ../backend/hp-option.c:2953 ../backend/leo.c:871 ../backend/ma1509.c:599 +#: ../backend/matsushita.c:1189 ../backend/microtek2.h:600 +#: ../backend/mustek.c:4411 ../backend/mustek_usb.c:353 +#: ../backend/mustek_usb2.c:431 ../backend/niash.c:756 +#: ../backend/plustek.c:853 ../backend/plustek_pp.c:792 +#: ../backend/sceptre.c:750 ../backend/snapscan-options.c:561 +#: ../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:3183 +#: ../backend/epson2.c:1194 ../backend/rts8891.c:2792 +#: ../backend/snapscan-options.c:816 ../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:1143 ../backend/leo.c:781 +#: ../backend/pixma_sane_options.c:40 +#, 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:1219 +#, 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 +#, 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:235 ../backend/plustek_pp.c:202 ../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:1610 +#, 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:781 +#, no-c-format +msgid "Number of the frame to scan" +msgstr "" + +#: ../backend/avision.h:782 +#, no-c-format +msgid "Selects the number of the frame to scan" +msgstr "" + +#: ../backend/avision.h:785 +#, fuzzy, no-c-format +msgid "Duplex scan" +msgstr "Teljes szkennelés" + +#: ../backend/avision.h:786 +#, no-c-format +msgid "Duplex scan provide a scan of the front and back side of the document" +msgstr "" + +#: ../backend/canon630u.c:158 +#, no-c-format +msgid "Calibrate Scanner" +msgstr "Szkenner kalibrálása" + +#: ../backend/canon630u.c:159 +#, no-c-format +msgid "Force scanner calibration before scan" +msgstr "" + +#: ../backend/canon630u.c:258 ../backend/umax1220u.c:208 +#, no-c-format +msgid "Grayscale scan" +msgstr "Szürkeskálás szkennelés" + +#: ../backend/canon630u.c:259 ../backend/umax1220u.c:209 +#, no-c-format +msgid "Do a grayscale rather than color scan" +msgstr "" + +#: ../backend/canon630u.c:305 +#, no-c-format +msgid "Analog Gain" +msgstr "Analóg erÅ‘sÃtés" + +#: ../backend/canon630u.c:306 +#, no-c-format +msgid "Increase or decrease the analog gain of the CCD array" +msgstr "" + +#: ../backend/canon630u.c:346 ../backend/epson.h:68 ../backend/epson2.h:72 +#, no-c-format +msgid "Gamma Correction" +msgstr "Gamma korrekció" + +#: ../backend/canon630u.c:347 +#, no-c-format +msgid "Selects the gamma corrected transfer curve" +msgstr "" + +#: ../backend/canon.c:149 ../backend/canon-sane.c:1323 +#, 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:1318 ../backend/canon-sane.c:1487 +#: ../backend/canon-sane.c:1636 +#, 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/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:372 +#, no-c-format +msgid "rounded parameter" +msgstr "" + +#: ../backend/canon.c:375 ../backend/canon.c:391 ../backend/canon.c:426 +#: ../backend/canon.c:476 ../backend/canon.c:494 ../backend/canon.c:537 +#, no-c-format +msgid "unknown" +msgstr "ismeretlen" + +#: ../backend/canon.c:385 +#, fuzzy, no-c-format +msgid "ADF jam" +msgstr "ADF" + +#: ../backend/canon.c:388 +#, no-c-format +msgid "ADF cover open" +msgstr "" + +#: ../backend/canon.c:401 +#, fuzzy, no-c-format +msgid "lamp failure" +msgstr "Gamma érték" + +#: ../backend/canon.c:404 +#, no-c-format +msgid "scan head positioning error" +msgstr "" + +#: ../backend/canon.c:407 +#, no-c-format +msgid "CPU check error" +msgstr "" + +#: ../backend/canon.c:410 +#, no-c-format +msgid "RAM check error" +msgstr "" + +#: ../backend/canon.c:413 +#, no-c-format +msgid "ROM check error" +msgstr "" + +#: ../backend/canon.c:416 +#, no-c-format +msgid "hardware check error" +msgstr "" + +#: ../backend/canon.c:419 +#, no-c-format +msgid "transparency unit lamp failure" +msgstr "" + +#: ../backend/canon.c:422 +#, no-c-format +msgid "transparency unit scan head positioning failure" +msgstr "" + +#: ../backend/canon.c:436 +#, no-c-format +msgid "parameter list length error" +msgstr "" + +#: ../backend/canon.c:440 +#, no-c-format +msgid "invalid command operation code" +msgstr "" + +#: ../backend/canon.c:444 +#, no-c-format +msgid "invalid field in CDB" +msgstr "" + +#: ../backend/canon.c:448 +#, no-c-format +msgid "unsupported LUN" +msgstr "" + +#: ../backend/canon.c:452 +#, no-c-format +msgid "invalid field in parameter list" +msgstr "" + +#: ../backend/canon.c:456 +#, no-c-format +msgid "command sequence error" +msgstr "" + +#: ../backend/canon.c:460 +#, no-c-format +msgid "too many windows specified" +msgstr "" + +#: ../backend/canon.c:464 +#, no-c-format +msgid "medium not present" +msgstr "" + +#: ../backend/canon.c:468 +#, no-c-format +msgid "invalid bit IDENTIFY message" +msgstr "" + +#: ../backend/canon.c:472 +#, no-c-format +msgid "option not connect" +msgstr "" + +#: ../backend/canon.c:486 +#, no-c-format +msgid "power on reset / bus device reset" +msgstr "" + +#: ../backend/canon.c:490 +#, no-c-format +msgid "parameter changed by another initiator" +msgstr "" + +#: ../backend/canon.c:504 +#, no-c-format +msgid "no additional sense information" +msgstr "" + +#: ../backend/canon.c:508 +#, no-c-format +msgid "reselect failure" +msgstr "" + +#: ../backend/canon.c:512 +#, no-c-format +msgid "SCSI parity error" +msgstr "" + +#: ../backend/canon.c:516 +#, no-c-format +msgid "initiator detected error message received" +msgstr "" + +#: ../backend/canon.c:521 +#, no-c-format +msgid "invalid message error" +msgstr "" + +#: ../backend/canon.c:525 +#, no-c-format +msgid "timeout error" +msgstr "" + +#: ../backend/canon.c:529 +#, no-c-format +msgid "transparency unit shading error" +msgstr "" + +#: ../backend/canon.c:533 +#, no-c-format +msgid "lamp not stabilized" +msgstr "" + +#: ../backend/canon.c:547 +#, no-c-format +msgid "problem not analyzed (unknown SCSI class)" +msgstr "" + +#: ../backend/canon.c:865 ../backend/canon.c:880 +#, fuzzy, no-c-format +msgid "film scanner" +msgstr "lapolvasó" + +#: ../backend/canon.c:895 ../backend/canon.c:910 ../backend/canon.c:925 +#: ../backend/hp3900_sane.c:1683 ../backend/plustek.c:1334 +#: ../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:1181 ../backend/epson.c:3372 ../backend/epson2.c:1343 +#, no-c-format +msgid "Film type" +msgstr "FilmtÃpus" + +#: ../backend/canon.c:1182 +#, no-c-format +msgid "Selects the film type, i.e. negatives or slides" +msgstr "" + +#: ../backend/canon.c:1194 +#, fuzzy, no-c-format +msgid "Negative film type" +msgstr "NegatÃv film" + +#: ../backend/canon.c:1195 +#, no-c-format +msgid "Selects the negative film type" +msgstr "" + +#: ../backend/canon.c:1234 +#, no-c-format +msgid "Hardware resolution" +msgstr "Eszköz felbontása" + +#: ../backend/canon.c:1235 +#, no-c-format +msgid "Use only hardware resolutions" +msgstr "" + +#: ../backend/canon.c:1316 +#, no-c-format +msgid "Focus" +msgstr "" + +#: ../backend/canon.c:1326 +#, no-c-format +msgid "Auto focus" +msgstr "" + +#: ../backend/canon.c:1327 +#, no-c-format +msgid "Enable/disable auto focus" +msgstr "" + +#: ../backend/canon.c:1334 +#, no-c-format +msgid "Auto focus only once" +msgstr "" + +#: ../backend/canon.c:1335 +#, no-c-format +msgid "Do auto focus only once between ejects" +msgstr "" + +#: ../backend/canon.c:1343 +#, no-c-format +msgid "Manual focus position" +msgstr "" + +#: ../backend/canon.c:1344 +#, no-c-format +msgid "Set the optical system's focus position by hand (default: 128)." +msgstr "" + +#: ../backend/canon.c:1354 +#, no-c-format +msgid "Scan margins" +msgstr "" + +#: ../backend/canon.c:1401 +#, no-c-format +msgid "Extra color adjustments" +msgstr "" + +#: ../backend/canon.c:1532 ../backend/epson.c:3191 ../backend/epson2.c:1233 +#, no-c-format +msgid "Mirror image" +msgstr "Kép tükrözése" + +#: ../backend/canon.c:1533 +#, fuzzy, no-c-format +msgid "Mirror the image horizontally" +msgstr "A kép vÃzszintes tükrözése." + +#: ../backend/canon.c:1602 +#, no-c-format +msgid "Auto exposure" +msgstr "" + +#: ../backend/canon.c:1603 +#, no-c-format +msgid "Enable/disable the auto exposure feature" +msgstr "" + +#: ../backend/canon.c:1619 +#, fuzzy, no-c-format +msgid "Calibration now" +msgstr "Kalibráció" + +#: ../backend/canon.c:1620 +#, fuzzy, no-c-format +msgid "Execute calibration *now*" +msgstr "PrecÃz beállÃtás" + +#: ../backend/canon.c:1630 +#, no-c-format +msgid "Self diagnosis" +msgstr "" + +#: ../backend/canon.c:1631 +#, no-c-format +msgid "Perform scanner self diagnosis" +msgstr "" + +#: ../backend/canon.c:1642 +#, fuzzy, no-c-format +msgid "Reset scanner" +msgstr "lapolvasó" + +#: ../backend/canon.c:1643 +#, fuzzy, no-c-format +msgid "Reset the scanner" +msgstr "lapolvasó" + +#: ../backend/canon.c:1653 +#, no-c-format +msgid "Medium handling" +msgstr "" + +#: ../backend/canon.c:1662 +#, no-c-format +msgid "Eject film after each scan" +msgstr "" + +#: ../backend/canon.c:1663 +#, no-c-format +msgid "Automatically eject the film from the device after each scan" +msgstr "" + +#: ../backend/canon.c:1672 +#, no-c-format +msgid "Eject film before exit" +msgstr "" + +#: ../backend/canon.c:1673 +#, no-c-format +msgid "Automatically eject the film from the device before exiting the program" +msgstr "" + +#: ../backend/canon.c:1682 +#, no-c-format +msgid "Eject film now" +msgstr "" + +#: ../backend/canon.c:1683 +#, no-c-format +msgid "Eject the film *now*" +msgstr "" + +#: ../backend/canon.c:1692 +#, no-c-format +msgid "Document feeder extras" +msgstr "" + +#: ../backend/canon.c:1699 +#, no-c-format +msgid "Flatbed only" +msgstr "Csak sÃkágyas" + +#: ../backend/canon.c:1700 +#, no-c-format +msgid "Disable auto document feeder and use flatbed only" +msgstr "" + +#: ../backend/canon.c:1710 ../backend/canon.c:1720 +#, fuzzy, no-c-format +msgid "Transparency unit" +msgstr "Ãtlátszó" + +#: ../backend/canon.c:1721 +#, no-c-format +msgid "Switch on/off the transparency unit (FAU, film adapter unit)" +msgstr "" + +#: ../backend/canon.c:1731 +#, fuzzy, no-c-format +msgid "Negative film" +msgstr "NegatÃv film" + +#: ../backend/canon.c:1732 +#, fuzzy, no-c-format +msgid "Positive or negative film" +msgstr "PozitÃv film" + +#: ../backend/canon.c:1741 +#, no-c-format +msgid "Density control" +msgstr "" + +#: ../backend/canon.c:1742 +#, no-c-format +msgid "Set density control mode" +msgstr "" + +#: ../backend/canon.c:1753 +#, fuzzy, no-c-format +msgid "Transparency ratio" +msgstr "Ãtlátszó" + +#: ../backend/canon.c:1767 +#, fuzzy, no-c-format +msgid "Select film type" +msgstr "FilmtÃpus" + +#: ../backend/canon.c:1768 +#, no-c-format +msgid "Select the film type" +msgstr "" + +#: ../backend/canon_dr.c:330 ../backend/epjitsu.c:203 ../backend/epson.c:501 +#: ../backend/epson2.c:110 ../backend/fujitsu.c:548 ../backend/gt68xx.c:148 +#: ../backend/hp3900_sane.c:418 ../backend/hp3900_sane.c:427 +#: ../backend/hp3900_sane.c:1017 ../backend/hp5590.c:82 +#: ../backend/ma1509.c:108 ../backend/magicolor.c:163 ../backend/mustek.c:156 +#: ../backend/mustek.c:160 ../backend/mustek.c:164 ../backend/pixma.c:664 +#: ../backend/pixma_sane_options.c:85 ../backend/snapscan-options.c:82 +#: ../backend/test.c:192 ../backend/umax.c:181 +#, no-c-format +msgid "Flatbed" +msgstr "SÃkágyas" + +#: ../backend/canon_dr.c:331 ../backend/epjitsu.c:204 ../backend/fujitsu.c:549 +#: ../backend/kodak.c:135 +#, no-c-format +msgid "ADF Front" +msgstr "" + +#: ../backend/canon_dr.c:332 ../backend/epjitsu.c:205 ../backend/fujitsu.c:550 +#: ../backend/kodak.c:136 +#, no-c-format +msgid "ADF Back" +msgstr "" + +#: ../backend/canon_dr.c:333 ../backend/epjitsu.c:206 ../backend/fujitsu.c:551 +#: ../backend/kodak.c:137 ../backend/hp5590.c:84 ../backend/pixma.c:675 +#, no-c-format +msgid "ADF Duplex" +msgstr "" + +#: ../backend/canon_dr.c:340 ../backend/epson.c:599 ../backend/epson.c:3082 +#: ../backend/epson2.c:195 ../backend/fujitsu.c:568 ../backend/genesys.c:106 +#: ../backend/genesys.c:113 ../backend/gt68xx_low.h:136 +#: ../backend/hp-option.c:3093 +#, no-c-format +msgid "Red" +msgstr "Vörös" + +#: ../backend/canon_dr.c:341 ../backend/epson.c:600 ../backend/epson.c:3078 +#: ../backend/epson2.c:196 ../backend/fujitsu.c:569 ../backend/genesys.c:107 +#: ../backend/genesys.c:114 ../backend/gt68xx_low.h:137 +#: ../backend/hp-option.c:3094 +#, no-c-format +msgid "Green" +msgstr "Zöld" + +#: ../backend/canon_dr.c:342 ../backend/epson.c:601 ../backend/epson.c:3086 +#: ../backend/epson2.c:197 ../backend/fujitsu.c:570 ../backend/genesys.c:108 +#: ../backend/genesys.c:115 ../backend/gt68xx_low.h:138 +#: ../backend/hp-option.c:3095 +#, no-c-format +msgid "Blue" +msgstr "Kék" + +#: ../backend/canon_dr.c:343 +#, fuzzy, no-c-format +msgid "Enhance Red" +msgstr "Haladó" + +#: ../backend/canon_dr.c:344 +#, fuzzy, no-c-format +msgid "Enhance Green" +msgstr "Haladó" + +#: ../backend/canon_dr.c:345 +#, fuzzy, no-c-format +msgid "Enhance Blue" +msgstr "Haladó" + +#: ../backend/canon_dr.c:347 ../backend/epson.c:556 ../backend/epson.c:564 +#: ../backend/epson.c:576 ../backend/epson.c:598 ../backend/epson2.c:159 +#: ../backend/epson2.c:167 ../backend/epson2.c:179 ../backend/epson2.c:194 +#: ../backend/epson2.c:208 ../backend/fujitsu.c:574 ../backend/genesys.c:116 +#: ../backend/leo.c:109 ../backend/matsushita.c:138 +#: ../backend/matsushita.c:159 ../backend/matsushita.c:191 +#: ../backend/matsushita.c:213 ../backend/snapscan-options.c:87 +#, no-c-format +msgid "None" +msgstr "Nincs" + +#: ../backend/canon_dr.c:348 ../backend/fujitsu.c:575 +#, no-c-format +msgid "JPEG" +msgstr "" + +#: ../backend/epson.c:491 ../backend/epson2.c:103 ../backend/magicolor.c:156 +#, no-c-format +msgid "Simplex" +msgstr "" + +#: ../backend/epson.c:492 ../backend/epson2.c:104 ../backend/magicolor.c:157 +#: ../backend/matsushita.h:218 +#, no-c-format +msgid "Duplex" +msgstr "" + +#: ../backend/epson.c:502 ../backend/epson2.c:111 ../backend/pixma.c:681 +#, no-c-format +msgid "Transparency Unit" +msgstr "" + +#: ../backend/epson.c:503 ../backend/epson2.c:112 ../backend/magicolor.c:164 +#: ../backend/mustek.c:160 ../backend/pixma.c:669 ../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:128 +#, no-c-format +msgid "Positive Film" +msgstr "PozitÃv film" + +#: ../backend/epson.c:524 ../backend/epson2.c:129 +#, no-c-format +msgid "Negative Film" +msgstr "NegatÃv film" + +#: ../backend/epson.c:529 ../backend/epson2.c:136 +#, no-c-format +msgid "Focus on glass" +msgstr "Fókusz az üvegen" + +#: ../backend/epson.c:530 ../backend/epson2.c:137 +#, 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:160 ../backend/epson2.c:168 ../backend/epson2.c:180 +#, no-c-format +msgid "Halftone A (Hard Tone)" +msgstr "" + +#: ../backend/epson.c:558 ../backend/epson.c:566 ../backend/epson.c:578 +#: ../backend/epson2.c:161 ../backend/epson2.c:169 ../backend/epson2.c:181 +#, no-c-format +msgid "Halftone B (Soft Tone)" +msgstr "" + +#: ../backend/epson.c:559 ../backend/epson.c:567 ../backend/epson.c:579 +#: ../backend/epson2.c:162 ../backend/epson2.c:170 ../backend/epson2.c:182 +#, no-c-format +msgid "Halftone C (Net Screen)" +msgstr "" + +#: ../backend/epson.c:568 ../backend/epson.c:580 ../backend/epson2.c:171 +#: ../backend/epson2.c:183 +#, no-c-format +msgid "Dither A (4x4 Bayer)" +msgstr "" + +#: ../backend/epson.c:569 ../backend/epson.c:581 ../backend/epson2.c:172 +#: ../backend/epson2.c:184 +#, no-c-format +msgid "Dither B (4x4 Spiral)" +msgstr "" + +#: ../backend/epson.c:570 ../backend/epson.c:582 ../backend/epson2.c:173 +#: ../backend/epson2.c:185 +#, no-c-format +msgid "Dither C (4x4 Net Screen)" +msgstr "" + +#: ../backend/epson.c:571 ../backend/epson.c:583 ../backend/epson2.c:174 +#: ../backend/epson2.c:186 +#, no-c-format +msgid "Dither D (8x4 Net Screen)" +msgstr "" + +#: ../backend/epson.c:584 ../backend/epson2.c:187 +#, no-c-format +msgid "Text Enhanced Technology" +msgstr "" + +#: ../backend/epson.c:585 ../backend/epson2.c:188 +#, no-c-format +msgid "Download pattern A" +msgstr "" + +#: ../backend/epson.c:586 ../backend/epson2.c:189 +#, 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:249 +#, 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:248 ../backend/fujitsu.c:558 +#: ../backend/hp-option.c:3226 ../backend/test.c:143 +#, no-c-format +msgid "Default" +msgstr "Alapértelmezett" + +#: ../backend/epson.c:658 ../backend/epson2.c:250 +#, no-c-format +msgid "High density printing" +msgstr "" + +#: ../backend/epson.c:659 ../backend/epson2.c:251 +#, no-c-format +msgid "Low density printing" +msgstr "" + +#: ../backend/epson.c:660 ../backend/epson2.c:252 +#, no-c-format +msgid "High contrast printing" +msgstr "" + +#: ../backend/epson.c:678 ../backend/epson2.c:270 +#, no-c-format +msgid "User defined (Gamma=1.0)" +msgstr "" + +#: ../backend/epson.c:679 ../backend/epson2.c:271 +#, 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 +#, no-c-format +msgid "Letter" +msgstr "Letter" + +#: ../backend/epson.c:761 +#, no-c-format +msgid "A4" +msgstr "A4" + +#: ../backend/epson.c:762 +#, no-c-format +msgid "Max" +msgstr "Max" + +#: ../backend/epson.c:2799 ../backend/epson2.c:954 ../backend/genesys.c:5955 +#: ../backend/gt68xx.c:458 ../backend/hp-option.c:2914 ../backend/ma1509.c:501 +#: ../backend/matsushita.c:1084 ../backend/microtek2.h:598 +#: ../backend/mustek.c:4205 ../backend/mustek_usb.c:260 +#: ../backend/mustek_usb2.c:344 ../backend/niash.c:736 +#: ../backend/plustek.c:720 ../backend/plustek_pp.c:657 +#: ../backend/sceptre.c:673 ../backend/snapscan-options.c:315 +#: ../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:2831 ../backend/epson2.c:990 +#, no-c-format +msgid "Selects the halftone." +msgstr "" + +#: ../backend/epson.c:2853 ../backend/epson2.c:1011 +#, no-c-format +msgid "Dropout" +msgstr "" + +#: ../backend/epson.c:2854 ../backend/epson2.c:1012 +#, no-c-format +msgid "Selects the dropout." +msgstr "" + +#: ../backend/epson.c:2866 ../backend/epson2.c:1024 +#, no-c-format +msgid "Selects the brightness." +msgstr "" + +#: ../backend/epson.c:2881 ../backend/epson2.c:1037 +#, no-c-format +msgid "Sharpness" +msgstr "" + +#: ../backend/epson.c:3017 ../backend/epson2.c:1153 ../backend/epson2.c:1200 +#, no-c-format +msgid "Color correction" +msgstr "SzÃnkorrekció" + +#: ../backend/epson.c:3020 ../backend/epson2.c:1155 +#, no-c-format +msgid "Sets the color correction table for the selected output device." +msgstr "" + +#: ../backend/epson.c:3061 +#, no-c-format +msgid "Color correction coefficients" +msgstr "" + +#: ../backend/epson.c:3062 +#, no-c-format +msgid "Matrix multiplication of RGB" +msgstr "" + +#: ../backend/epson.c:3079 +#, no-c-format +msgid "Shift green to red" +msgstr "" + +#: ../backend/epson.c:3080 +#, no-c-format +msgid "Shift green to blue" +msgstr "" + +#: ../backend/epson.c:3081 +#, no-c-format +msgid "Shift red to green" +msgstr "" + +#: ../backend/epson.c:3083 +#, no-c-format +msgid "Shift red to blue" +msgstr "" + +#: ../backend/epson.c:3084 +#, no-c-format +msgid "Shift blue to green" +msgstr "" + +#: ../backend/epson.c:3085 +#, no-c-format +msgid "Shift blue to red" +msgstr "" + +#: ../backend/epson.c:3088 +#, no-c-format +msgid "Controls green level" +msgstr "" + +#: ../backend/epson.c:3089 +#, no-c-format +msgid "Adds to red based on green level" +msgstr "" + +#: ../backend/epson.c:3090 +#, no-c-format +msgid "Adds to blue based on green level" +msgstr "" + +#: ../backend/epson.c:3091 +#, no-c-format +msgid "Adds to green based on red level" +msgstr "" + +#: ../backend/epson.c:3092 +#, no-c-format +msgid "Controls red level" +msgstr "" + +#: ../backend/epson.c:3093 +#, no-c-format +msgid "Adds to blue based on red level" +msgstr "" + +#: ../backend/epson.c:3094 +#, no-c-format +msgid "Adds to green based on blue level" +msgstr "" + +#: ../backend/epson.c:3095 +#, no-c-format +msgid "Adds to red based on blue level" +msgstr "" + +#: ../backend/epson.c:3096 +#, fuzzy, no-c-format +msgid "Controls blue level" +msgstr "A kék csatorna kontrasztja" + +#: ../backend/epson.c:3192 ../backend/epson2.c:1234 +#, no-c-format +msgid "Mirror the image." +msgstr "Kép tükrözése." + +#: ../backend/epson.c:3218 ../backend/mustek.c:4334 +#, no-c-format +msgid "Fast preview" +msgstr "Gyors elÅ‘nézet" + +#: ../backend/epson.c:3231 ../backend/epson2.c:1244 +#, no-c-format +msgid "Auto area segmentation" +msgstr "" + +#: ../backend/epson.c:3244 +#, no-c-format +msgid "Short resolution list" +msgstr "" + +#: ../backend/epson.c:3246 +#, no-c-format +msgid "Display short resolution list" +msgstr "" + +#: ../backend/epson.c:3253 +#, no-c-format +msgid "Zoom" +msgstr "NagyÃtás" + +#: ../backend/epson.c:3255 +#, no-c-format +msgid "Defines the zoom factor the scanner will use" +msgstr "" + +#: ../backend/epson.c:3335 +#, no-c-format +msgid "Quick format" +msgstr "" + +#: ../backend/epson.c:3346 ../backend/epson2.c:1319 +#, no-c-format +msgid "Optional equipment" +msgstr "" + +#: ../backend/epson.c:3417 ../backend/epson2.c:1372 +#, no-c-format +msgid "Eject" +msgstr "" + +#: ../backend/epson.c:3418 ../backend/epson2.c:1373 +#, no-c-format +msgid "Eject the sheet in the ADF" +msgstr "" + +#: ../backend/epson.c:3430 ../backend/epson2.c:1383 +#, no-c-format +msgid "Auto eject" +msgstr "" + +#: ../backend/epson.c:3431 ../backend/epson2.c:1385 +#, no-c-format +msgid "Eject document after scanning" +msgstr "" + +#: ../backend/epson.c:3443 ../backend/epson2.c:1395 +#: ../backend/magicolor.c:2345 +#, no-c-format +msgid "ADF Mode" +msgstr "" + +#: ../backend/epson.c:3445 ../backend/epson2.c:1397 +#: ../backend/magicolor.c:2347 +#, no-c-format +msgid "Selects the ADF mode (simplex/duplex)" +msgstr "" + +#: ../backend/epson.c:3459 ../backend/epson2.c:1409 +#, no-c-format +msgid "Bay" +msgstr "" + +#: ../backend/epson.c:3460 ../backend/epson2.c:1410 +#, no-c-format +msgid "Select bay to scan" +msgstr "" + +#: ../backend/epson.h:69 ../backend/epson2.h:73 +#, 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:76 +#, no-c-format +msgid "Focus Position" +msgstr "" + +#: ../backend/epson.h:73 ../backend/epson2.h:77 +#, 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:79 +#, no-c-format +msgid "Wait for Button" +msgstr "" + +#: ../backend/epson.h:76 ../backend/epson2.h:80 +#, 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:97 +#, no-c-format +msgid "Infrared" +msgstr "" + +#: ../backend/epson2.c:130 +#, fuzzy, no-c-format +msgid "Positive Slide" +msgstr "PozitÃv film" + +#: ../backend/epson2.c:131 +#, fuzzy, no-c-format +msgid "Negative Slide" +msgstr "NegatÃv film" + +#: ../backend/epson2.c:209 +#, no-c-format +msgid "Built in CCT profile" +msgstr "" + +#: ../backend/epson2.c:210 +#, no-c-format +msgid "User defined CCT profile" +msgstr "" + +#: ../backend/fujitsu.c:559 ../backend/hp-option.c:3327 +#: ../backend/hp-option.c:3340 +#, no-c-format +msgid "On" +msgstr "Be" + +#: ../backend/fujitsu.c:560 ../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:562 +#, no-c-format +msgid "DTC" +msgstr "DTC" + +#: ../backend/fujitsu.c:563 +#, no-c-format +msgid "SDTC" +msgstr "SDTC" + +#: ../backend/fujitsu.c:565 ../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:566 +#, no-c-format +msgid "Diffusion" +msgstr "" + +#: ../backend/fujitsu.c:571 +#, fuzzy, no-c-format +msgid "White" +msgstr "Fehérszint" + +#: ../backend/fujitsu.c:572 +#, fuzzy, no-c-format +msgid "Black" +msgstr "Feketeszint" + +#: ../backend/fujitsu.c:577 +#, no-c-format +msgid "Continue" +msgstr "Folytatás" + +#: ../backend/fujitsu.c:578 +#, no-c-format +msgid "Stop" +msgstr "MegállÃt" + +#: ../backend/fujitsu.c:580 +#, no-c-format +msgid "10mm" +msgstr "10mm" + +#: ../backend/fujitsu.c:581 +#, no-c-format +msgid "15mm" +msgstr "15mm" + +#: ../backend/fujitsu.c:582 +#, no-c-format +msgid "20mm" +msgstr "20mm" + +#: ../backend/fujitsu.c:584 ../backend/hp-option.c:3045 +#, no-c-format +msgid "Horizontal" +msgstr "VÃzszintes" + +#: ../backend/fujitsu.c:585 +#, fuzzy, no-c-format +msgid "Horizontal bold" +msgstr "VÃzszintes" + +#: ../backend/fujitsu.c:586 +#, fuzzy, no-c-format +msgid "Horizontal narrow" +msgstr "VÃzszintes" + +#: ../backend/fujitsu.c:587 ../backend/hp-option.c:3044 +#, no-c-format +msgid "Vertical" +msgstr "FüggÅ‘leges" + +#: ../backend/fujitsu.c:588 +#, fuzzy, no-c-format +msgid "Vertical bold" +msgstr "FüggÅ‘leges" + +#: ../backend/fujitsu.c:590 +#, no-c-format +msgid "Top to bottom" +msgstr "" + +#: ../backend/fujitsu.c:591 +#, no-c-format +msgid "Bottom to top" +msgstr "" + +#: ../backend/fujitsu.c:593 +#, fuzzy, no-c-format +msgid "Front" +msgstr "Nyomtatás" + +#: ../backend/fujitsu.c:594 +#, no-c-format +msgid "Back" +msgstr "" + +#: ../backend/genesys.c:6173 +#, fuzzy, no-c-format +msgid "Extras" +msgstr "Extra gyors" + +#: ../backend/genesys.c:6192 +#, no-c-format +msgid "Threshold curve" +msgstr "" + +#: ../backend/genesys.c:6193 +#, no-c-format +msgid "Dynamic threshold curve, from light to dark, normally 50-65" +msgstr "" + +#: ../backend/genesys.c:6202 +#, no-c-format +msgid "Disable dynamic lineart" +msgstr "" + +#: ../backend/genesys.c:6204 +#, no-c-format +msgid "" +"Disable use of a software adaptive algorithm to generate lineart relying " +"instead on hardware lineart." +msgstr "" + +#: ../backend/genesys.c:6219 +#, fuzzy, no-c-format +msgid "Disable interpolation" +msgstr "TesztbeállÃtások engedélyezése" + +#: ../backend/genesys.c:6222 +#, 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:6231 +#, fuzzy, no-c-format +msgid "Color Filter" +msgstr "SzÃnmátrix" + +#: ../backend/genesys.c:6234 +#, no-c-format +msgid "When using gray or lineart this option selects the used color." +msgstr "" + +#: ../backend/genesys.c:6260 +#, no-c-format +msgid "Lamp off time" +msgstr "" + +#: ../backend/genesys.c:6263 +#, 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:6292 ../backend/genesys.c:6293 +#, no-c-format +msgid "File button" +msgstr "Fájl gomb" + +#: ../backend/genesys.c:6345 ../backend/genesys.c:6346 +#, no-c-format +msgid "OCR button" +msgstr "OCR gomb" + +#: ../backend/genesys.c:6359 ../backend/genesys.c:6360 +#, no-c-format +msgid "Power button" +msgstr "" + +#: ../backend/genesys.c:6373 ../backend/gt68xx.c:762 +#, fuzzy, no-c-format +msgid "Need calibration" +msgstr "Finom beállÃtás" + +#: ../backend/genesys.c:6374 ../backend/gt68xx.c:763 +#, no-c-format +msgid "The scanner needs calibration for the current settings" +msgstr "" + +#: ../backend/genesys.c:6387 ../backend/gt68xx.c:787 ../backend/gt68xx.c:788 +#: ../backend/pixma_sane_options.c:210 ../backend/plustek.c:1079 +#, no-c-format +msgid "Buttons" +msgstr "Gombok" + +#: ../backend/genesys.c:6394 ../backend/gt68xx.c:794 +#: ../backend/hp5400_sane.c:392 ../backend/hp-option.h:97 +#: ../backend/niash.c:728 ../backend/plustek.c:940 +#, no-c-format +msgid "Calibrate" +msgstr "Kalibrálás" + +#: ../backend/genesys.c:6396 ../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:6410 ../backend/gt68xx.c:809 +#, fuzzy, no-c-format +msgid "Clear calibration" +msgstr "Finom beállÃtás" + +#: ../backend/genesys.c:6411 ../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:83 ../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:976 +#, fuzzy, no-c-format +msgid "Geometry Group" +msgstr "Geometria" + +#: ../backend/hp3500.c:1032 ../backend/hp3500.c:1033 +#, 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 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:683 +#, no-c-format +msgid "Image" +msgstr "Kép" + +#: ../backend/hp5400_sane.c:352 ../backend/niash.c:711 +#, 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:718 +#, no-c-format +msgid "Lamp status" +msgstr "" + +#: ../backend/hp5400_sane.c:382 ../backend/niash.c:719 +#, no-c-format +msgid "Switches the lamp on or off." +msgstr "" + +#: ../backend/hp5400_sane.c:393 ../backend/niash.c:729 +#, no-c-format +msgid "Calibrates for black and white level." +msgstr "" + +#: ../backend/hp5590.c:83 ../backend/hp-option.c:3253 +#, no-c-format +msgid "ADF" +msgstr "ADF" + +#: ../backend/hp5590.c:85 +#, no-c-format +msgid "TMA Slides" +msgstr "" + +#: ../backend/hp5590.c:86 +#, fuzzy, no-c-format +msgid "TMA Negatives" +msgstr "NegatÃv" + +#: ../backend/hp5590.c:89 +#, fuzzy, no-c-format +msgid "Color (48 bits)" +msgstr "SzÃnes 42/48" + +#: ../backend/hp5590.c:92 +#, no-c-format +msgid "Extend lamp timeout" +msgstr "" + +#: ../backend/hp5590.c:93 +#, no-c-format +msgid "Extends lamp timeout (from 15 minutes to 1 hour)" +msgstr "" + +#: ../backend/hp5590.c:95 +#, no-c-format +msgid "Wait for button" +msgstr "" + +#: ../backend/hp5590.c:96 +#, 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/matsushita.c:244 ../backend/mustek.c:149 +#: ../backend/plustek.c:233 ../backend/plustek_pp.c:200 ../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:73 +#, no-c-format +msgid "Smoothing" +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/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:1000 ../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:1016 ../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:1032 ../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:177 +#, no-c-format +msgid "From paper" +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:1332 +#, no-c-format +msgid "sheetfed scanner" +msgstr "" + +#: ../backend/matsushita.c:1126 +#, no-c-format +msgid "Feeder mode" +msgstr "" + +#: ../backend/matsushita.c:1127 +#, no-c-format +msgid "Sets the feeding mode" +msgstr "" + +#: ../backend/matsushita.c:1224 +#, no-c-format +msgid "Automatic threshold" +msgstr "" + +#: ../backend/matsushita.c:1227 +#, no-c-format +msgid "" +"Automatically sets brightness, contrast, white level, gamma, noise reduction " +"and image emphasis" +msgstr "" + +#: ../backend/matsushita.c:1275 +#, no-c-format +msgid "Noise reduction" +msgstr "Zajszűrés" + +#: ../backend/matsushita.c:1277 +#, no-c-format +msgid "Reduce the isolated dot noise" +msgstr "" + +#: ../backend/matsushita.c:1288 +#, no-c-format +msgid "Image emphasis" +msgstr "" + +#: ../backend/matsushita.c:1289 +#, no-c-format +msgid "Sets the image emphasis" +msgstr "" + +#: ../backend/matsushita.c:1300 ../backend/matsushita.c:1301 +#: ../backend/pixma_sane_options.c:107 +#, no-c-format +msgid "Gamma" +msgstr "Gamma" + +#: ../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/matsushita.h:219 +#, no-c-format +msgid "Paper size" +msgstr "PapÃr mérete" + +#: ../backend/matsushita.h:220 ../backend/matsushita.h:227 +#, no-c-format +msgid "Automatic separation" +msgstr "" + +#: ../backend/matsushita.h:223 +#, no-c-format +msgid "Enable Duplex (Dual-Sided) Scanning" +msgstr "" + +#: ../backend/matsushita.h:225 +#, no-c-format +msgid "Physical size of the paper in the ADF" +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:375 +#, no-c-format +msgid "Quality scan" +msgstr "MinÅ‘ségi szkennelés" + +#: ../backend/microtek2.h:627 ../backend/snapscan-options.c:376 +#, 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:640 +#, no-c-format +msgid "Gamma correction" +msgstr "Gamma korrekció" + +#: ../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:4237 +#, no-c-format +msgid "Fast gray mode" +msgstr "" + +#: ../backend/mustek.c:4238 +#, no-c-format +msgid "Scan in fast gray mode (lower quality)." +msgstr "" + +#: ../backend/mustek.c:4335 +#, 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:4343 +#, no-c-format +msgid "Lamp off time (minutes)" +msgstr "" + +#: ../backend/mustek.c:4344 +#, no-c-format +msgid "Set the time (in minutes) after which the lamp is shut off." +msgstr "" + +#: ../backend/mustek.c:4355 +#, no-c-format +msgid "Turn lamp off" +msgstr "" + +#: ../backend/mustek.c:4356 +#, no-c-format +msgid "Turns the lamp off immediately." +msgstr "" + +#: ../backend/mustek.c:4433 +#, no-c-format +msgid "Red brightness" +msgstr "Vörös fényerÅ‘" + +#: ../backend/mustek.c:4434 +#, no-c-format +msgid "Controls the brightness of the red channel of the acquired image." +msgstr "" + +#: ../backend/mustek.c:4446 +#, no-c-format +msgid "Green brightness" +msgstr "Zöld fényerÅ‘" + +#: ../backend/mustek.c:4447 +#, no-c-format +msgid "Controls the brightness of the green channel of the acquired image." +msgstr "" + +#: ../backend/mustek.c:4459 +#, no-c-format +msgid "Blue brightness" +msgstr "Kék fényerÅ‘" + +#: ../backend/mustek.c:4460 +#, no-c-format +msgid "Controls the brightness of the blue channel of the acquired image." +msgstr "" + +#: ../backend/mustek.c:4485 +#, no-c-format +msgid "Contrast red channel" +msgstr "A vörös csatorna kontrasztja" + +#: ../backend/mustek.c:4486 +#, no-c-format +msgid "Controls the contrast of the red channel of the acquired image." +msgstr "" + +#: ../backend/mustek.c:4498 +#, no-c-format +msgid "Contrast green channel" +msgstr "A zöld csatorna kontrasztja" + +#: ../backend/mustek.c:4499 +#, no-c-format +msgid "Controls the contrast of the green channel of the acquired image." +msgstr "" + +#: ../backend/mustek.c:4511 +#, no-c-format +msgid "Contrast blue channel" +msgstr "A kék csatorna kontrasztja" + +#: ../backend/mustek.c:4512 +#, 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_sane_options.c:91 +#, no-c-format +msgid "Button-controlled scan" +msgstr "" + +#: ../backend/pixma_sane_options.c:94 +#, 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:216 +#, no-c-format +msgid "Update button state" +msgstr "" + +#: ../backend/pixma_sane_options.c:228 +#, no-c-format +msgid "Button 1" +msgstr "" + +#: ../backend/pixma_sane_options.c:242 +#, no-c-format +msgid "Button 2" +msgstr "" + +#: ../backend/plustek.c:234 ../backend/plustek_pp.c:201 ../backend/u12.c:156 +#, no-c-format +msgid "Transparency" +msgstr "Ãtlátszó" + +#: ../backend/plustek.c:912 +#, no-c-format +msgid "Device-Settings" +msgstr "" + +#: ../backend/plustek.c:919 +#, no-c-format +msgid "Lampswitch" +msgstr "" + +#: ../backend/plustek.c:920 +#, no-c-format +msgid "Manually switching the lamp(s)." +msgstr "" + +#: ../backend/plustek.c:925 +#, fuzzy, no-c-format +msgid "Lamp off during dark calibration" +msgstr "Finom beállÃtás" + +#: ../backend/plustek.c:926 +#, no-c-format +msgid "Always switches lamp off when doing dark calibration." +msgstr "" + +#: ../backend/plustek.c:934 +#, fuzzy, no-c-format +msgid "Calibration data cache" +msgstr "Kalibráció" + +#: ../backend/plustek.c:935 +#, no-c-format +msgid "Enables or disables calibration data cache." +msgstr "" + +#: ../backend/plustek.c:941 +#, fuzzy, no-c-format +msgid "Performs calibration" +msgstr "Finom beállÃtás" + +#: ../backend/plustek.c:958 +#, no-c-format +msgid "Speedup sensor" +msgstr "" + +#: ../backend/plustek.c:959 +#, no-c-format +msgid "Enables or disables speeding up sensor movement." +msgstr "" + +#: ../backend/plustek.c:973 +#, no-c-format +msgid "Warmup-time" +msgstr "" + +#: ../backend/plustek.c:974 +#, no-c-format +msgid "Warmup-time in seconds." +msgstr "" + +#: ../backend/plustek.c:986 +#, no-c-format +msgid "Lampoff-time" +msgstr "" + +#: ../backend/plustek.c:987 +#, no-c-format +msgid "Lampoff-time in seconds." +msgstr "" + +#: ../backend/plustek.c:994 +#, fuzzy, no-c-format +msgid "Analog frontend" +msgstr "Analóg erÅ‘sÃtés" + +#: ../backend/plustek.c:1001 +#, no-c-format +msgid "Red gain value of the AFE" +msgstr "" + +#: ../backend/plustek.c:1008 ../backend/umax_pp.c:792 +#, no-c-format +msgid "Red offset" +msgstr "" + +#: ../backend/plustek.c:1009 +#, no-c-format +msgid "Red offset value of the AFE" +msgstr "" + +#: ../backend/plustek.c:1017 +#, no-c-format +msgid "Green gain value of the AFE" +msgstr "" + +#: ../backend/plustek.c:1024 ../backend/umax_pp.c:804 +#, no-c-format +msgid "Green offset" +msgstr "" + +#: ../backend/plustek.c:1025 +#, no-c-format +msgid "Green offset value of the AFE" +msgstr "" + +#: ../backend/plustek.c:1033 +#, no-c-format +msgid "Blue gain value of the AFE" +msgstr "" + +#: ../backend/plustek.c:1040 ../backend/umax_pp.c:816 +#, no-c-format +msgid "Blue offset" +msgstr "" + +#: ../backend/plustek.c:1041 +#, no-c-format +msgid "Blue offset value of the AFE" +msgstr "" + +#: ../backend/plustek.c:1048 +#, no-c-format +msgid "Red lamp off" +msgstr "" + +#: ../backend/plustek.c:1049 +#, no-c-format +msgid "Defines red lamp off parameter" +msgstr "" + +#: ../backend/plustek.c:1056 +#, no-c-format +msgid "Green lamp off" +msgstr "" + +#: ../backend/plustek.c:1057 +#, no-c-format +msgid "Defines green lamp off parameter" +msgstr "" + +#: ../backend/plustek.c:1064 +#, no-c-format +msgid "Blue lamp off" +msgstr "" + +#: ../backend/plustek.c:1065 +#, no-c-format +msgid "Defines blue lamp off parameter" +msgstr "" + +#: ../backend/plustek.c:1095 +#, no-c-format +msgid "This option reflects the status of the scanner buttons." +msgstr "" + +#: ../backend/plustek_pp.c:194 +#, no-c-format +msgid "Color36" +msgstr "" + +#: ../backend/plustek_pp.c:208 +#, no-c-format +msgid "Dithermap 1" +msgstr "" + +#: ../backend/plustek_pp.c:209 +#, no-c-format +msgid "Dithermap 2" +msgstr "" + +#: ../backend/plustek_pp.c:210 +#, 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 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:2770 +#, no-c-format +msgid "This option reflects the status of a scanner button." +msgstr "" + +#: ../backend/rts8891.c:2801 ../backend/umax.c:5795 ../backend/umax_pp.c:639 +#, no-c-format +msgid "Lamp on" +msgstr "" + +#: ../backend/rts8891.c:2802 ../backend/umax.c:5796 +#, no-c-format +msgid "Turn on scanner lamp" +msgstr "" + +#: ../backend/rts8891.c:2812 ../backend/umax1220u.c:248 ../backend/umax.c:5812 +#, no-c-format +msgid "Lamp off" +msgstr "" + +#: ../backend/rts8891.c:2813 ../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:84 +#, no-c-format +msgid "Document Feeder" +msgstr "" + +#: ../backend/snapscan-options.c:88 +#, no-c-format +msgid "6x4 (inch)" +msgstr "6x4 (inch)" + +#: ../backend/snapscan-options.c:89 +#, no-c-format +msgid "8x10 (inch)" +msgstr "8x10 (inch)" + +#: ../backend/snapscan-options.c:90 +#, no-c-format +msgid "8.5x11 (inch)" +msgstr "8.5x11 (inch)" + +#: ../backend/snapscan-options.c:93 +#, no-c-format +msgid "Halftoning Unsupported" +msgstr "" + +#: ../backend/snapscan-options.c:94 +#, no-c-format +msgid "DispersedDot8x8" +msgstr "" + +#: ../backend/snapscan-options.c:95 +#, no-c-format +msgid "DispersedDot16x16" +msgstr "" + +#: ../backend/snapscan-options.c:99 +#, 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:436 +#, no-c-format +msgid "Preview mode" +msgstr "ElÅ‘nézeti mód" + +#: ../backend/snapscan-options.c:438 +#, 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:545 +#, no-c-format +msgid "Predefined settings" +msgstr "" + +#: ../backend/snapscan-options.c:547 +#, no-c-format +msgid "" +"Provides standard scanning areas for photographs, printed pages and the like." +msgstr "" + +#: ../backend/snapscan-options.c:823 +#, no-c-format +msgid "Colour lines per read" +msgstr "" + +#: ../backend/snapscan-options.c:835 +#, 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 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" @@ -360,12 +360,12 @@ msgstr "ランプã®æš–æ©Ÿ" #: ../include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" -msgstr "露出時間を構æˆ" +msgstr "露出時間を較æ£" #: ../include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" -msgstr "赤ã®éœ²å‡ºæ™‚間を構æˆ" +msgstr "赤ã®éœ²å‡ºæ™‚間を較æ£" #: ../include/sane/saneopts.h:219 #, no-c-format @@ -4571,7 +4571,7 @@ msgid "" msgstr "" "ãƒãƒ³ãƒ‰ã‚¹ã‚ャナーをシミュレートã—ã¾ã™ã€‚ãƒãƒ³ãƒ‰ã‚¹ã‚ャナーã¯ã€ãŸã„ã¦ã„ã®å ´" "åˆã€ã‚¤ãƒ¡ãƒ¼ã‚¸ã®é«˜ã•ãŒäº‹å‰ã«ã¯ã‚ã‹ã‚Šã¾ã›ã‚“。ãã®ä»£ã‚ã‚Šã€é«˜ã•ã¨ã—ã¦ãƒ¼ï¼‘ã‚’è¿”" -"ã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションをè¨å®šã™ã‚‹ã¨ã€ãƒ•ãƒãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ãŒæ£ã—ããれを圧ã‚ã‘ã‚‹" +"ã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションをè¨å®šã™ã‚‹ã¨ã€ãƒ•ãƒãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ãŒæ£ã—ããれを扱ãˆã‚‹" "ã‹ã€ãƒ†ã‚¹ãƒˆã—ã¾ã™ã€‚" #: ../backend/pnm.c:283 diff --git a/sanei/Makefile.am b/sanei/Makefile.am index c466e44..c1106ae 100644 --- a/sanei/Makefile.am +++ b/sanei/Makefile.am @@ -14,7 +14,7 @@ libsanei_la_SOURCES = sanei_ab306.c sanei_constrain_value.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_udp.c sanei_magic.c sanei_ir.c if HAVE_JPEG libsanei_la_SOURCES += sanei_jpeg.c endif diff --git a/sanei/Makefile.in b/sanei/Makefile.in index 66fc549..d2d6992 100644 --- a/sanei/Makefile.in +++ b/sanei/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -102,7 +102,7 @@ am__libsanei_la_SOURCES_DIST = sanei_ab306.c sanei_constrain_value.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_jpeg.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 \ @@ -110,7 +110,7 @@ am_libsanei_la_OBJECTS = sanei_ab306.lo sanei_constrain_value.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 $(am__objects_1) + 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@) @@ -269,6 +269,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -285,6 +286,7 @@ 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_LIBS = @USB_LIBS@ @@ -358,7 +360,7 @@ libsanei_la_SOURCES = sanei_ab306.c sanei_constrain_value.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 $(am__append_1) + 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 @@ -424,6 +426,7 @@ distclean-compile: @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@ @@ -444,14 +447,14 @@ distclean-compile: @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/sanei/sanei_ab306.c b/sanei/sanei_ab306.c index 91d647d..c663d38 100644 --- a/sanei/sanei_ab306.c +++ b/sanei/sanei_ab306.c @@ -51,6 +51,9 @@ #ifdef HAVE_SYS_IO_H # include <sys/io.h> /* 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 <asm/io.h> /* ugly, but backwards compatible */ #elif defined (__i386__) && defined (__GNUC__) diff --git a/sanei/sanei_ir.c b/sanei/sanei_ir.c new file mode 100644 index 0000000..ad96a55 --- /dev/null +++ b/sanei/sanei_ir.c @@ -0,0 +1,1205 @@ +/** @file sanei_ir.c + * + * sanei_ir - functions for utilizing the infrared plane + * + * Copyright (C) 2012 Michael Rickmann <mrickma@gwdg.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. + * + * 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 <stdlib.h> +#include <string.h> +#include <values.h> +#include <math.h> + +#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; + } + + *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; +} diff --git a/sanei/sanei_pa4s2.c b/sanei/sanei_pa4s2.c index 8fe4260..c15dd5a 100644 --- a/sanei/sanei_pa4s2.c +++ b/sanei/sanei_pa4s2.c @@ -72,7 +72,10 @@ # if defined (__ICC) && __ICC >= 700 # define __GNUC__ 2 # endif -# include <sys/io.h> +# include <sys/io.h> +# 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) diff --git a/sanei/sanei_pio.c b/sanei/sanei_pio.c index ef00861..00e40ee 100644 --- a/sanei/sanei_pio.c +++ b/sanei/sanei_pio.c @@ -61,6 +61,9 @@ #ifdef HAVE_SYS_IO_H # include <sys/io.h> /* 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 <asm/io.h> /* ugly, but backwards compatible */ #elif HAVE_SYS_HW_H diff --git a/sanei/sanei_pp.c b/sanei/sanei_pp.c index ced1a85..6146d1e 100644 --- a/sanei/sanei_pp.c +++ b/sanei/sanei_pp.c @@ -94,6 +94,9 @@ # define __GNUC__ 2 # endif # include <sys/io.h> +# 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) diff --git a/sanei/sanei_thread.c b/sanei/sanei_thread.c index fd58af2..8db4a21 100644 --- a/sanei/sanei_thread.c +++ b/sanei/sanei_thread.c @@ -512,11 +512,15 @@ sanei_thread_waitpid( SANE_Pid pid, int *status ) DBG(2, "* result = %d (%p)\n", stat, (void*)status ); result = pid; } - /* 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 ( 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; diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index de2e094..3aebd01 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -265,6 +265,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -281,6 +282,7 @@ 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_LIBS = @USB_LIBS@ diff --git a/testsuite/sanei/Makefile.in b/testsuite/sanei/Makefile.in index af6761f..6b29c45 100644 --- a/testsuite/sanei/Makefile.in +++ b/testsuite/sanei/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -481,6 +481,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -497,6 +498,7 @@ 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_LIBS = @USB_LIBS@ @@ -661,14 +663,14 @@ distclean-compile: @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/testsuite/tools/Makefile.in b/testsuite/tools/Makefile.in index e02349b..677dea2 100644 --- a/testsuite/tools/Makefile.in +++ b/testsuite/tools/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -205,6 +205,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -221,6 +222,7 @@ 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_LIBS = @USB_LIBS@ diff --git a/testsuite/tools/data/html-backends-split.ref b/testsuite/tools/data/html-backends-split.ref index b498c57..72fd949 100644 --- a/testsuite/tools/data/html-backends-split.ref +++ b/testsuite/tools/data/html-backends-split.ref @@ -16466,7 +16466,7 @@ Grandtek Scopecam <dt><b>Manufacturer:</b></dt> <dd>Manufacturer, vendor or brand name of the device.</dd> <dt><b>Model:</b></dt> - <dd>Name of the the device.</dd> + <dd>Name of the device.</dd> <dt><b>Interface:</b></dt> <dd>How the device is connected to the computer.</dd> <dt><b>USB id:</b></dt> diff --git a/testsuite/tools/data/html-mfgs.ref b/testsuite/tools/data/html-mfgs.ref index 3cbaaef..5e53ee3 100644 --- a/testsuite/tools/data/html-mfgs.ref +++ b/testsuite/tools/data/html-mfgs.ref @@ -23864,7 +23864,7 @@ qcam<br>(unmaintained) <blockquote> <dl> <dt><b>Model:</b></dt> - <dd>Name of the the device.</dd> + <dd>Name of the device.</dd> <dt><b>Interface:</b></dt> <dd>How the device is connected to the computer.</dd> <dt><b>USB id:</b></dt> diff --git a/tools/Makefile.am b/tools/Makefile.am index 7c2a616..2024180 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -8,7 +8,12 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include bin_PROGRAMS = sane-find-scanner gamma4scanimage -noinst_PROGRAMS = sane-desc umax_pp +noinst_PROGRAMS = sane-desc +if INSTALL_UMAX_PP_TOOLS +bin_PROGRAMS = umax_pp +else +noinst_PROGRAMS = umax_pp +endif if CROSS_COMPILING HOTPLUG = diff --git a/tools/Makefile.in b/tools/Makefile.in index 367a70b..ae79cda 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -80,8 +80,15 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -bin_PROGRAMS = sane-find-scanner$(EXEEXT) gamma4scanimage$(EXEEXT) -noinst_PROGRAMS = sane-desc$(EXEEXT) umax_pp$(EXEEXT) +@INSTALL_UMAX_PP_TOOLS_FALSE@bin_PROGRAMS = \ +@INSTALL_UMAX_PP_TOOLS_FALSE@ sane-find-scanner$(EXEEXT) \ +@INSTALL_UMAX_PP_TOOLS_FALSE@ gamma4scanimage$(EXEEXT) +@INSTALL_UMAX_PP_TOOLS_TRUE@bin_PROGRAMS = umax_pp$(EXEEXT) \ +@INSTALL_UMAX_PP_TOOLS_TRUE@ sane-find-scanner$(EXEEXT) \ +@INSTALL_UMAX_PP_TOOLS_TRUE@ gamma4scanimage$(EXEEXT) +@INSTALL_UMAX_PP_TOOLS_FALSE@noinst_PROGRAMS = umax_pp$(EXEEXT) \ +@INSTALL_UMAX_PP_TOOLS_FALSE@ sane-desc$(EXEEXT) +@INSTALL_UMAX_PP_TOOLS_TRUE@noinst_PROGRAMS = sane-desc$(EXEEXT) subdir = tools DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(srcdir)/sane-config.in \ @@ -303,6 +310,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_LIBS = @PNG_LIBS@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -319,6 +327,7 @@ 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_LIBS = @USB_LIBS@ @@ -584,14 +593,14 @@ distclean-compile: @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.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 `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/tools/sane-desc.c b/tools/sane-desc.c index c8b50ad..badc8ce 100644 --- a/tools/sane-desc.c +++ b/tools/sane-desc.c @@ -2878,7 +2878,7 @@ static void html_print_legend_model (void) { printf - (" <dt><b>Model:</b></dt>\n" " <dd>Name of the the device.</dd>\n"); + (" <dt><b>Model:</b></dt>\n" " <dd>Name of the device.</dd>\n"); } static void |