From b2802d98d4486d6afc585062f4ca02fddf829dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Fri, 2 Jan 2015 20:06:30 +0100 Subject: Release 1.0.25+git20150102-1 --- .gitignore | 17 +- ChangeLog | 832 ++-- ChangeLog-1.0.24 | 602 +++ README.linux | 16 +- backend/abaton.c | 2 +- backend/apple.c | 2 +- backend/artec.c | 2 +- backend/avision.c | 4 +- backend/canon_dr-cmd.h | 41 +- backend/canon_dr.c | 1191 ++++-- backend/canon_dr.conf.in | 64 +- backend/canon_dr.h | 36 +- backend/coolscan.c | 2 +- backend/epjitsu-cmd.h | 282 +- backend/epjitsu.c | 1413 +++++-- backend/epjitsu.conf.in | 37 + backend/epjitsu.h | 49 +- backend/epson.c | 36 +- backend/epson2-commands.c | 5 +- backend/epson2-ops.c | 27 +- backend/epson2-ops.h | 1 + backend/epson2.c | 10 +- backend/epson2_net.c | 41 +- backend/epson2_net.h | 3 - backend/epson_usb.c | 74 +- backend/fujitsu-scsi.h | 24 +- backend/fujitsu.c | 801 ++-- backend/fujitsu.conf.in | 18 +- backend/fujitsu.h | 49 +- backend/genesys.c | 656 +-- backend/genesys.conf.in | 3 + backend/genesys.h | 35 +- backend/genesys_conv.c | 44 +- backend/genesys_conv_hlp.c | 90 +- backend/genesys_devices.c | 384 +- backend/genesys_gl124.c | 311 +- backend/genesys_gl124.h | 61 +- backend/genesys_gl646.c | 219 +- backend/genesys_gl646.h | 54 +- backend/genesys_gl841.c | 1918 ++++++--- backend/genesys_gl841.h | 84 +- backend/genesys_gl843.c | 145 +- backend/genesys_gl843.h | 16 +- backend/genesys_gl846.c | 186 +- backend/genesys_gl846.h | 20 +- backend/genesys_gl847.c | 150 +- backend/genesys_gl847.h | 20 +- backend/genesys_low.c | 66 +- backend/genesys_low.h | 93 +- backend/hp3900_debug.c | 2 +- backend/hp3900_sane.c | 2 +- backend/kodakaio.c | 416 +- backend/kodakaio.h | 5 +- backend/kvs1025.conf.in | 2 + backend/mustek_pp_ccd300.c | 4 +- backend/pixma.c | 2 +- backend/pixma.h | 4 +- backend/pixma_bjnp.c | 520 ++- backend/pixma_bjnp.h | 2 +- backend/pixma_bjnp_private.h | 46 +- backend/pixma_common.c | 15 +- backend/pixma_common.h | 2 +- backend/pixma_imageclass.c | 117 +- backend/pixma_io_sanei.c | 2 +- backend/pixma_mp150.c | 194 +- backend/pixma_mp730.c | 2 +- backend/pixma_mp750.c | 2 +- backend/pixma_mp810.c | 2 +- backend/pnm.c | 2 +- backend/rts8891.c | 16 +- backend/scripts/pixma_gen_options.py | 390 ++ backend/test.c | 2 +- backend/umax-uc630.c | 12 +- backend/umax.c | 2 +- backend/umax_pp_low.c | 2 +- configure | 26 +- configure.in | 30 +- debian/changelog | 29 + debian/patches/0500-systemd_configure.patch | 12 +- debian/patches/sane-desc.c_debian_mods.patch | 13 - debian/patches/series | 16 +- debian/rules | 5 +- debian/sane-utils.postinst | 4 +- debian/watch | 5 +- doc/descriptions/canon_dr.desc | 95 +- doc/descriptions/epjitsu.desc | 19 +- doc/descriptions/epson.desc | 1 + doc/descriptions/epson2.desc | 1268 +++++- doc/descriptions/fujitsu.desc | 36 +- doc/descriptions/genesys.desc | 8 +- doc/descriptions/kodakaio.desc | 2 +- doc/descriptions/pixma.desc | 182 +- doc/descriptions/unsupported.desc | 21 - doc/releases.txt | 15 +- doc/sane-cardscan.man | 2 +- doc/sane-coolscan.man | 2 +- doc/sane-epjitsu.man | 13 +- doc/sane-epson.man | 4 +- doc/sane-epson2.man | 4 +- doc/sane-genesys.man | 22 +- doc/sane-gt68xx.man | 2 +- doc/sane-kodakaio.man | 2 +- doc/sane-pixma.man | 107 +- doc/sane-scsi.man | 2 +- doc/sane-test.man | 8 +- doc/sane-umax_pp.man | 4 +- doc/sane-usb.man | 2 +- doc/sane.man | 2 +- doc/saned.man | 2 +- frontend/scanimage.c | 163 +- frontend/stiff.c | 10 +- frontend/stiff.h | 2 +- lib/snprintf.c | 1139 ++++-- po/bg.po | 4 +- po/cs.po | 4 +- po/da.po | 4 +- po/de.po | 4 +- po/en_GB.po | 8 +- po/eo.po | 4 +- po/es.po | 4 +- po/fi.po | 4 +- po/fr.po | 4 +- po/gl.po | 4 +- po/it.po | 4 +- po/ja.po | 4 +- po/nb.po | 4 +- po/nl.po | 4 +- po/pl.po | 4 +- po/pt.po | 4 +- po/ru.po | 4 +- po/sane-backends.pot | 5503 -------------------------- po/sv.po | 4 +- po/uk.po | 4 +- sanei/sanei_usb.c | 171 +- testsuite/sanei/sanei_config_test.c | 3 + testsuite/tools/Makefile.am | 2 +- testsuite/tools/Makefile.in | 2 +- testsuite/tools/data/hwdb.ref | 1336 +++---- testsuite/tools/data/udev+acl.ref | 3 +- testsuite/tools/data/udev+hwdb.ref | 5 +- testsuite/tools/data/udev.ref | 3 +- tools/check-usb-chip.c | 210 + tools/epson2usb.pl | 63 + tools/sane-desc.c | 9 +- tools/sane-find-scanner.c | 2 - 145 files changed, 11713 insertions(+), 10961 deletions(-) create mode 100644 ChangeLog-1.0.24 create mode 100644 backend/kvs1025.conf.in create mode 100755 backend/scripts/pixma_gen_options.py delete mode 100644 po/sane-backends.pot create mode 100755 tools/epson2usb.pl diff --git a/.gitignore b/.gitignore index 6c270cd..57d0a42 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,14 @@ -.bzr -.bzrignore -.pc \ No newline at end of file +*.o +*.lo +*.a +*.la +.libs/ +*~ +autom4te.cache/ +Makefile +config.log +config.status +config.cache +libtool +.deps/ +.* diff --git a/ChangeLog b/ChangeLog index 45053b8..e398d74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,602 +1,294 @@ -****** Release of sane-backends 1.0.24. End of code freeze ****** - -2013-09-30 m. allan noah - * po/nl.po: updated translation from Martin Kho. - -2013-09-30 Rolf Bensch - * backend/pixma_mp810.c: fix button support for Canon CS8800F. - -2013-09-24 Rolf Bensch - * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, - doc/sane-pixma.man: New scanner Canon imageCLASS MF4770n - reported by Ralph Little. - -2013-09-18 Alex Belkin - * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id - for dell 1235cn, reported by Jean-Francois Labrousse. - -2013-09-17 m. allan noah - * sanei/sanei_init_debug.c: do our own upcasing to allow backend - debugging in Turkish. Revert prior set_locale() patch. - * po/uk.po: updated by Yuri Chornoivan - * backend/microtek.c: add missing break (#314408) - -2013-09-16 Gerhard Jaeger - * backend/plustek-usbdevs.c: Tweaked motor settings for CanoScan N650U - * backend/plustek.c: Bumped build number +2014-12-31 Paul Newall

+ * backend/kodakaio.c: + connection to device moved from sane_open to sane_start + disconnection move from sane_close to sane_cancel + in order to fix bug where scanner disconnected after 30s idle. -2013-09-13 Rolf Bensch +2014-12-19 Paul Newall

+ * backend/kodakaio.c: + param.depth corrected for lineart mode, was 8 now 1 + sequence of modes changed to make the color mode the default. + +2014-12-16 m. allan noah + * sanei/sanei_usb.c: add calls to sanei_usb_set_altinterface in + sanei_usb_close and sanei_usb_clear_halt- hopefully work around + USB3/xhci problems in Linux. + +2014-11-18 Rolf Bensch + * backend/pixma_imageclass.c: + - Canon i-SENSYS MF8200C and MF8500C use generation 2 protocols. + - Also use has_paper() for generation 2 scanners. + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc: Canon i-SENSYS + MF8200C: ADF supports max. 300DPI. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.14 + +2014-11-15 Rolf Bensch + * backend/avision.c: + - Remove firmware checking for HP5370c scanners. Launchpad bug #1080787, + reported by Night Train. + - Build version 297. + +2014-10-29 Rolf Bensch * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - New scanners Canon Pixma MG2400, MG2500, MG3500, MG5500, MG64000, MG6500 - and MG7100. All scanners need further testing. - * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, - doc/sane-pixma.man: New scanners Canon imageCLASS MF4570dw and - imageRUNNER 1133. All scanners need further testing. - * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.4 - -2013-09-08 paul newall - * kodakaio.desc: Added hero 4.1 model, marked some scanners as staus basic - -2013-08-27 m. allan noah - * acinclude.m4, configure: enable pthread on Linux by default - * sanei/sanei_init_debug.c: use C locale when building debug - env vars, to allow backend debugging in Turkish. Patch from - Olaf Meeuwissen. - -2013-08-26 Chris Bagwell - * sanei/sanei_usb.c: Treat errno of EACCES as access denied. - This is what libusb is return on my Linux box. This will help - give more helpful error messages to user during debugging. - * testsuite/sanie/sanie_usb_test.c: Do not treat open failures - because of permission errors or already opened by other processes - as test failures since this is expected in some cases (such as - network devices that use vendor specific class). - -2013-08-16 Chris Bagwell - * testsuite/sanei/Makefile.am: Add missing data files to distribution. - Pass in $srcdir to sanei_config_test so it knows were data files are - regardless of were ran from. - * testsuite/sanei/sanei_config_test.c: Use full path for config - file. This allows "make distcheck" to work for this testcase - since it uses a different build directory then source directory - and also runs it from build directory. - * testsuite/sanei/sanei_usb_test.c: add a fake name string - when creating MAX_DEVICE fake devices so that strcmp() won't - crash. - * testsuite/tools/Makefile.am: Add missing data files to distribution. - Make use of $srcdir so test case can base when build directory - is not same as source directory. - -2013-08-15 Chris Bagwell - * sanei/sanei_thread.c: Add support for winpthreads used by - mingw64 in addition to preexisting support for pthread-win32 used - by mingw32. Based on work from Michael Cronenworth for - Fedora's mingw64 sane-backends package. - -2013-08-15 Chris Bagwell - * configure.in: Make snmp detection work better when cross conmpiling; - such as mingw builds on Fedora host. Most likely, net-snmp-config - values are for local host so ignore them if matching library isn't - also found. Required updated all autofoo's generated files to newer - version by running 'autoreconf -i -f' and repatching ltmain.sh. - * test-driver: Added missing test-driver that automake installs. - Its expected to exist by the Makefile.in that we also checkin. - -2013-08-11 Stéphane Voltz - * backend/genesys_low.[ch] backend/genesys_conv.c backend/genesys.c - backend/genesys_gl841.c backend/genesys_gl646.c: make use of hardware - gamma tables to implement constrast and brightness correction. - -2013-08-07 Stéphane Voltz - * backend/genesys.[ch] backend/genesys_conv.c doc/sane-genesys.man - po/fr.po: add digital brightness and contrast options. - Add an option to set calibration cache file name. - -2013-08-07 Stéphane Voltz - * frontend/tstbackend.c: add argument to get verbose messages during - checks. - -2013-08-04 Stéphane Voltz - * sanei/sanei_constrain_value.c - testsuite/sanei/sanei_constrain_test.c: fixed the case where the - rounding in sanei_constrain_value computes a value higher than the - range maximum, spotted and proposed by viresh_shirol@yahoo.co.uk . - Added testcase for the bug in testsuite. - -2013-08-02 Stéphane Voltz - * configure configure.in testsuite/Makefile.* testsuite/tools/*: add - a testsuite for sane-desc, then merge hwdb support for sane-desc by - Tom Gundersen . - -2013-07-31 m. allan noah - * backend/canon_dr*: backend version 41 - - initial P-208 and P-215 support - - bug fix for calibration of scanners with duplex_offset - - allow duplex_offset to be controlled from config file - -2013-07-30 Stéphane Voltz - * backend/genesys.c: fixed typo when defining OPT_SWDEROTATE cap - (#314339). - -2013-07-19 Rolf Bensch - * backend/pixma_mp150.c: Canon Pixma MX920 has duplex ADF and supports - max. 600 dpi @ ADF. - -2013-07-18 Rolf Bensch - * backend/pixma_mp810.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - Canon PIXMA MG8200 is working now. - * backend/pixma.[ch], backend/pixma_mp150.c, backend/pixma_mp810.c, - backend/pixma_sane_options.[ch], doc/sane-pixma.man, po/de.po: - - New button option --scan-resolution. Scan resolution is provided from - some multi function devices. - - Add some detailed button option description to the pixma man page. - * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.3 - -2013-06-26 Stéphane Voltz - * backend/genesys.[ch] backend/genesys_devices.c backend/genesys_gl124.[ch] - backend/genesys_low.[ch]: improve scanning speed and quality for GL124 - based scanner by implementing half ccd mode below 600 dpi, - thanks for an hardware donation from Dany Qumsiyeh. - -2013-07-03 Rolf Bensch + New Canon scanners MAXIFY MB5000, MB5300, MB2000 and MB2300; + PIXMA MG7500, MG6600, MG5600, MG2900 and E460. All scanners need further + testing. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.13 * doc/descriptions/pixma.desc, doc/sane-pixma.man: - Canon PIXMA MG5200 Series support reported by Dimitri Fellous. - * .gitignore: ignore all .* files - -2013-06-27 Rolf Bensch - * backend/pixma.c: fix mode list for infrared scans - -2013-06-27 m. allan noah - * backend/fujitsu*: backend v117 - - default buffer-mode to off - - improved error handling in sane_start - - image width must be multiple of 8 when swcrop is used before binarization (iX500) - - check hopper sensor before calling object_position(load) on iX500 - * .gitignore: ignore .deps directories - -2013-06-26 Stéphane Voltz - * backend/genesys.c backend/genesys.conf.in backend/genesys_devices.c - backend/genesys_gl846.c backend/genesys_gl846.h backend/genesys_low.c - backend/genesys_low.h: add experimental description and code for the - GL845 based Opticbook 3800. - -2013-06-22 Alex Belkin - * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: multiple - usb ids for Samsung models, reported by Mikhail Elhimov. - -2013-06-21 Rolf Bensch - * doc/descriptions/pixma.desc: Canon PIXMA MG3100 Series WLAN support - reported by Torben Nielsen. - -2013-06-19 Stéphane Voltz - * frontend/scanimage.c: protect for group option with incorrect - capabilites. - * frontend/tstbackend.c: add test to check is group option are - settable. Fix test_getdevices() function. - -2013-06-18 Stéphane Voltz - * backend/genesys.c: add missing cap to 2 option group tp fix long - argument option bug in scanimage. - -2013-06-15 Rolf Bensch - * backend/pixma_mp810.c: fix test mode - -2013-06-10 Stéphane Voltz - * tools/check-usb-chip.c: add genesys GL128, GT-68xx usb chip - detection. - -2013-06-10 Rolf Bensch - * backend/pixma_mp810.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - New scanner Canon CanoScan 9000F Mark II. - * backend/pixma_mp810.c: Disable TPU negatives scan for CS8800F and CS9000F. - Negatives scan has no benefit for the user and disabling avoids confusion. - -2013-06-03 Stéphane Voltz - * tools/sane-find-scanner.c tools/check-usb-chip.c: add genesys usb - chip detection when compiled for libusb-1.0 . - -2013-06-03 Stéphane Voltz - * backend/genesys_gl646.c: #314293 fix - -2013-05-29 Rolf Bensch - * doc/sane-pixma.man: - - HTML parseable name section (bug #314283) - - typo in device names - -2013-05-27 Stéphane Voltz - * backend/genesys_gl646.c: #314261 fix - -2013-05-11 Rolf Bensch - * README.linux: some distros need libusb-1_0-devel. - -2013-05-11 Jonathan Bravo Lopez - * backend/hp3900_rts8822.c: fix compilation warnings. - -2013-04-26 Rolf Bensch - * backend/pixma.[ch], backend/pixma_common.[ch], backend/pixma_imageclass.c, - backend/pixma_io_sanei.c, backend/pixma_mp150.c, backend/pixma_mp7[35]0.c, - backend/pixma_mp810.c: update copyright. + Canon PIXMA MG2900 Series is working, reported by Yannick Dirou. -2013-04-24 Rolf Bensch - * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - New scanners Canon Pixma E510, E610 and MX720. All scanners need further - testing. +2014-10-27 Rolf Bensch + * backend/pixma_mp150.c: Canon PIXMA MG3500 Series doesn't need special + image post processing. + * doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon PIXMA MG3500 Series is working. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.12 -2013-04-19 Rolf Bensch +2014-10-20 Rolf Bensch * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, - doc/sane-pixma.man: New scanner Canon i-SENSYS MF3010 reported by - Nathan Stewart. + doc/sane-pixma.man: New Scanner Canon imageCLASS D530. + * backend/pixma_mp150.c: + - increase calibration timeout + - calibration can finish with 0x01 or 0x02 -2013-04-11 Rolf Bensch +2014-09-18 Rolf Bensch * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - New scanners Canon Pixma MG2200, MG3200, MG5400, MX390, MX450, MX520 and - MX920. All scanners need further testing. - -2012-04-03 Alex Belkin - * doc/descriptions/xerox_mfp.desc: add Samsung SCX-4835FD networked - support, reported by Dave Lewis. USB mode doesn't work. - -2013-04-02 Stéphane Voltz - * backend/lexmark.c backend/lexmark.h: fix device detection to - handle hotplugging and unplugging of USB devices. USe - sanei_usb_exit(). - -2013-03-29 Stéphane Voltz - * backend/gt68xx.c backend/gt68xx_low.h: fix device detection to - handle hotplugging and unplugging of USB devices. - * frontend/tstbackend.c: a test to loop over snae_get_devices to - check if a backend handle hotplugging correctly - -2013-03-27 Stéphane Voltz - * backend/genesys.c backend/genesys_low.h backend/genesys_gl846.c: - warning fixes, SANE option correctness fixes. - -2013-03-25 Rolf Bensch - * backend/pixma_mp150.c: fix button support for Canon Pixma MG6300. - -2013-03-24 Stéphane Voltz - * sanei/test_wire.c, testsuite/sanei/sanei_*test.c: move test program - to testsuite/sanei. Add unit test programs for sanei_check_*, - sanei_constrain_*, sanei_config_* and sanei_usb_* functions. - -2013-03-24 Stéphane Voltz - * backend/genesys.c: make use of the new sanei_usb_scan_devices function - in sane_get_devices. - -2013-03-24 Stéphane Voltz - * sanei/sanei_usb.c include/sane/sanei_usb.h: - separate device search logic from usb init by creating a - sanei_usb_scan_devices. Add a sanei_usb_exit function to free - allocated resources by sanei_usb_init. - -2013-03-21 Rolf Bensch - * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - New scanner Canon Pixma MP230 reported by Petar Dodev. - -2013-03-18 Stéphane Voltz - * backend/hp5590.c backend/nec.c backend/sharp.c backend/stv680: - apply use after free fixes, bugs #314035, #314036, #314037 and - #314038 - * backend/hp4200.c: fix a potential division by O, bug #314042 - All five patches for these bugs were provided by Nickolai Zeldovich - + Canon Pixma MG5500 Series is working, bug #314819. -2013-03-15 Rolf Bensch +2014-09-16 Rolf Bensch + * doc/descriptions/pixma.desc, doc/sane-pixma.man: Canon Pixma MG2400 Series + is working, reported by Marcus Wellnitz. * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - New scanner Canon Pixma MG6300 reported by Theo van Rijn. - -2013-02-28 Stéphane Voltz - * configure.in configure: restored HAVE_USBCALLS like initially - committed for OS/2 support - -2013-03-04 Oliver Schwartz - * backend/snapscan-options.c backend/snapscan-scsi.c backend/snapscan.c - backend/snapscan-sources.c backend/snapscan.h - doc/descriptions/snapscan.desc: Added support for Acer Scanwit 2720S - implemented by Andrew Goddbody. - -2013-02-28 Stéphane Voltz - * sanei/sanei_usb.c: only free devanme when reusing a device slot in - device list + Canon Pixma MX530 Series is working, reported by Stephen Weston. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.11 -2013-02-28 Rolf Bensch - * README.linux: ease installation procedure. +2014-09-13 Paul Newall

+ * backend/kodakaio.c, backend/kodakaio.h: + * Added lineart mode with threshold option. -2013-02-27 Stéphane Voltz - * doc/descriptions/genesys.desc: update G2410 status to basic - -2013-02-27 Stéphane Voltz - * backend/rts8891.c backend/rts88xx_lib.c backend/lexmark.c - backend/lexmark_low.c backend/rts8891_low.c: cppcheck errors and - warnings fixes - -2013-02-27 Rolf Bensch - * README.linux: fix installation path for libsane.la. - -2013-02-22 Gerhard Jaeger - * tools/sane-find-scanner.c: Fix another bug in the libusb1 - part of function check_libusb_device() that prevents sanner - detection for certain devices. - -2013-02-20 Gerhard Jaeger - * tools/sane-find-scanner.c: Setup libusb1 debugging after - initialization otherwise a segfault appears in triple -v mode - * sanei/sanei_usb.c: Free heap memory, acquired via strdup for - devname, in sanei_usb_close() - * po/de.po: Fixed typo - -2013-02-18 Rolf Bensch - * backend/pixma.[ch], backend/pixma_common.[ch], backend/pixma_imageclass.c, - backend/pixma_mp150.c, backend/pixma_mp7[35]0.c, backend/pixma_mp810.c, - doc/descriptions/pixma.desc, doc/sane-pixma.man, po/de.po: - - add infrared scan support for Canon Canoscan 9000F - - Pixma backend version 0.17.2 - -2013-02-13 Stéphane Voltz - * backend/genesys*.[ch]: cppcheck errors fixes - -2013-02-13 Gerhard Jaeger - * backend/plustek_pp.c: Bumped build number - * backend/plustek-pp*: Fixed kernel module build for recent kernels - Defined internal "ULong" types to be in fact 32 bit wide, - this should fix issues on 64 bit machines. - * doc/plustek/Plustek-PARPORT.changes: Update - -2013-02-13 Gerhard Jaeger - * backend/plustek.c: Bumped build number - * backend/plustek-usbscan.c backend/plustek-usbshading.c: Cleanup - * backend/plustek-usb.h backend/plustek-usbdevs.c backend/plustek-usbhw.c: - Added support for Q-Scan A6 portable scanner - * doc/descriptions/plustek.desc: Added entry for Q-Scan A6 - Q-Scan A6 Patch submitted and tested by Hiroshi Miura. Bug #312073. - * doc/sane-plustek.man doc/plustek/Plustek-USB.changes: Update - -2013-02-11 Rolf Bensch - * backend/pixma_common.c, backend/pixma_imageclass.c, - doc/descriptions/pixma.desc: fixed adf paper empty for Canon i-SENSYS - MF4550d. Bug #313674. - -2013-02-11 Stéphane Voltz - * tools/sane-desc.c: fix minor memleaks and whitespace at end of line. - -2013-02-09 Rolf Bensch - * backend/pixma.c, backend/pixma_mp750.c, backend/pixma_mp810.c, - backend/pixma_sane_options.c: fixed compiler warnings. - * backend/pixma.c, backend/pixma_io_sanei.c, backend/pixma_mp150.c, - backend/pixma_mp7[35]0.c, backend/pixma_mp810.c: fixed cppcheck warnings. - -2013-02-06 Rolf Bensch - * backend/pixma_mp150.c: fixed button support for Canon Pixma MG6200 - by Matthias Thon. - -2013-02-01 Stéphane Voltz - * backend/genesys_low.c backend/genesys_gl843.c - backend/genesys_gl846.c: minor usb firmware setup changes - -2013-01-31 Stéphane Voltz - * backend/genesys.[ch] backend/genesys_devices.c - backend/genesys_gl124.c backend/genesys_low.h: add support for LIDE - 210 fifth button. - -2013-01-29 Stéphane Voltz - * backend/genesys*.[ch] : ASIC init refactor. Groundwork for GL846 - support. - -2013-01-24 Rolf Bensch - * backend/pixma_mp150.c: fixed 1200 dpi scan for Canon Pixma MG2100. +2014-09-07 Paul Newall

+ * backend/kodakaio.c: + * Fixed error where the colour compensation curves did not have enough + elements and this caused speckles in areas of very low or high colour. + +2014-08-23 Louis Lagendijk + * backend/pixma_bjnp.c: + * Keep TCP-connection closed untill we really need it. This avoids + the scanner closing the TCP-connection when idle + * Add an explicit error message when we detect that the scanner + closed the TCP-connection + +2014-08-16 Rolf Bensch + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanners Canon i-SENSYS MF8200C Series and MF8500C Series. MF8500C + Series need further testing. + * doc/sane-pixma.man: add up to now undocumented verbose debug-level + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.10 * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - Canon Pixma MG2100 support reported by David Durgee. - * backend/pixma_imageclass.c: fixed usb checksums for MF4100. - -2013-01-19 Paul Newall - * backends/kodakaio.c: - Hero 4.1 added. - -2013-01-18 Rolf Bensch - * backend/pixma.c, backend/pixma_mp810.c: fixed button support for Canon - Canoscan CS9000F. - * doc/sane-pixma-man: additional description for button support. - -2013-01-16 Paul Newall - * doc/descriptions/kodakaio.desc: - Desc file updated. + Canon PIXMA MX720 Series scanner is working (bug #314787). -2013-01-14 Rolf Bensch +2014-07-25 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanners Canon Pixma E400, E560, MX470 and MX530. All scanners need + further testing. + +2014-07-14 m. allan noah + * frontend/scanimage.c: batch-print option and exit value changes + from Jeff Breidenbach jeff@jab.org + +2014-07-01 Stéphane Voltz + * testsuite/sanei/sanei_config_test.c: fix #314694 by exporting a + specific SANE_CONFIG_DIR env dir for tests + +2014-06-29 Stéphane Voltz + * backend/genesys_gl646.c: fix regression in coarse gain calibration + +2014-06-05 Tom Callaway + * lib/snprintf.c: update to newer version from LPRng. The old version is + licensed under the Artistic License 1.0 which isn't compatible with the + GPL and arguably non-free. + +2014-06-02 Stéphane Voltz + * backend/genesys_*.[ch]: add internal ini_scan_regs_api. Add proper + target speed for LiDE 110/210 grey mode motor tables. + +2014-05-29 Paul Newall + * backend/kodakaio.c: change to comment on ./configure parameters + +2014-05-26 Rolf Bensch + * backend/pixma_mp150.c: fix ADF paper empty @ start scanning for Canon + Pixma MP150 based ADF scanners + * backend/pixma_common.c: remove unused variable + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.9 + +2014-05-08 Rolf Bensch + * backend/pixma_mp150.c: fix MG7100 image data post processing @ high + resolutions > 600dpi. + * doc/descriptions/pixma.desc, doc/sane-pixma.man: Canon Pixma MG7100 + Series scanner is working, reported by Gert Cauwenberg. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.8 + +2014-05-13 Stéphane Voltz + * backend/genesys_gl646.[ch] backend/genesys.c backend/genesys_low.c: + fix bug #314663. Set gamma for gl646 devices only at scan time. Reset + endpoint each time before leaving. + +2014-05-08 Rolf Bensch + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.7 + * backend/pixma_mp150.c: + - all Canon Pixma MP150 based ADF scanners support 14" legal paper size + - fix ADF paper empty bug for Canon Pixma MP150 based ADF scanners + * doc/descriptions/pixma.desc: remove comments for Canon Pixma MP150 based + ADF scanners: adf empty buggy + * doc/sane-pixma.man: Canon Pixma MX360 shouldn't hang anymore (@ ADF paper + empty) + +2014-04-07 Rolf Bensch + * doc/descriptions/pixma.desc, doc/sane-pixma.man: Canon Pixma MX410 + is working, reported from Javier Gorostiza. + +2014-03-21 Rolf Bensch + * doc/descriptions/pixma.desc, doc/sane-pixma.man: Canon Pixma MG3200 + is working, reported in ubuntuforums.org/showthread.php?t=2072162. + * doc/descriptions/pixma.desc: rename WLAN to WiFi + * backend/pixma_mp150.c: + - Canon Pixma MX520 Series supports 14" legal paper size in ADF mode. + - MX520 has button support. + * backend/pixma_common.c: Clamp minimum image size to 16 px x 16 px. Some + new scanners need minimum 16 px height. + * doc/descriptions/pixma.desc, doc/sane-pixma.man: Canon Pixma MX520 Series + is working, reported by Trygve Flathen. + +2014-02-28 Rolf Bensch * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, - doc/sane-pixma.man: - - new scanner Canon i-SENSYS MF4550d. Bug #313674. - - new scanner Canon i-SENSYS MF5880dn. Bug #313613. - - new scanner Canon i-SENSYS MF6680dn. Bug #313922. - -2013-01-11 Rolf Bensch - * backend/pixma_mp810.c: - - formatted white space - - Canon Pixma MP970 & MP990: fix for broken post_process_image_data. + doc/sane-pixma.man: Rename Canon i-SENSYS MF4550d to Canon i-SENSYS MF4500 + Series. This fixes ethernet problems. Patch from chrysn. + +2014-02-24 Stéphane Voltz + * doc/sane-genesys.man backend/genesys.[ch]: + avoid calibration file name collision in case of several identical + scanners + +2014-02-10 Louis Lagendijk + * backend/pixma_bjnp.c backend/pixma_bjnp.h backend/pixma_bjnp_private.h: + - Added support for Canon laser multi-functionals using the MFNP protocol over port 8610 + - Improved debug-logging to be more readable + +2014-02-08 Rolf Bensch + * backend/pixma_mp150.c: + - Canon Pixma MX510 Series supports 14" legal paper size in ADF mode. * doc/descriptions/pixma.desc, doc/sane-pixma.man: - Canon Pixma MG5100 support reported by Patrick Viola. - -2013-01-10 Louis Lagendijk - * Changed the pixma_bjnp.c implementation to use its own debug environment - variable (SANE_DEBUG_BJNP) so debugging for the bjnp protocol and the - backend proper can be controlled independently. - Updated manpage for sane-pixma to document the above changes as well - as the changed scannner buttjn options and the fact the bjnp protocol - has added support for IPv6 - -2013-01-10 Louis Lagendijk - * Added optional support in sanedi.c for systemd socket activation. This - will allow for using backend debugging using SANE_DEBUG_xxx to be used - for saned controlled scanning when using socket activation. When only the - socket is received we use the existing code path. - -2013-01-08 Rolf Bensch - * backend/pixma_mp810.c: fix for broken tpu scan. - -2013-01-03 Paul Newall - * backend/kodakaio.c kodakaio.h: - Detecting end of paper when using adf is now an option. - Alternatively the image is padded with the background colour to make up - the specified image size. - -2012-12-31 Paul Newall - * backend/kodakaio.c kodakaio.h kodakaio.conf kodakaio.conf.in: - better fix for bug where adf could not scan more than 1 page with net connection - end of paper now detected with adf, if it is less than the selected size - ESP 2170 and Hero 9.1 can now do 1200dpi - -2012-12-31 Rolf Bensch - * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - New scanner Canon Pixma MG4200 reported by nuxer. + - Canon Pixma MX510 Series is working, reported by sebastien_gd. -2012-12-28 Alex Belkin - * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id - for Samsung CLX-3300 Series, reported by Jarkko A-L. +2014-01-29 m. allan noah + * backend/umax-uc630.c: updates from Ondrej Zary -2012-12-23 Paul Newall - * backend/kodakaio.c: - fix bug where adf could not scan more than 1 page with net connection +2014-01-21 Stéphane Voltz + * doc/descriptions/unsupported.desc doc/descriptions/genesys.desc: + update status of the HP Scanjet 4850C -2012-12-13 Rolf Bensch - * README.linux: Installation description moved to top and some editing. +2014-01-17 Rolf Bensch + * doc/descriptions/pixma.desc: Update specification file for + Canon i-SENSYS MF4800 Series: + - Ethernet is buggy. + - ADF is working. -2012-12-09 Paul Newall - * backend/kodakaio.c: - add adf to ESP2170. Reduce the default adf y length to 11.3 inch +2014-01-09 Gerhard Jaeger + * tools/sane-find-scanner.c tools/check-usb-chip.c: Add LM983x usb + chip detection when compiled for libusb-1.0. -2012-12-09 Stéphane Voltz - * backend/genesys*.c backend/genesys_low.h: reworked gamma table - handling. Compute gamma table outside send_gamma_table so default - gamma table use device specific gamma values defined in device - description. +2014-01-02 Rolf Bensch + * doc/descriptions/pixma.desc: ADF is working for Canon i-SENSYS MF4800 + Series, reported by Yvan L. Gélinas. -2012-12-07 Rolf Bensch - * backend/pixma.h: Pixma backend version 0.17.1 - * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - - Canon Pixma MG3100 support reported by Madis Lõhmus. - - Canon Pixma MG6200 support reported by Matthias Thon. - - Canon Pixma MX890 support reported by Henry Ptasinski. +2014-01-02 Rolf Bensch + * backend/pixma.[ch], backend/pixma_common.[ch], backend/pixma_imageclass.c, + backend/pixma_io_sanei.c, backend/pixma_mp150.c, backend/pixma_mp7[35]0.c, + backend/pixma_mp810.c: update copyright. * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, - doc/sane-pixma.man: - - Canon imageCLASS MF4430 support reported by Michael Mik. This device is - a MF4410 with ADF. - -2012-12-05 Stéphane Voltz - * backend/genesys.c backend/genesys_gl124.c: add binary data logging - for gl124 based scanners. Issue park command as early as possible to - speed up batch scans - -2012-11-28 Paul Newall - * backend/kodakaio.c backend/kodakaio.h backend/kodakaio.conf.in - backend/Makefile.am backend/Makefile.in docs/descriptions/kodakaio.desc: - Use avahi instead of cups for network autodetection - -2012-11-24 Stéphane Voltz - * backend/rts9918.c backend/rts8891_low.c backend/rts8891_low.h: - fix batch scan by adding asynchronous head parking. Fix 600 and 1200 - dpi scan mode for sensor type 1 - -2012-11-11 Stéphane Voltz - * backend/genesys.c backend/genesys_gl124.c: improve calibration for - gl124 based scanners. Fix head parking issue at 1200 dpi. - -2012-11-02 Stéphane Voltz - * doc/descriptions/unsupported.desc: add USB ID 0x07b3, 0x0802 - -2012-11-02 Stéphane Voltz - * configure configure.in doc/Makefile.am doc/Makefile.in: add optional - doxygen documentation generation for genesys backend. - -2012-10-31 Louis Lagendijk - * backend/scripts/pixma_gen_options.py - Updated formatting of produced files to match pixma.c formatting - without need for manual editing - * pixma.[ch] pixma_mp810.c pixma_mp150.c - Rewrite of button option handling. Button options can now be read - without triggering through the button-update option. Buton-update - options is left for ease of use with xsane - Options are cached so that only when an option is read again all - options are re-read. - -2012-10-29 Alex Belkin - * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id - for Samsung SCX-4833FD, reported by Frank Pennycook; description for - SCX-3405W working in networking mode, reported by Patrick Mackinlay. - -2012-10-24 Stéphane Voltz - * backend/genesys_*.[ch]: Lide 35 improvements, doxygen fixes, - experimental 100 dpi support for Canoscan 4400F and 8400F - -2012-10-24 Mattias Ellert - * configure.in, configure: Unset VERSION during the SCSI header check - (Check fails on MacOS X if VERSION is defined) - -2012-10-22 Mattias Ellert - * po/sv.po: Updated Swedish translation - * backend/pixma_bjnp.c: Fix arguments to IPv6 macros - -2012-10-18 m. allan noah - * backend/canon*: IX-4015 support by Ondrej Zary - -2012-10-17 Alex Belkin - * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id - for Samsung SCX-4100, reported by Antonello Lobianco. - -2012-09-18 Alex Belkin - * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id - for Samsung SCX-4729FD, reported by wom balton. - -2012-09-12 Rolf Bensch - * doc/descriptions/pixma.desc, doc/sane-pixma.man: - Canon imageCLASS MF5730 support reported by Ondrej Zary. + doc/sane-pixma.man: bug #314411, Canon imageCLASS MF4570dw is working. -2012-09-10 Rolf Bensch - * doc/descriptions/unsupported.desc: Removed Canon Multipass 390 from - unsupported device list. +2013-12-27 Rolf Bensch + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: + - Canon i-SENSYS MF4800 Series has ADF and supports 14" legal paper size + in ADF mode. + - Canon i-SENSYS MF4800 Series is working, reported by Yvan L. Gélinas. -2012-09-08 Louis Lagendijk - * backend/pixma_bjnp.c, backend/pixma_bjnp_private.h - bulk reading rewritten and solved the case where the scanner returns - a 0 length payload. - Use MDL string instead of DES as it is mre fool proof when matching - the model string from the backend +2013-12-23 Rolf Bensch + * backend/pixma_common.c: fix usb cmd transaction timeout -2012-09-06 Stéphane Voltz - * backend/genesys_gl646.c backend/genesys.c: enable hardware lineart - for Strobe XP200 +2013-12-23 Stéphane Voltz + * backend/genesys_devices.c backend/genesys.c backend/genesys_low.h + backend/genesys_gl841.[ch]: color calibration improvement for LiDE80, + working LEDADD for gl841 CIS scanners -2012-09-05 Rolf Bensch +2013-12-16 Rolf Bensch * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, - doc/sane-pixma.man: New scanner reported by Eric Schwartz. Bug #313761. - * backend/pixma_mp150.c: 14" (ADF) / A4 (Flatbed) exception for Pixma MX420 - reported by D.Möller. Same exception also added for Pixma MX410. - -2012-09-04 Rolf Bensch - * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - Pixma MG5300 support reported by Gernot Hassenpflug. - -2012-09-03 Rolf Bensch - * README.linux: Installation description updated for sane-backends - 1.0.24git. - * doc/descriptions/pixma.desc, doc/sane-pixma.man: - Canon imageRunner 1020/1024/1025 support reported by Yuri Kirin. - Bug #313203. - * backend/pixma_mp150.c: Use xdpi to check for 14" / A4 scan. + doc/sane-pixma.man: + - rename Canon imageCLASS MF4770n to i-SENSYS MF4700 Series + - rename Canon i-SENSYS MF4890dw to MF4800 Series * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - Pixma MX370 support reported by Daniel Lehmann. Bug #313750. - * backend/pixma_mp150.c: PIXMA_CAP_EXPERIMENT removed from new scanners. - -2012-08-27 Louis Lagendijk - * pixma_bjnp.c pixma_bjnp_private.h - Added working scan-button support - Added IPv6 support - Some clean up and refactoring + - Canon MX920 reported as working; ADF is still buggy + - MX920 has 14" ADF paper length + - MX920 has button support + - fix vertical stripe shifting for MX920 + - tidy function calc_shifting() + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.6 + +2013-12-16 Stéphane Voltz + * doc/descriptions/genesys.desc: update LiDE 80 + * backend/genesys_devices.c backend/genesys.c backend/genesys_low.h + backend/genesys_gl841.[ch]: basic support for LiDE 80 + +2013-12-10 m. allan noah + * backend/fujitsu*: fujitsu backend v118 + - support fi-7160, fi-7260, fi-7180 and fi-7280 + - remove unused var from do_scsi_cmd() + - added more request_sense options + - add adv_paper_protect option + - enable paper protection by default + - increase max_x_fb for fi-6240 and fi-6230 + +2013-12-09 m. allan noah + * backend/canon_dr*: canon_dr backend v42 + - initial DR-G1100 support + - add support for paper sensors (P-215 & P-208) + - add initial support for card reader (P-215) + - removed unused var from do_scsi_cmd() + +2013-11-21 Stéphane Voltz + * testsuite/tools/Makefile.*: handle sane git version change in tests. + +2013-10-19 Stéphane Voltz + * doc/descriptions/genesys.desc doc/Descriptions/unsupported.desc: + update LiDE 80 and HP2400 information + * backend/genesys_devices.c backend/genesys.conf.in backend/genesys.c + backend/genesys_low.h backend/genesys_gl841.[ch]: add first element of + LiDE 80 support. + +2013-10-15 Paul Newall + * configure.in: detection of cups was commented out. Avahi is now used + for autodetection in kodakaio so the detection of cups is no longer required. + +2013-10-14 Paul Newall + * backend/kodakaio.c: fix bug #314301, + Segfault when unexpected data returned by avahi auto discovery. + +2013-10-11 Rolf Bensch + * backend/pixma_imageclass.c: Use generation variable instead of single + defines of scanner pid's. Now new scanners should work without extensive + code editing. + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: New scanner Canon i-SENSYS MF4890dw. This scanner needs + further testing. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.5 -2012-08-27 Rolf Bensch - * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: - Pixma MG6100 support reported by Yann Bonnamy. Bug #313471. +2013-10-02 Rolf Bensch + * README.linux: Update Installation description for 1.0.25git. -2012-08-26 m. allan noah - * ChangeLog*, configure*, Makefile.in, doc/desc/{kodakaio,kvs40xx}.desc: - Various updates related to starting 1.0.24git +2013-09-30 m. allan noah + * ChangeLog*, configure*, doc/releases.txt: + Various updates related to starting 1.0.25git -Older entries can be found in ChangeLog-1.0.23. +Older entries can be found in ChangeLog-1.0.24. diff --git a/ChangeLog-1.0.24 b/ChangeLog-1.0.24 new file mode 100644 index 0000000..45053b8 --- /dev/null +++ b/ChangeLog-1.0.24 @@ -0,0 +1,602 @@ +****** Release of sane-backends 1.0.24. End of code freeze ****** + +2013-09-30 m. allan noah + * po/nl.po: updated translation from Martin Kho. + +2013-09-30 Rolf Bensch + * backend/pixma_mp810.c: fix button support for Canon CS8800F. + +2013-09-24 Rolf Bensch + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: New scanner Canon imageCLASS MF4770n + reported by Ralph Little. + +2013-09-18 Alex Belkin + * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id + for dell 1235cn, reported by Jean-Francois Labrousse. + +2013-09-17 m. allan noah + * sanei/sanei_init_debug.c: do our own upcasing to allow backend + debugging in Turkish. Revert prior set_locale() patch. + * po/uk.po: updated by Yuri Chornoivan + * backend/microtek.c: add missing break (#314408) + +2013-09-16 Gerhard Jaeger + * backend/plustek-usbdevs.c: Tweaked motor settings for CanoScan N650U + * backend/plustek.c: Bumped build number + +2013-09-13 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanners Canon Pixma MG2400, MG2500, MG3500, MG5500, MG64000, MG6500 + and MG7100. All scanners need further testing. + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: New scanners Canon imageCLASS MF4570dw and + imageRUNNER 1133. All scanners need further testing. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.4 + +2013-09-08 paul newall + * kodakaio.desc: Added hero 4.1 model, marked some scanners as staus basic + +2013-08-27 m. allan noah + * acinclude.m4, configure: enable pthread on Linux by default + * sanei/sanei_init_debug.c: use C locale when building debug + env vars, to allow backend debugging in Turkish. Patch from + Olaf Meeuwissen. + +2013-08-26 Chris Bagwell + * sanei/sanei_usb.c: Treat errno of EACCES as access denied. + This is what libusb is return on my Linux box. This will help + give more helpful error messages to user during debugging. + * testsuite/sanie/sanie_usb_test.c: Do not treat open failures + because of permission errors or already opened by other processes + as test failures since this is expected in some cases (such as + network devices that use vendor specific class). + +2013-08-16 Chris Bagwell + * testsuite/sanei/Makefile.am: Add missing data files to distribution. + Pass in $srcdir to sanei_config_test so it knows were data files are + regardless of were ran from. + * testsuite/sanei/sanei_config_test.c: Use full path for config + file. This allows "make distcheck" to work for this testcase + since it uses a different build directory then source directory + and also runs it from build directory. + * testsuite/sanei/sanei_usb_test.c: add a fake name string + when creating MAX_DEVICE fake devices so that strcmp() won't + crash. + * testsuite/tools/Makefile.am: Add missing data files to distribution. + Make use of $srcdir so test case can base when build directory + is not same as source directory. + +2013-08-15 Chris Bagwell + * sanei/sanei_thread.c: Add support for winpthreads used by + mingw64 in addition to preexisting support for pthread-win32 used + by mingw32. Based on work from Michael Cronenworth for + Fedora's mingw64 sane-backends package. + +2013-08-15 Chris Bagwell + * configure.in: Make snmp detection work better when cross conmpiling; + such as mingw builds on Fedora host. Most likely, net-snmp-config + values are for local host so ignore them if matching library isn't + also found. Required updated all autofoo's generated files to newer + version by running 'autoreconf -i -f' and repatching ltmain.sh. + * test-driver: Added missing test-driver that automake installs. + Its expected to exist by the Makefile.in that we also checkin. + +2013-08-11 Stéphane Voltz + * backend/genesys_low.[ch] backend/genesys_conv.c backend/genesys.c + backend/genesys_gl841.c backend/genesys_gl646.c: make use of hardware + gamma tables to implement constrast and brightness correction. + +2013-08-07 Stéphane Voltz + * backend/genesys.[ch] backend/genesys_conv.c doc/sane-genesys.man + po/fr.po: add digital brightness and contrast options. + Add an option to set calibration cache file name. + +2013-08-07 Stéphane Voltz + * frontend/tstbackend.c: add argument to get verbose messages during + checks. + +2013-08-04 Stéphane Voltz + * sanei/sanei_constrain_value.c + testsuite/sanei/sanei_constrain_test.c: fixed the case where the + rounding in sanei_constrain_value computes a value higher than the + range maximum, spotted and proposed by viresh_shirol@yahoo.co.uk . + Added testcase for the bug in testsuite. + +2013-08-02 Stéphane Voltz + * configure configure.in testsuite/Makefile.* testsuite/tools/*: add + a testsuite for sane-desc, then merge hwdb support for sane-desc by + Tom Gundersen . + +2013-07-31 m. allan noah + * backend/canon_dr*: backend version 41 + - initial P-208 and P-215 support + - bug fix for calibration of scanners with duplex_offset + - allow duplex_offset to be controlled from config file + +2013-07-30 Stéphane Voltz + * backend/genesys.c: fixed typo when defining OPT_SWDEROTATE cap + (#314339). + +2013-07-19 Rolf Bensch + * backend/pixma_mp150.c: Canon Pixma MX920 has duplex ADF and supports + max. 600 dpi @ ADF. + +2013-07-18 Rolf Bensch + * backend/pixma_mp810.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon PIXMA MG8200 is working now. + * backend/pixma.[ch], backend/pixma_mp150.c, backend/pixma_mp810.c, + backend/pixma_sane_options.[ch], doc/sane-pixma.man, po/de.po: + - New button option --scan-resolution. Scan resolution is provided from + some multi function devices. + - Add some detailed button option description to the pixma man page. + * backend/pixma.h, doc/descriptions/pixma.desc: Pixma backend version 0.17.3 + +2013-06-26 Stéphane Voltz + * backend/genesys.[ch] backend/genesys_devices.c backend/genesys_gl124.[ch] + backend/genesys_low.[ch]: improve scanning speed and quality for GL124 + based scanner by implementing half ccd mode below 600 dpi, + thanks for an hardware donation from Dany Qumsiyeh. + +2013-07-03 Rolf Bensch + * doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon PIXMA MG5200 Series support reported by Dimitri Fellous. + * .gitignore: ignore all .* files + +2013-06-27 Rolf Bensch + * backend/pixma.c: fix mode list for infrared scans + +2013-06-27 m. allan noah + * backend/fujitsu*: backend v117 + - default buffer-mode to off + - improved error handling in sane_start + - image width must be multiple of 8 when swcrop is used before binarization (iX500) + - check hopper sensor before calling object_position(load) on iX500 + * .gitignore: ignore .deps directories + +2013-06-26 Stéphane Voltz + * backend/genesys.c backend/genesys.conf.in backend/genesys_devices.c + backend/genesys_gl846.c backend/genesys_gl846.h backend/genesys_low.c + backend/genesys_low.h: add experimental description and code for the + GL845 based Opticbook 3800. + +2013-06-22 Alex Belkin + * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: multiple + usb ids for Samsung models, reported by Mikhail Elhimov. + +2013-06-21 Rolf Bensch + * doc/descriptions/pixma.desc: Canon PIXMA MG3100 Series WLAN support + reported by Torben Nielsen. + +2013-06-19 Stéphane Voltz + * frontend/scanimage.c: protect for group option with incorrect + capabilites. + * frontend/tstbackend.c: add test to check is group option are + settable. Fix test_getdevices() function. + +2013-06-18 Stéphane Voltz + * backend/genesys.c: add missing cap to 2 option group tp fix long + argument option bug in scanimage. + +2013-06-15 Rolf Bensch + * backend/pixma_mp810.c: fix test mode + +2013-06-10 Stéphane Voltz + * tools/check-usb-chip.c: add genesys GL128, GT-68xx usb chip + detection. + +2013-06-10 Rolf Bensch + * backend/pixma_mp810.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanner Canon CanoScan 9000F Mark II. + * backend/pixma_mp810.c: Disable TPU negatives scan for CS8800F and CS9000F. + Negatives scan has no benefit for the user and disabling avoids confusion. + +2013-06-03 Stéphane Voltz + * tools/sane-find-scanner.c tools/check-usb-chip.c: add genesys usb + chip detection when compiled for libusb-1.0 . + +2013-06-03 Stéphane Voltz + * backend/genesys_gl646.c: #314293 fix + +2013-05-29 Rolf Bensch + * doc/sane-pixma.man: + - HTML parseable name section (bug #314283) + - typo in device names + +2013-05-27 Stéphane Voltz + * backend/genesys_gl646.c: #314261 fix + +2013-05-11 Rolf Bensch + * README.linux: some distros need libusb-1_0-devel. + +2013-05-11 Jonathan Bravo Lopez + * backend/hp3900_rts8822.c: fix compilation warnings. + +2013-04-26 Rolf Bensch + * backend/pixma.[ch], backend/pixma_common.[ch], backend/pixma_imageclass.c, + backend/pixma_io_sanei.c, backend/pixma_mp150.c, backend/pixma_mp7[35]0.c, + backend/pixma_mp810.c: update copyright. + +2013-04-24 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanners Canon Pixma E510, E610 and MX720. All scanners need further + testing. + +2013-04-19 Rolf Bensch + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: New scanner Canon i-SENSYS MF3010 reported by + Nathan Stewart. + +2013-04-11 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanners Canon Pixma MG2200, MG3200, MG5400, MX390, MX450, MX520 and + MX920. All scanners need further testing. + +2012-04-03 Alex Belkin + * doc/descriptions/xerox_mfp.desc: add Samsung SCX-4835FD networked + support, reported by Dave Lewis. USB mode doesn't work. + +2013-04-02 Stéphane Voltz + * backend/lexmark.c backend/lexmark.h: fix device detection to + handle hotplugging and unplugging of USB devices. USe + sanei_usb_exit(). + +2013-03-29 Stéphane Voltz + * backend/gt68xx.c backend/gt68xx_low.h: fix device detection to + handle hotplugging and unplugging of USB devices. + * frontend/tstbackend.c: a test to loop over snae_get_devices to + check if a backend handle hotplugging correctly + +2013-03-27 Stéphane Voltz + * backend/genesys.c backend/genesys_low.h backend/genesys_gl846.c: + warning fixes, SANE option correctness fixes. + +2013-03-25 Rolf Bensch + * backend/pixma_mp150.c: fix button support for Canon Pixma MG6300. + +2013-03-24 Stéphane Voltz + * sanei/test_wire.c, testsuite/sanei/sanei_*test.c: move test program + to testsuite/sanei. Add unit test programs for sanei_check_*, + sanei_constrain_*, sanei_config_* and sanei_usb_* functions. + +2013-03-24 Stéphane Voltz + * backend/genesys.c: make use of the new sanei_usb_scan_devices function + in sane_get_devices. + +2013-03-24 Stéphane Voltz + * sanei/sanei_usb.c include/sane/sanei_usb.h: + separate device search logic from usb init by creating a + sanei_usb_scan_devices. Add a sanei_usb_exit function to free + allocated resources by sanei_usb_init. + +2013-03-21 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanner Canon Pixma MP230 reported by Petar Dodev. + +2013-03-18 Stéphane Voltz + * backend/hp5590.c backend/nec.c backend/sharp.c backend/stv680: + apply use after free fixes, bugs #314035, #314036, #314037 and + #314038 + * backend/hp4200.c: fix a potential division by O, bug #314042 + All five patches for these bugs were provided by Nickolai Zeldovich + + +2013-03-15 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanner Canon Pixma MG6300 reported by Theo van Rijn. + +2013-02-28 Stéphane Voltz + * configure.in configure: restored HAVE_USBCALLS like initially + committed for OS/2 support + +2013-03-04 Oliver Schwartz + * backend/snapscan-options.c backend/snapscan-scsi.c backend/snapscan.c + backend/snapscan-sources.c backend/snapscan.h + doc/descriptions/snapscan.desc: Added support for Acer Scanwit 2720S + implemented by Andrew Goddbody. + +2013-02-28 Stéphane Voltz + * sanei/sanei_usb.c: only free devanme when reusing a device slot in + device list + +2013-02-28 Rolf Bensch + * README.linux: ease installation procedure. + +2013-02-27 Stéphane Voltz + * doc/descriptions/genesys.desc: update G2410 status to basic + +2013-02-27 Stéphane Voltz + * backend/rts8891.c backend/rts88xx_lib.c backend/lexmark.c + backend/lexmark_low.c backend/rts8891_low.c: cppcheck errors and + warnings fixes + +2013-02-27 Rolf Bensch + * README.linux: fix installation path for libsane.la. + +2013-02-22 Gerhard Jaeger + * tools/sane-find-scanner.c: Fix another bug in the libusb1 + part of function check_libusb_device() that prevents sanner + detection for certain devices. + +2013-02-20 Gerhard Jaeger + * tools/sane-find-scanner.c: Setup libusb1 debugging after + initialization otherwise a segfault appears in triple -v mode + * sanei/sanei_usb.c: Free heap memory, acquired via strdup for + devname, in sanei_usb_close() + * po/de.po: Fixed typo + +2013-02-18 Rolf Bensch + * backend/pixma.[ch], backend/pixma_common.[ch], backend/pixma_imageclass.c, + backend/pixma_mp150.c, backend/pixma_mp7[35]0.c, backend/pixma_mp810.c, + doc/descriptions/pixma.desc, doc/sane-pixma.man, po/de.po: + - add infrared scan support for Canon Canoscan 9000F + - Pixma backend version 0.17.2 + +2013-02-13 Stéphane Voltz + * backend/genesys*.[ch]: cppcheck errors fixes + +2013-02-13 Gerhard Jaeger + * backend/plustek_pp.c: Bumped build number + * backend/plustek-pp*: Fixed kernel module build for recent kernels + Defined internal "ULong" types to be in fact 32 bit wide, + this should fix issues on 64 bit machines. + * doc/plustek/Plustek-PARPORT.changes: Update + +2013-02-13 Gerhard Jaeger + * backend/plustek.c: Bumped build number + * backend/plustek-usbscan.c backend/plustek-usbshading.c: Cleanup + * backend/plustek-usb.h backend/plustek-usbdevs.c backend/plustek-usbhw.c: + Added support for Q-Scan A6 portable scanner + * doc/descriptions/plustek.desc: Added entry for Q-Scan A6 + Q-Scan A6 Patch submitted and tested by Hiroshi Miura. Bug #312073. + * doc/sane-plustek.man doc/plustek/Plustek-USB.changes: Update + +2013-02-11 Rolf Bensch + * backend/pixma_common.c, backend/pixma_imageclass.c, + doc/descriptions/pixma.desc: fixed adf paper empty for Canon i-SENSYS + MF4550d. Bug #313674. + +2013-02-11 Stéphane Voltz + * tools/sane-desc.c: fix minor memleaks and whitespace at end of line. + +2013-02-09 Rolf Bensch + * backend/pixma.c, backend/pixma_mp750.c, backend/pixma_mp810.c, + backend/pixma_sane_options.c: fixed compiler warnings. + * backend/pixma.c, backend/pixma_io_sanei.c, backend/pixma_mp150.c, + backend/pixma_mp7[35]0.c, backend/pixma_mp810.c: fixed cppcheck warnings. + +2013-02-06 Rolf Bensch + * backend/pixma_mp150.c: fixed button support for Canon Pixma MG6200 + by Matthias Thon. + +2013-02-01 Stéphane Voltz + * backend/genesys_low.c backend/genesys_gl843.c + backend/genesys_gl846.c: minor usb firmware setup changes + +2013-01-31 Stéphane Voltz + * backend/genesys.[ch] backend/genesys_devices.c + backend/genesys_gl124.c backend/genesys_low.h: add support for LIDE + 210 fifth button. + +2013-01-29 Stéphane Voltz + * backend/genesys*.[ch] : ASIC init refactor. Groundwork for GL846 + support. + +2013-01-24 Rolf Bensch + * backend/pixma_mp150.c: fixed 1200 dpi scan for Canon Pixma MG2100. + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon Pixma MG2100 support reported by David Durgee. + * backend/pixma_imageclass.c: fixed usb checksums for MF4100. + +2013-01-19 Paul Newall + * backends/kodakaio.c: + Hero 4.1 added. + +2013-01-18 Rolf Bensch + * backend/pixma.c, backend/pixma_mp810.c: fixed button support for Canon + Canoscan CS9000F. + * doc/sane-pixma-man: additional description for button support. + +2013-01-16 Paul Newall + * doc/descriptions/kodakaio.desc: + Desc file updated. + +2013-01-14 Rolf Bensch + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: + - new scanner Canon i-SENSYS MF4550d. Bug #313674. + - new scanner Canon i-SENSYS MF5880dn. Bug #313613. + - new scanner Canon i-SENSYS MF6680dn. Bug #313922. + +2013-01-11 Rolf Bensch + * backend/pixma_mp810.c: + - formatted white space + - Canon Pixma MP970 & MP990: fix for broken post_process_image_data. + * doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon Pixma MG5100 support reported by Patrick Viola. + +2013-01-10 Louis Lagendijk + * Changed the pixma_bjnp.c implementation to use its own debug environment + variable (SANE_DEBUG_BJNP) so debugging for the bjnp protocol and the + backend proper can be controlled independently. + Updated manpage for sane-pixma to document the above changes as well + as the changed scannner buttjn options and the fact the bjnp protocol + has added support for IPv6 + +2013-01-10 Louis Lagendijk + * Added optional support in sanedi.c for systemd socket activation. This + will allow for using backend debugging using SANE_DEBUG_xxx to be used + for saned controlled scanning when using socket activation. When only the + socket is received we use the existing code path. + +2013-01-08 Rolf Bensch + * backend/pixma_mp810.c: fix for broken tpu scan. + +2013-01-03 Paul Newall + * backend/kodakaio.c kodakaio.h: + Detecting end of paper when using adf is now an option. + Alternatively the image is padded with the background colour to make up + the specified image size. + +2012-12-31 Paul Newall + * backend/kodakaio.c kodakaio.h kodakaio.conf kodakaio.conf.in: + better fix for bug where adf could not scan more than 1 page with net connection + end of paper now detected with adf, if it is less than the selected size + ESP 2170 and Hero 9.1 can now do 1200dpi + +2012-12-31 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + New scanner Canon Pixma MG4200 reported by nuxer. + +2012-12-28 Alex Belkin + * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id + for Samsung CLX-3300 Series, reported by Jarkko A-L. + +2012-12-23 Paul Newall + * backend/kodakaio.c: + fix bug where adf could not scan more than 1 page with net connection + +2012-12-13 Rolf Bensch + * README.linux: Installation description moved to top and some editing. + +2012-12-09 Paul Newall + * backend/kodakaio.c: + add adf to ESP2170. Reduce the default adf y length to 11.3 inch + +2012-12-09 Stéphane Voltz + * backend/genesys*.c backend/genesys_low.h: reworked gamma table + handling. Compute gamma table outside send_gamma_table so default + gamma table use device specific gamma values defined in device + description. + +2012-12-07 Rolf Bensch + * backend/pixma.h: Pixma backend version 0.17.1 + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + - Canon Pixma MG3100 support reported by Madis Lõhmus. + - Canon Pixma MG6200 support reported by Matthias Thon. + - Canon Pixma MX890 support reported by Henry Ptasinski. + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: + - Canon imageCLASS MF4430 support reported by Michael Mik. This device is + a MF4410 with ADF. + +2012-12-05 Stéphane Voltz + * backend/genesys.c backend/genesys_gl124.c: add binary data logging + for gl124 based scanners. Issue park command as early as possible to + speed up batch scans + +2012-11-28 Paul Newall + * backend/kodakaio.c backend/kodakaio.h backend/kodakaio.conf.in + backend/Makefile.am backend/Makefile.in docs/descriptions/kodakaio.desc: + Use avahi instead of cups for network autodetection + +2012-11-24 Stéphane Voltz + * backend/rts9918.c backend/rts8891_low.c backend/rts8891_low.h: + fix batch scan by adding asynchronous head parking. Fix 600 and 1200 + dpi scan mode for sensor type 1 + +2012-11-11 Stéphane Voltz + * backend/genesys.c backend/genesys_gl124.c: improve calibration for + gl124 based scanners. Fix head parking issue at 1200 dpi. + +2012-11-02 Stéphane Voltz + * doc/descriptions/unsupported.desc: add USB ID 0x07b3, 0x0802 + +2012-11-02 Stéphane Voltz + * configure configure.in doc/Makefile.am doc/Makefile.in: add optional + doxygen documentation generation for genesys backend. + +2012-10-31 Louis Lagendijk + * backend/scripts/pixma_gen_options.py + Updated formatting of produced files to match pixma.c formatting + without need for manual editing + * pixma.[ch] pixma_mp810.c pixma_mp150.c + Rewrite of button option handling. Button options can now be read + without triggering through the button-update option. Buton-update + options is left for ease of use with xsane + Options are cached so that only when an option is read again all + options are re-read. + +2012-10-29 Alex Belkin + * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id + for Samsung SCX-4833FD, reported by Frank Pennycook; description for + SCX-3405W working in networking mode, reported by Patrick Mackinlay. + +2012-10-24 Stéphane Voltz + * backend/genesys_*.[ch]: Lide 35 improvements, doxygen fixes, + experimental 100 dpi support for Canoscan 4400F and 8400F + +2012-10-24 Mattias Ellert + * configure.in, configure: Unset VERSION during the SCSI header check + (Check fails on MacOS X if VERSION is defined) + +2012-10-22 Mattias Ellert + * po/sv.po: Updated Swedish translation + * backend/pixma_bjnp.c: Fix arguments to IPv6 macros + +2012-10-18 m. allan noah + * backend/canon*: IX-4015 support by Ondrej Zary + +2012-10-17 Alex Belkin + * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id + for Samsung SCX-4100, reported by Antonello Lobianco. + +2012-09-18 Alex Belkin + * backend/xerox_mfp.conf.in doc/descriptions/xerox_mfp.desc: usb id + for Samsung SCX-4729FD, reported by wom balton. + +2012-09-12 Rolf Bensch + * doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon imageCLASS MF5730 support reported by Ondrej Zary. + +2012-09-10 Rolf Bensch + * doc/descriptions/unsupported.desc: Removed Canon Multipass 390 from + unsupported device list. + +2012-09-08 Louis Lagendijk + * backend/pixma_bjnp.c, backend/pixma_bjnp_private.h + bulk reading rewritten and solved the case where the scanner returns + a 0 length payload. + Use MDL string instead of DES as it is mre fool proof when matching + the model string from the backend + +2012-09-06 Stéphane Voltz + * backend/genesys_gl646.c backend/genesys.c: enable hardware lineart + for Strobe XP200 + +2012-09-05 Rolf Bensch + * backend/pixma_imageclass.c, doc/descriptions/pixma.desc, + doc/sane-pixma.man: New scanner reported by Eric Schwartz. Bug #313761. + * backend/pixma_mp150.c: 14" (ADF) / A4 (Flatbed) exception for Pixma MX420 + reported by D.Möller. Same exception also added for Pixma MX410. + +2012-09-04 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + Pixma MG5300 support reported by Gernot Hassenpflug. + +2012-09-03 Rolf Bensch + * README.linux: Installation description updated for sane-backends + 1.0.24git. + * doc/descriptions/pixma.desc, doc/sane-pixma.man: + Canon imageRunner 1020/1024/1025 support reported by Yuri Kirin. + Bug #313203. + * backend/pixma_mp150.c: Use xdpi to check for 14" / A4 scan. + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + Pixma MX370 support reported by Daniel Lehmann. Bug #313750. + * backend/pixma_mp150.c: PIXMA_CAP_EXPERIMENT removed from new scanners. + +2012-08-27 Louis Lagendijk + * pixma_bjnp.c pixma_bjnp_private.h + Added working scan-button support + Added IPv6 support + Some clean up and refactoring + +2012-08-27 Rolf Bensch + * backend/pixma_mp150.c, doc/descriptions/pixma.desc, doc/sane-pixma.man: + Pixma MG6100 support reported by Yann Bonnamy. Bug #313471. + +2012-08-26 m. allan noah + * ChangeLog*, configure*, Makefile.in, doc/desc/{kodakaio,kvs40xx}.desc: + Various updates related to starting 1.0.24git + +Older entries can be found in ChangeLog-1.0.23. diff --git a/README.linux b/README.linux index d650d48..9011b72 100644 --- a/README.linux +++ b/README.linux @@ -86,10 +86,10 @@ Step by step install on Linux 2.6.* and 3.*, both with udev: Register new installed SANE dynamically linked shared object library. $ sudo ldconfig -v | grep libsane - libsane.so.1 -> libsane.so.1.0.24 - libsane.so.1 -> libsane.so.1.0.22 + libsane.so.1 -> libsane.so.1.0.25 + libsane.so.1 -> libsane.so.1.0.23 - This example shows that the system first find version 1.0.24 and then 1.0.22. + This example shows that the system first find version 1.0.25 and then 1.0.23. This is the correct order. If your system first find the old version and then the new installed one, @@ -133,17 +133,17 @@ Step by step install on Linux 2.6.* and 3.*, both with udev: 4.1. Check the used backend version: - The programs must use the installed SANE backend version, e.g. 1.0.24. + The programs must use the installed SANE backend version, e.g. 1.0.25. $ scanimage -V - scanimage (sane-backends) 1.0.24git; backend version 1.0.24 + scanimage (sane-backends) 1.0.25git; backend version 1.0.25 - This example shows that backend and scanimage are version 1.0.24. + This example shows that backend and scanimage are version 1.0.25. $ /usr/bin/scanimage -V - scanimage (sane-backends) 1.0.20; backend version 1.0.24 + scanimage (sane-backends) 1.0.23; backend version 1.0.25 - This example shows that an old scanimage (1.0.20) uses the backend 1.0.24. + This example shows that an old scanimage (1.0.23) uses the backend 1.0.25. If you want to use xsane, start xsane and check the used version with CTRL - i. diff --git a/backend/abaton.c b/backend/abaton.c index 10f5c21..6187166 100644 --- a/backend/abaton.c +++ b/backend/abaton.c @@ -1455,7 +1455,7 @@ sane_cancel (SANE_Handle handle) if (s->AbortedByUser) { DBG (FLOW_CONTROL, "sane_cancel: Scan has not been initiated yet." - "we probably recieved a signal while writing data.\n"); + "we probably received a signal while writing data.\n"); s->AbortedByUser = SANE_FALSE; } else diff --git a/backend/apple.c b/backend/apple.c index c806983..86d5cde 100644 --- a/backend/apple.c +++ b/backend/apple.c @@ -1596,7 +1596,7 @@ init_options (Apple_Scanner * s) s->opt[OPT_WAIT].title = "Wait"; s->opt[OPT_WAIT].desc = "You may issue the scan command but the actual " "scan will not start unless you press the button in the front of the " - "scanner. It is usefull feature when you want to make a network scan (?) " + "scanner. It is a useful feature when you want to make a network scan (?) " "In the mean time you may halt your computer waiting for the SCSI bus " "to be free. If this happens just press the scanner button."; s->opt[OPT_WAIT].type = SANE_TYPE_BOOL; diff --git a/backend/artec.c b/backend/artec.c index 212de34..9adaa39 100644 --- a/backend/artec.c +++ b/backend/artec.c @@ -607,7 +607,7 @@ sense_handler (int fd, u_char * sense, void *arg) return SANE_STATUS_IO_ERROR; } default: - DBG (2, "sense: Unkown Error Code Qualifier (%02x)\n", sense[0]); + DBG (2, "sense: Unknown Error Code Qualifier (%02x)\n", sense[0]); return SANE_STATUS_IO_ERROR; } diff --git a/backend/avision.c b/backend/avision.c index 31b0a58..74ffe80 100644 --- a/backend/avision.c +++ b/backend/avision.c @@ -137,7 +137,7 @@ #include #define BACKEND_NAME avision -#define BACKEND_BUILD 296 /* avision backend BUILD version */ +#define BACKEND_BUILD 297 /* avision backend BUILD version */ #include "../include/sane/sane.h" #include "../include/sane/sanei.h" @@ -620,7 +620,7 @@ static Avision_HWEntry Avision_Device_List [] = { "HP", "ScanJet 5370C", 0x03f0, 0x0701, "Hewlett-Packard", "ScanJet 5370C", - AV_MULTI_CALIB_CMD | AV_INT_STATUS, AV_FIRMWARE }, + AV_MULTI_CALIB_CMD | AV_INT_STATUS, 0 }, /* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */ /* status="good" */ diff --git a/backend/canon_dr-cmd.h b/backend/canon_dr-cmd.h index 64e6887..b969c3b 100644 --- a/backend/canon_dr-cmd.h +++ b/backend/canon_dr-cmd.h @@ -66,6 +66,10 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) } } +/* ==================================================================== */ +/* extended status packet */ +#define get_ES_length(b) getnbyte(b+0x04, 4) + /* ==================================================================== */ /* SCSI commands */ @@ -203,7 +207,9 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) /* READ/SEND page codes */ #define SR_datatype_image 0x00 #define SR_datatype_lut 0x03 +#define SR_datatype_pixelsize 0x80 /*DR-G1130*/ #define SR_datatype_panel 0x84 +#define SR_datatype_sensors 0x8b #define SR_datatype_counters 0x8c #define SR_datatype_endorser 0x90 #define SR_datatype_fineoffset 0x90 @@ -234,6 +240,11 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define get_R_PANEL_enable_led(in) getbitfield(in+2, 1, 0) #define get_R_PANEL_counter(in) getnbyte(in + 0x04, 4) +/*sensors*/ +#define R_SENSORS_len 0x01 +#define get_R_SENSORS_card(in) getbitfield(in, 1, 3) +#define get_R_SENSORS_adf(in) getbitfield(in, 1, 0) + /*counters*/ #define R_COUNTERS_len 0x80 #define get_R_COUNTERS_scans(in) getnbyte(in + 0x04, 4) @@ -334,6 +345,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define set_SSM_BUFF_async(sb, val) setbitfield(sb+0x0a, 1, 6, val) #define set_SSM_BUFF_ald(sb, val) setbitfield(sb+0x0a, 1, 5, val) #define set_SSM_BUFF_fb(sb, val) setbitfield(sb+0x0a, 1, 4, val) +#define set_SSM_BUFF_card(sb, val) setbitfield(sb+0x0a, 1, 3, val) /* for DO (0x36) page */ #define SSM_DO_none 0 @@ -414,19 +426,40 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define set_CC3_exp_b_g(sb, val) putnbyte(sb + 0x1e, val, 2) #define set_CC3_exp_b_b(sb, val) putnbyte(sb + 0x20, val, 2) +/* ==================================================================== */ +/* Page codes used by GET/SET SCAN MODE 2 */ +#define SM2_pc_df 0x00 +#define SM2_pc_ultra 0x01 +#define SM2_pc_buffer 0x02 +#define SM2_pc_dropout 0x06 + /* ==================================================================== */ /* SET SCAN MODE 2 */ #define SET_SCAN_MODE2_code 0xe5 -#define SET_SCAN_MODE2_len 10 +#define SET_SCAN_MODE2_len 12 #define set_SSM2_page_code(sb, val) sb[0x02] = val #define set_SSM2_pay_len(sb, val) sb[0x08] = val /* the payload */ #define SSM2_PAY_len 0x10 -#define set_SSM2_unk(sb, val) sb[0x02] = val -#define set_SSM2_unk2(sb, val) sb[0x03] = val -#define set_SSM2_unk3(sb, val) sb[0x04] = val + +/* for DF (0x00) page */ +#define set_SSM2_DF_thick(sb, val) setbitfield(sb+3, 1, 2, val) +#define set_SSM2_DF_len(sb, val) setbitfield(sb+3, 1, 0, val) + +/* for ULTRA (0x01) page */ +#define set_SSM2_ULTRA_top(sb, val) putnbyte(sb + 0x07, val, 2) +#define set_SSM2_ULTRA_bot(sb, val) putnbyte(sb + 0x09, val, 2) + +/* for BUFFER (0x02) page */ +#define set_SSM2_BUFF_unk(sb, val) sb[0x03] = val +#define set_SSM2_BUFF_unk2(sb, val) sb[0x06] = val +#define set_SSM2_BUFF_sync(sb, val) sb[0x09] = val + +/* for DROPOUT (0x06) page */ +#define set_SSM2_DO_do(sb, val) sb[0x09] = val +#define set_SSM2_DO_en(sb, val) sb[0x0a] = val /* ==================================================================== */ /* window descriptor macros for SET_WINDOW and GET_WINDOW */ diff --git a/backend/canon_dr.c b/backend/canon_dr.c index 594aab2..15dcc59 100644 --- a/backend/canon_dr.c +++ b/backend/canon_dr.c @@ -276,10 +276,39 @@ - DR-2580C pads the backside of duplex scans v40 2012-11-01, MAN - initial DR-9050C, DR-7550C, DR-6050C and DR-3010C support - v41 2013-07-31, MAN + v41 2013-07-31, MAN (SANE 1.0.24) - initial P-208 and P-215 support - bug fix for calibration of scanners with duplex_offset - allow duplex_offset to be controlled from config file + v42 2013-12-09, MAN + - initial DR-G1100 support + - add support for paper sensors (P-215 & P-208) + - add initial support for card reader (P-215) + - removed unused var from do_scsi_cmd() + v43 2014-03-13, MAN + - initial DR-M140 support + - add extra_status config and code + - split status code into do_usb_status + - fix copy_line margin offset + - add new color interlacing modes and code + - comment out ssm2 + - add timestamp to do_usb_cmd + v44 2014-03-26, MAN + - buffermode support for machines with ssm2 command + - DR-M140 needs always_op=0 + v45 2014-03-29, MAN + - dropout support for machines with ssm2 command + - doublefeed support for machines with ssm2 command + v46 2014-04-09, MAN + - split debug level 30 into two levels + - simplify jpeg ifdefs + - add support for DR-M160 + v47 2014-07-07, MAN + - initial DR-G1130 support + v48 2014-08-06, MAN + - set another unknown byte in buffermode for ssm2 + - add another gettimeofday call at end of do_usb_cmd + - don't print 0 length line in hexdump SANE FLOW DIAGRAM @@ -317,6 +346,7 @@ #include /*isspace*/ #include /*tan*/ #include /*usleep*/ +#include /*gettimeofday*/ #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_scsi.h" @@ -328,7 +358,7 @@ #include "canon_dr.h" #define DEBUG 1 -#define BUILD 41 +#define BUILD 48 /* values for SANE_DEBUG_CANON_DR env var: - errors 5 @@ -336,15 +366,25 @@ - function detail 15 - get/setopt cmds 20 - scsi/usb trace 25 - - scsi/usb detail 30 + - scsi/usb writes 30 + - scsi/usb reads 31 - useless noise 35 */ +/* ------------------------------------------------------------------------- */ +/* if JPEG support is not enabled in sane.h, we setup our own defines */ +#ifndef SANE_FRAME_JPEG +#define SANE_FRAME_JPEG 0x0B +#define SANE_JPEG_DISABLED 1 +#endif /* ------------------------------------------------------------------------- */ #define STRING_FLATBED SANE_I18N("Flatbed") #define STRING_ADFFRONT SANE_I18N("ADF Front") #define STRING_ADFBACK SANE_I18N("ADF Back") #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") +#define STRING_CARDFRONT SANE_I18N("Card Front") +#define STRING_CARDBACK SANE_I18N("Card Back") +#define STRING_CARDDUPLEX SANE_I18N("Card Duplex") #define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART #define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE @@ -366,6 +406,8 @@ static int global_buffer_size; static int global_buffer_size_default = 2 * 1024 * 1024; static int global_padded_read; static int global_padded_read_default = 0; +static int global_extra_status; +static int global_extra_status_default = 0; static int global_duplex_offset; static int global_duplex_offset_default = 0; static char global_vendor_name[9]; @@ -543,6 +585,32 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) global_padded_read = buf; } + /* EXTRA STATUS: we clamp to 0 or 1 */ + else if (!strncmp (lp, "extra-status", 12) && isspace (lp[12])) { + + int buf; + lp += 12; + lp = sanei_config_skip_whitespace (lp); + buf = atoi (lp); + + if (buf < 0) { + DBG (5, "sane_get_devices: config option \"extra-status\" " + "(%d) is < 0, ignoring!\n", buf); + continue; + } + + if (buf > 1) { + DBG (5, "sane_get_devices: config option \"extra-status\" " + "(%d) is > 1, ignoring!\n", buf); + continue; + } + + DBG (15, "sane_get_devices: setting \"extra-status\" to %d\n", + buf); + + global_extra_status = buf; + } + /* DUPLEXOFFSET: < 1200 */ else if (!strncmp (lp, "duplex-offset", 13) && isspace (lp[13])) { @@ -733,6 +801,7 @@ attach_one (const char *device_name, int connType) /* config file settings */ s->buffer_size = global_buffer_size; s->padded_read = global_padded_read; + s->extra_status = global_extra_status; s->duplex_offset = global_duplex_offset; /* copy the device name */ @@ -1160,6 +1229,9 @@ init_model (struct scanner *s) s->reverse_by_mode[MODE_GRAYSCALE] = 0; s->reverse_by_mode[MODE_COLOR] = 0; + s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RGB; + s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RGB; + s->always_op = 1; s->has_df = 1; s->has_btc = 1; @@ -1191,9 +1263,7 @@ init_model (struct scanner *s) /* specific settings missing from vpd */ if (strstr (s->model_name,"DR-9080") || strstr (s->model_name,"DR-7580")){ -#ifdef SANE_FRAME_JPEG s->has_comp_JPEG = 1; -#endif s->rgb_format = 2; } @@ -1203,7 +1273,10 @@ init_model (struct scanner *s) else if (strstr (s->model_name,"DR-9050") || strstr (s->model_name,"DR-7550") - || strstr (s->model_name,"DR-6050")){ + || strstr (s->model_name,"DR-6050") + || strstr (s->model_name,"DR-G1100") + || strstr (s->model_name,"DR-G1130") + ){ /*missing*/ s->std_res_x[DPI_100]=1; @@ -1367,6 +1440,7 @@ init_model (struct scanner *s) s->has_ssm_pay_head_len = 1; s->ppl_mod = 8; s->ccal_version = 3; + s->can_read_sensors = 1; } else if (strstr (s->model_name, "P-215")) { @@ -1382,6 +1456,90 @@ init_model (struct scanner *s) s->has_ssm_pay_head_len = 1; s->ppl_mod = 8; s->ccal_version = 3; + s->can_read_sensors = 1; + s->has_card = 1; + } + + else if (strstr (s->model_name,"DR-M160")){ + + /*missing*/ + s->std_res_x[DPI_100]=1; + s->std_res_y[DPI_100]=1; + s->std_res_x[DPI_150]=1; + s->std_res_y[DPI_150]=1; + s->std_res_x[DPI_200]=1; + s->std_res_y[DPI_200]=1; + s->std_res_x[DPI_300]=1; + s->std_res_y[DPI_300]=1; + s->std_res_x[DPI_400]=1; + s->std_res_y[DPI_400]=1; + s->std_res_x[DPI_600]=1; + s->std_res_y[DPI_600]=1; + + s->has_comp_JPEG = 1; + s->rgb_format = 1; + s->can_color = 1; + s->has_df_ultra = 1; + + s->color_inter_by_res[DPI_100] = COLOR_INTERLACE_GBR; + s->color_inter_by_res[DPI_150] = COLOR_INTERLACE_GBR; + s->color_inter_by_res[DPI_200] = COLOR_INTERLACE_BRG; + s->color_inter_by_res[DPI_400] = COLOR_INTERLACE_GBR; + + /*weirdness*/ + s->always_op = 0; + s->fixed_width = 1; + s->invert_tly = 1; + s->can_write_panel = 0; + s->has_ssm = 0; + s->has_ssm2 = 1; + s->duplex_interlace = DUPLEX_INTERLACE_FFBB; + s->duplex_offset_side = SIDE_FRONT; + + /*lies*/ + s->can_halftone=0; + s->can_monochrome=0; + } + + else if (strstr (s->model_name,"DR-M140")){ + + /*missing*/ + s->std_res_x[DPI_100]=1; + s->std_res_y[DPI_100]=1; + s->std_res_x[DPI_150]=1; + s->std_res_y[DPI_150]=1; + s->std_res_x[DPI_200]=1; + s->std_res_y[DPI_200]=1; + s->std_res_x[DPI_300]=1; + s->std_res_y[DPI_300]=1; + s->std_res_x[DPI_400]=1; + s->std_res_y[DPI_400]=1; + s->std_res_x[DPI_600]=1; + s->std_res_y[DPI_600]=1; + + s->has_comp_JPEG = 1; + s->rgb_format = 1; + s->can_color = 1; + s->has_df_ultra = 1; + + s->color_inter_by_res[DPI_100] = COLOR_INTERLACE_GBR; + s->color_inter_by_res[DPI_150] = COLOR_INTERLACE_GBR; + s->color_inter_by_res[DPI_200] = COLOR_INTERLACE_BRG; + s->color_inter_by_res[DPI_400] = COLOR_INTERLACE_GBR; + + /*weirdness*/ + s->always_op = 0; + s->fixed_width = 1; + s->invert_tly = 1; + s->can_write_panel = 0; + s->has_ssm = 0; + s->has_ssm2 = 1; + s->duplex_interlace = DUPLEX_INTERLACE_FFBB; + s->duplex_offset_side = SIDE_BACK; + + /*lies*/ + s->can_halftone=0; + s->can_monochrome=0; } DBG (10, "init_model: finish\n"); @@ -1435,6 +1593,8 @@ init_user (struct scanner *s) s->u.source = SOURCE_FLATBED; else if(s->has_adf) s->u.source = SOURCE_ADF_FRONT; + else if(s->has_card) + s->u.source = SOURCE_CARD_FRONT; /* scan mode */ if(s->can_monochrome) @@ -1628,6 +1788,16 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->source_list[i++]=STRING_ADFDUPLEX; } } + if(s->has_card){ + s->source_list[i++]=STRING_CARDFRONT; + + if(s->has_back){ + s->source_list[i++]=STRING_CARDBACK; + } + if(s->has_duplex){ + s->source_list[i++]=STRING_CARDDUPLEX; + } + } s->source_list[i]=NULL; opt->name = SANE_NAME_SCAN_SOURCE; @@ -1841,7 +2011,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_x_range; - if(s->has_adf){ + if(s->has_adf || s->has_card){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->u.source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; @@ -1868,7 +2038,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_y_range; - if(s->has_adf){ + if(s->has_adf || s->has_card){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->u.source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; @@ -1985,7 +2155,9 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->compress_list[i++]=STRING_NONE; if(s->has_comp_JPEG){ +#ifndef SANE_JPEG_DISABLED s->compress_list[i++]=STRING_JPEG; +#endif } s->compress_list[i]=NULL; @@ -2306,6 +2478,28 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } + if(option==OPT_ADF_LOADED){ + opt->name = "adf-loaded"; + opt->title = "ADF Loaded"; + opt->desc = "Paper available in ADF input hopper"; + opt->type = SANE_TYPE_BOOL; + opt->unit = SANE_UNIT_NONE; + opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if(!s->can_read_sensors) + opt->cap = SANE_CAP_INACTIVE; + } + + if(option==OPT_CARD_LOADED){ + opt->name = "card-loaded"; + opt->title = "Card Loaded"; + opt->desc = "Paper available in card reader"; + opt->type = SANE_TYPE_BOOL; + opt->unit = SANE_UNIT_NONE; + opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if(!s->can_read_sensors || !s->has_card) + opt->cap = SANE_CAP_INACTIVE; + } + return opt; } @@ -2382,6 +2576,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option, else if(s->u.source == SOURCE_ADF_DUPLEX){ strcpy (val, STRING_ADFDUPLEX); } + else if(s->u.source == SOURCE_CARD_FRONT){ + strcpy (val, STRING_CARDFRONT); + } + else if(s->u.source == SOURCE_CARD_BACK){ + strcpy (val, STRING_CARDBACK); + } + else if(s->u.source == SOURCE_CARD_DUPLEX){ + strcpy (val, STRING_CARDDUPLEX); + } return SANE_STATUS_GOOD; case OPT_MODE: @@ -2581,6 +2784,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option, *val_p = s->panel_counter; return ret; + case OPT_ADF_LOADED: + ret = read_sensors(s,OPT_ADF_LOADED); + *val_p = s->sensor_adf_loaded; + return ret; + + case OPT_CARD_LOADED: + ret = read_sensors(s,OPT_CARD_LOADED); + *val_p = s->sensor_card_loaded; + return ret; } } else if (action == SANE_ACTION_SET_VALUE) { @@ -2629,6 +2841,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option, else if (!strcmp (val, STRING_ADFDUPLEX)) { tmp = SOURCE_ADF_DUPLEX; } + else if (!strcmp (val, STRING_CARDFRONT)) { + tmp = SOURCE_CARD_FRONT; + } + else if (!strcmp (val, STRING_CARDBACK)) { + tmp = SOURCE_CARD_BACK; + } + else if (!strcmp (val, STRING_CARDDUPLEX)) { + tmp = SOURCE_CARD_DUPLEX; + } else{ tmp = SOURCE_FLATBED; } @@ -2837,54 +3058,85 @@ ssm_buffer (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; - unsigned char cmd[SET_SCAN_MODE_len]; - size_t cmdLen = SET_SCAN_MODE_len; - - unsigned char out[SSM_PAY_len]; - size_t outLen = SSM_PAY_len; - DBG (10, "ssm_buffer: start\n"); - if(!s->has_ssm){ - DBG (10, "ssm_buffer: unsupported\n"); - return ret; + if(s->has_ssm){ + + unsigned char cmd[SET_SCAN_MODE_len]; + size_t cmdLen = SET_SCAN_MODE_len; + + unsigned char out[SSM_PAY_len]; + size_t outLen = SSM_PAY_len; + + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SET_SCAN_MODE_code); + set_SSM_pf(cmd, 1); + set_SSM_pay_len(cmd, outLen); + + memset(out,0,outLen); + if(s->has_ssm_pay_head_len){ + set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); + } + set_SSM_page_code(out, SM_pc_buffer); + set_SSM_page_len(out, SSM_PAGE_len); + + if(s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX){ + set_SSM_BUFF_duplex(out, 1); + } + if(s->s.source == SOURCE_FLATBED){ + set_SSM_BUFF_fb(out, 1); + } + else if(s->s.source >= SOURCE_CARD_FRONT){ + set_SSM_BUFF_card(out, 1); + } + if(s->buffermode){ + set_SSM_BUFF_async(out, 1); + } + if(0){ + set_SSM_BUFF_ald(out, 1); + } + if(0){ + set_SSM_BUFF_unk(out,1); + } + + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); } - memset(cmd,0,cmdLen); - set_SCSI_opcode(cmd, SET_SCAN_MODE_code); - set_SSM_pf(cmd, 1); - set_SSM_pay_len(cmd, outLen); + else if(s->has_ssm2){ - memset(out,0,outLen); - if(s->has_ssm_pay_head_len){ - set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); + unsigned char cmd[SET_SCAN_MODE2_len]; + size_t cmdLen = SET_SCAN_MODE2_len; + + unsigned char out[SSM2_PAY_len]; + size_t outLen = SSM2_PAY_len; + + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); + set_SSM2_page_code(cmd, SM2_pc_buffer); + set_SSM2_pay_len(cmd, outLen); + + memset(out,0,outLen); + set_SSM2_BUFF_unk(out, !s->buffermode); + set_SSM2_BUFF_unk2(out, 0x40); + set_SSM2_BUFF_sync(out, !s->buffermode); + + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); } - set_SSM_page_code(out, SM_pc_buffer); - set_SSM_page_len(out, SSM_PAGE_len); - if(s->s.source == SOURCE_ADF_DUPLEX){ - set_SSM_BUFF_duplex(out, 1); - } - else if(s->s.source == SOURCE_FLATBED){ - set_SSM_BUFF_fb(out, 1); - } - if(s->buffermode){ - set_SSM_BUFF_async(out, 1); - } - if(0){ - set_SSM_BUFF_ald(out, 1); - } - if(0){ - set_SSM_BUFF_unk(out,1); + else{ + DBG (10, "ssm_buffer: unsupported\n"); } - ret = do_cmd ( - s, 1, 0, - cmd, cmdLen, - out, outLen, - NULL, NULL - ); - DBG (10, "ssm_buffer: finish\n"); return ret; @@ -2895,57 +3147,118 @@ ssm_df (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; - unsigned char cmd[SET_SCAN_MODE_len]; - size_t cmdLen = SET_SCAN_MODE_len; - - unsigned char out[SSM_PAY_len]; - size_t outLen = SSM_PAY_len; - DBG (10, "ssm_df: start\n"); - - if(!s->has_ssm || !s->has_df){ + + if(!s->has_df){ DBG (10, "ssm_df: unsupported, finishing\n"); return ret; } + + if(s->has_ssm){ - memset(cmd,0,cmdLen); - set_SCSI_opcode(cmd, SET_SCAN_MODE_code); - set_SSM_pf(cmd, 1); - set_SSM_pay_len(cmd, outLen); + unsigned char cmd[SET_SCAN_MODE_len]; + size_t cmdLen = SET_SCAN_MODE_len; + + unsigned char out[SSM_PAY_len]; + size_t outLen = SSM_PAY_len; + + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SET_SCAN_MODE_code); + set_SSM_pf(cmd, 1); + set_SSM_pay_len(cmd, outLen); + + memset(out,0,outLen); + if(s->has_ssm_pay_head_len){ + set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); + } + set_SSM_page_code(out, SM_pc_df); + set_SSM_page_len(out, SSM_PAGE_len); + + /* deskew by roller */ + if(s->rollerdeskew){ + set_SSM_DF_deskew_roll(out, 1); + } + + /* staple detection */ + if(s->stapledetect){ + set_SSM_DF_staple(out, 1); + } + + /* thickness */ + if(s->df_thickness){ + set_SSM_DF_thick(out, 1); + } + + /* length */ + if(s->df_length){ + set_SSM_DF_len(out, 1); + } + + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); - memset(out,0,outLen); - if(s->has_ssm_pay_head_len){ - set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); } - set_SSM_page_code(out, SM_pc_df); - set_SSM_page_len(out, SSM_PAGE_len); - /* deskew by roller */ - if(s->rollerdeskew){ - set_SSM_DF_deskew_roll(out, 1); - } + else if(s->has_ssm2){ + + unsigned char cmd[SET_SCAN_MODE2_len]; + size_t cmdLen = SET_SCAN_MODE2_len; - /* staple detection */ - if(s->stapledetect){ - set_SSM_DF_staple(out, 1); - } + unsigned char out[SSM2_PAY_len]; + size_t outLen = SSM2_PAY_len; + + /* send ultrasonic offsets first */ + if(s->df_thickness && s->has_df_ultra){ + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); + set_SSM2_page_code(cmd, SM2_pc_ultra); + set_SSM2_pay_len(cmd, outLen); + + memset(out,0,outLen); + set_SSM2_ULTRA_top(out, 0); + set_SSM2_ULTRA_bot(out, 0); + + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); + } - /* thickness */ - if(s->df_thickness){ - set_SSM_DF_thick(out, 1); - } + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); + set_SSM2_page_code(cmd, SM2_pc_df); + set_SSM2_pay_len(cmd, outLen); + + memset(out,0,outLen); + + /* thickness */ + if(s->df_thickness){ + set_SSM2_DF_thick(out, 1); + } + + /* length */ + if(s->df_length){ + set_SSM2_DF_len(out, 1); + } - /* length */ - if(s->df_length){ - set_SSM_DF_len(out, 1); + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); + } - ret = do_cmd ( - s, 1, 0, - cmd, cmdLen, - out, outLen, - NULL, NULL - ); + else{ + DBG (10, "ssm_df: unsupported\n"); + } DBG (10, "ssm_df: finish\n"); @@ -2957,140 +3270,203 @@ ssm_do (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; - unsigned char cmd[SET_SCAN_MODE_len]; - size_t cmdLen = SET_SCAN_MODE_len; + DBG (10, "ssm_do: start\n"); - unsigned char out[SSM_PAY_len]; - size_t outLen = SSM_PAY_len; + if(!s->can_color){ + DBG (10, "ssm_do: unsupported, finishing\n"); + return ret; + } + + if(s->has_ssm){ - DBG (10, "ssm_do: start\n"); + unsigned char cmd[SET_SCAN_MODE_len]; + size_t cmdLen = SET_SCAN_MODE_len; + + unsigned char out[SSM_PAY_len]; + size_t outLen = SSM_PAY_len; + + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SET_SCAN_MODE_code); + set_SSM_pf(cmd, 1); + set_SSM_pay_len(cmd, outLen); + + memset(out,0,outLen); + if(s->has_ssm_pay_head_len){ + set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); + } + set_SSM_page_code(out, SM_pc_dropout); + set_SSM_page_len(out, SSM_PAGE_len); + + set_SSM_DO_unk1(out, 0x03); + + switch(s->dropout_color_f){ + case COLOR_RED: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_f_do(out,SSM_DO_red); + break; + case COLOR_GREEN: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_f_do(out,SSM_DO_green); + break; + case COLOR_BLUE: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_f_do(out,SSM_DO_blue); + break; + case COLOR_EN_RED: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_f_en(out,SSM_DO_red); + break; + case COLOR_EN_GREEN: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_f_en(out,SSM_DO_green); + break; + case COLOR_EN_BLUE: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_f_en(out,SSM_DO_blue); + break; + } + + switch(s->dropout_color_b){ + case COLOR_RED: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_b_do(out,SSM_DO_red); + break; + case COLOR_GREEN: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_b_do(out,SSM_DO_green); + break; + case COLOR_BLUE: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_b_do(out,SSM_DO_blue); + break; + case COLOR_EN_RED: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_b_en(out,SSM_DO_red); + break; + case COLOR_EN_GREEN: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_b_en(out,SSM_DO_green); + break; + case COLOR_EN_BLUE: + set_SSM_DO_unk2(out, 0x05); + set_SSM_DO_b_en(out,SSM_DO_blue); + break; + } + + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); - if(!s->has_ssm || !s->can_color){ - DBG (10, "ssm_do: unsupported, finishing\n"); - return ret; } - memset(cmd,0,cmdLen); - set_SCSI_opcode(cmd, SET_SCAN_MODE_code); - set_SSM_pf(cmd, 1); - set_SSM_pay_len(cmd, outLen); - - memset(out,0,outLen); - if(s->has_ssm_pay_head_len){ - set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); - } - set_SSM_page_code(out, SM_pc_dropout); - set_SSM_page_len(out, SSM_PAGE_len); + else if(s->has_ssm2){ - set_SSM_DO_unk1(out, 0x03); + unsigned char cmd[SET_SCAN_MODE2_len]; + size_t cmdLen = SET_SCAN_MODE2_len; + + unsigned char out[SSM2_PAY_len]; + size_t outLen = SSM2_PAY_len; + + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); + set_SSM2_page_code(cmd, SM2_pc_dropout); + set_SSM2_pay_len(cmd, outLen); + + memset(out,0,outLen); + + switch(s->dropout_color_f){ + case COLOR_RED: + set_SSM2_DO_do(out,SSM_DO_red); + break; + case COLOR_GREEN: + set_SSM2_DO_do(out,SSM_DO_green); + break; + case COLOR_BLUE: + set_SSM2_DO_do(out,SSM_DO_blue); + break; + case COLOR_EN_RED: + set_SSM2_DO_en(out,SSM_DO_red); + break; + case COLOR_EN_GREEN: + set_SSM2_DO_en(out,SSM_DO_green); + break; + case COLOR_EN_BLUE: + set_SSM2_DO_en(out,SSM_DO_blue); + break; + } - switch(s->dropout_color_f){ - case COLOR_RED: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_f_do(out,SSM_DO_red); - break; - case COLOR_GREEN: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_f_do(out,SSM_DO_green); - break; - case COLOR_BLUE: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_f_do(out,SSM_DO_blue); - break; - case COLOR_EN_RED: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_f_en(out,SSM_DO_red); - break; - case COLOR_EN_GREEN: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_f_en(out,SSM_DO_green); - break; - case COLOR_EN_BLUE: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_f_en(out,SSM_DO_blue); - break; + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); } - switch(s->dropout_color_b){ - case COLOR_RED: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_b_do(out,SSM_DO_red); - break; - case COLOR_GREEN: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_b_do(out,SSM_DO_green); - break; - case COLOR_BLUE: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_b_do(out,SSM_DO_blue); - break; - case COLOR_EN_RED: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_b_en(out,SSM_DO_red); - break; - case COLOR_EN_GREEN: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_b_en(out,SSM_DO_green); - break; - case COLOR_EN_BLUE: - set_SSM_DO_unk2(out, 0x05); - set_SSM_DO_b_en(out,SSM_DO_blue); - break; + else{ + DBG (10, "ssm_do: unsupported\n"); } - ret = do_cmd ( - s, 1, 0, - cmd, cmdLen, - out, outLen, - NULL, NULL - ); - DBG (10, "ssm_do: finish\n"); return ret; } -/* used by recent scanners. meaning of payloads unknown */ static SANE_Status -ssm2 (struct scanner *s) +read_sensors(struct scanner *s,SANE_Int option) { - SANE_Status ret = SANE_STATUS_GOOD; - - unsigned char cmd[SET_SCAN_MODE2_len]; - size_t cmdLen = SET_SCAN_MODE2_len; + SANE_Status ret=SANE_STATUS_GOOD; - unsigned char out[SSM2_PAY_len]; - size_t outLen = SSM2_PAY_len; + unsigned char cmd[READ_len]; + size_t cmdLen = READ_len; - DBG (10, "ssm2:start\n"); + unsigned char in[R_SENSORS_len]; + size_t inLen = R_SENSORS_len; - if(!s->has_ssm2){ - DBG (10, "ssm2: unsupported, finishing\n"); + DBG (10, "read_sensors: start %d\n", option); + + if(!s->can_read_sensors){ + DBG (10, "read_sensors: unsupported, finishing\n"); return ret; } - memset(cmd,0,cmdLen); - set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); - /*FIXME: set this correctly */ - set_SSM2_page_code(cmd, 0); - set_SSM2_pay_len(cmd, outLen); + /* only run this if frontend has already read the last time we got it */ + /* or if we don't care for such bookkeeping (private use) */ + if (!option || !s->sensors_read[option-OPT_ADF_LOADED]) { - /*FIXME: set these correctly */ - memset(out,0,outLen); - set_SSM2_unk(out, 0); - set_SSM2_unk2(out, 0); - set_SSM2_unk3(out, 0); + DBG (15, "read_sensors: running\n"); - /* - ret = do_cmd ( + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, READ_code); + set_R_datatype_code (cmd, SR_datatype_sensors); + set_R_xfer_length (cmd, inLen); + + ret = do_cmd ( s, 1, 0, cmd, cmdLen, - out, outLen, - NULL, NULL - );*/ + NULL, 0, + in, &inLen + ); + + if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { + /*set flags indicating there is data to read*/ + memset(s->sensors_read,1,sizeof(s->sensors_read)); - DBG (10, "ssm2: finish\n"); + s->sensor_adf_loaded = get_R_SENSORS_adf(in); + s->sensor_card_loaded = get_R_SENSORS_card(in); + ret = SANE_STATUS_GOOD; + } + } + + if(option) + s->sensors_read[option-OPT_ADF_LOADED] = 0; + + DBG (10, "read_sensors: finish\n"); + return ret; } @@ -3112,9 +3488,9 @@ read_panel(struct scanner *s,SANE_Int option) return ret; } - /* only run this if frontend has read previous value - * or if the caller does not want the data stored */ - if (!option || !s->hw_read[option-OPT_START]) { + /* only run this if frontend has already read the last time we got it */ + /* or if we don't care for such bookkeeping (private use) */ + if (!option || !s->panel_read[option-OPT_START]) { DBG (15, "read_panel: running\n"); @@ -3132,8 +3508,7 @@ read_panel(struct scanner *s,SANE_Int option) if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { /*set flags indicating there is data to read*/ - if(option) - memset(s->hw_read,1,sizeof(s->hw_read)); + memset(s->panel_read,1,sizeof(s->panel_read)); s->panel_start = get_R_PANEL_start(in); s->panel_stop = get_R_PANEL_stop(in); @@ -3143,12 +3518,13 @@ read_panel(struct scanner *s,SANE_Int option) s->panel_bypass_mode = get_R_PANEL_bypass_mode(in); s->panel_enable_led = get_R_PANEL_enable_led(in); s->panel_counter = get_R_PANEL_counter(in); + ret = SANE_STATUS_GOOD; } } if(option) - s->hw_read[option-OPT_START] = 0; + s->panel_read[option-OPT_START] = 0; DBG (10, "read_panel: finish %d\n",s->panel_counter); @@ -3294,14 +3670,12 @@ update_params(struct scanner *s, int calib) /* round down to pixel boundary for some scanners */ s->u.width -= s->u.width % s->ppl_mod; -#ifdef SANE_FRAME_JPEG /* jpeg requires 8x8 squares */ if(s->compress == COMP_JPEG && s->u.mode >= MODE_GRAYSCALE){ s->u.format = SANE_FRAME_JPEG; s->u.width -= s->u.width % 8; s->u.height -= s->u.height % 8; } -#endif s->u.Bpl = s->u.width * s->u.bpp / 8; s->u.valid_Bpl = s->u.Bpl; @@ -3396,7 +3770,8 @@ update_params(struct scanner *s, int calib) } /* some scanners need longer scans because front/back is offset */ - if(s->u.source == SOURCE_ADF_DUPLEX && s->duplex_offset && !calib) + if((s->u.source == SOURCE_ADF_DUPLEX || s->u.source == SOURCE_CARD_DUPLEX) + && s->duplex_offset && !calib) s->s.height = (s->u.br_y-s->u.tl_y+s->duplex_offset) * s->u.dpi_y / 1200; /* round lines up to even number */ @@ -3421,7 +3796,7 @@ update_params(struct scanner *s, int calib) else{ memcpy(&s->i,&s->u,sizeof(struct img_params)); /*dumb scanners pad the top of front page in duplex*/ - if(s->i.source == SOURCE_ADF_DUPLEX) + if(s->i.source == SOURCE_ADF_DUPLEX || s->i.source == SOURCE_CARD_DUPLEX) s->i.skip_lines[s->duplex_offset_side] = s->duplex_offset * s->i.dpi_y / 1200; } @@ -3485,7 +3860,7 @@ sane_start (SANE_Handle handle) if(!s->started){ /* load side marker */ - if(s->u.source == SOURCE_ADF_BACK){ + if(s->u.source == SOURCE_ADF_BACK || s->u.source == SOURCE_CARD_BACK){ s->side = SIDE_BACK; } else{ @@ -3549,7 +3924,7 @@ sane_start (SANE_Handle handle) goto errors; } - /* buffer/duplex/ald command */ + /* buffer/duplex/ald/fb/card command */ ret = ssm_buffer(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot ssm buffer\n"); @@ -3591,18 +3966,21 @@ sane_start (SANE_Handle handle) goto errors; } - /* grab next page */ - ret = object_position (s, SANE_TRUE); - if (ret != SANE_STATUS_GOOD) { - DBG (5, "sane_start: ERROR: cannot load page\n"); - goto errors; - } - - /* wait for scanner to finish load */ - ret = wait_scanner (s); - if (ret != SANE_STATUS_GOOD) { - DBG (5, "sane_start: ERROR: cannot wait scanner\n"); - goto errors; + /* card reader dislikes op? */ + if(s->s.source < SOURCE_CARD_FRONT){ + /* grab next page */ + ret = object_position (s, SANE_TRUE); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "sane_start: ERROR: cannot load page\n"); + goto errors; + } + + /* wait for scanner to finish load */ + ret = wait_scanner (s); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "sane_start: ERROR: cannot wait scanner\n"); + goto errors; + } } /* start scanning */ @@ -3619,7 +3997,7 @@ sane_start (SANE_Handle handle) else{ /* duplex needs to switch sides */ - if(s->s.source == SOURCE_ADF_DUPLEX){ + if(s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX){ s->side = !s->side; } @@ -3635,7 +4013,7 @@ sane_start (SANE_Handle handle) /* otherwise buffered back page will be lost */ /* ingest paper with adf (no-op for fb) */ /* dont call object pos or scan on back side of duplex scan */ - if(s->side == SIDE_FRONT || s->s.source == SOURCE_ADF_BACK){ + if(s->side == SIDE_FRONT || s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_BACK){ /* clean scan params for new scan */ ret = clean_params(s); @@ -3694,9 +4072,7 @@ sane_start (SANE_Handle handle) * API has no way to inform the frontend of this, * so we block and buffer. yuck */ if( (s->swdeskew || s->swdespeck || s->swcrop) -#ifdef SANE_FRAME_JPEG && s->s.format != SANE_FRAME_JPEG -#endif ){ /* get image */ @@ -3772,23 +4148,26 @@ clean_params (struct scanner *s) s->s.bytes_tot[1]=0; /* store the number of front bytes */ - if ( s->u.source != SOURCE_ADF_BACK ) + if ( s->u.source != SOURCE_ADF_BACK && s->u.source != SOURCE_CARD_BACK ) s->u.bytes_tot[SIDE_FRONT] = s->u.Bpl * s->u.height; - if ( s->i.source != SOURCE_ADF_BACK ) + if ( s->i.source != SOURCE_ADF_BACK && s->i.source != SOURCE_CARD_BACK ) s->i.bytes_tot[SIDE_FRONT] = s->i.Bpl * s->i.height; - if ( s->s.source != SOURCE_ADF_BACK ) + if ( s->s.source != SOURCE_ADF_BACK && s->s.source != SOURCE_CARD_BACK ) s->s.bytes_tot[SIDE_FRONT] = s->s.Bpl * s->s.height; /* store the number of back bytes */ - if ( s->u.source == SOURCE_ADF_DUPLEX || s->u.source == SOURCE_ADF_BACK ) + if ( s->u.source == SOURCE_ADF_DUPLEX || s->u.source == SOURCE_ADF_BACK + || s->u.source == SOURCE_CARD_DUPLEX || s->u.source == SOURCE_CARD_BACK ) s->u.bytes_tot[SIDE_BACK] = s->u.Bpl * s->u.height; - if ( s->i.source == SOURCE_ADF_DUPLEX || s->i.source == SOURCE_ADF_BACK ) + if ( s->i.source == SOURCE_ADF_DUPLEX || s->i.source == SOURCE_ADF_BACK + || s->i.source == SOURCE_CARD_DUPLEX || s->i.source == SOURCE_CARD_BACK ) s->i.bytes_tot[SIDE_BACK] = s->i.Bpl * s->i.height; - if ( s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_ADF_BACK ) + if ( s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_ADF_BACK + || s->s.source == SOURCE_CARD_DUPLEX || s->s.source == SOURCE_CARD_BACK ) s->s.bytes_tot[SIDE_BACK] = s->s.Bpl * s->s.height; DBG (10, "clean_params: finish\n"); @@ -3863,7 +4242,7 @@ set_window (struct scanner *s) set_WPDB_wdblen(header, SW_desc_len); /* init the window block */ - if (s->s.source == SOURCE_ADF_BACK) { + if (s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_BACK) { set_WD_wid (desc1, WD_wid_back); } else{ @@ -3933,13 +4312,11 @@ set_window (struct scanner *s) set_WD_compress_type(desc1, COMP_NONE); set_WD_compress_arg(desc1, 0); -#ifdef SANE_FRAME_JPEG /* some scanners support jpeg image compression, for color/gs only */ if(s->s.format == SANE_FRAME_JPEG){ set_WD_compress_type(desc1, COMP_JPEG); set_WD_compress_arg(desc1, s->compress_arg); } -#endif /*build the command*/ memset(cmd,0,cmdLen); @@ -3953,7 +4330,7 @@ set_window (struct scanner *s) NULL, NULL ); - if (!ret && s->s.source == SOURCE_ADF_DUPLEX) { + if (!ret && (s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX)) { set_WD_wid (desc1, WD_wid_back); ret = do_cmd ( s, 1, 0, @@ -4037,9 +4414,9 @@ start_scan (struct scanner *s, int type) out[1] = type; } - if (s->s.source != SOURCE_ADF_DUPLEX) { + if (s->s.source != SOURCE_ADF_DUPLEX && s->s.source != SOURCE_CARD_DUPLEX) { outLen--; - if(s->s.source == SOURCE_ADF_BACK) { + if(s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_BACK) { out[0] = WD_wid_back; } } @@ -4100,7 +4477,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len s->reading = 1; /* double width pnm interlacing */ - if(s->s.source == SOURCE_ADF_DUPLEX + if((s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX) && s->s.format <= SANE_FRAME_RGB && s->duplex_interlace != DUPLEX_INTERLACE_NONE ){ @@ -4225,7 +4602,6 @@ read_from_scanner(struct scanner *s, int side, int exact) inLen = 0; } -#ifdef SANE_FRAME_JPEG /* this is jpeg data, we need to fix the missing image size */ if(s->s.format == SANE_FRAME_JPEG){ @@ -4275,7 +4651,6 @@ read_from_scanner(struct scanner *s, int side, int exact) } } } -#endif /*scanner may have sent more data than we asked for, chop it*/ if(inLen > remain){ @@ -4301,37 +4676,32 @@ read_from_scanner(struct scanner *s, int side, int exact) if(ret == SANE_STATUS_EOF){ - switch (s->s.format){ + /* this is jpeg data, we need to change the total size */ + if(s->s.format == SANE_FRAME_JPEG){ + s->s.bytes_tot[side] = s->s.bytes_sent[side]; + s->i.bytes_tot[side] = s->i.bytes_sent[side]; + s->u.bytes_tot[side] = s->i.bytes_sent[side]; + } -#ifdef SANE_FRAME_JPEG - /* this is jpeg data, we need to change the total size */ - case SANE_FRAME_JPEG: - s->s.bytes_tot[side] = s->s.bytes_sent[side]; - s->i.bytes_tot[side] = s->i.bytes_sent[side]; - s->u.bytes_tot[side] = s->i.bytes_sent[side]; - break; -#endif - - /* this is non-jpeg data, fill remainder, change rx'd size */ - default: + /* this is non-jpeg data, fill remainder, change rx'd size */ + else{ - DBG (15, "read_from_scanner: eof: %d %d\n", s->i.bytes_tot[side], s->i.bytes_sent[side]); + DBG (15, "read_from_scanner: eof: %d %d\n", s->i.bytes_tot[side], s->i.bytes_sent[side]); - /* clone the last line repeatedly until the end */ - while(s->i.bytes_tot[side] > s->i.bytes_sent[side]){ - memcpy( - s->buffers[side]+s->i.bytes_sent[side]-s->i.Bpl, - s->buffers[side]+s->i.bytes_sent[side], - s->i.Bpl - ); - s->i.bytes_sent[side] += s->i.Bpl; - } + /* clone the last line repeatedly until the end */ + while(s->i.bytes_tot[side] > s->i.bytes_sent[side]){ + memcpy( + s->buffers[side]+s->i.bytes_sent[side]-s->i.Bpl, + s->buffers[side]+s->i.bytes_sent[side], + s->i.Bpl + ); + s->i.bytes_sent[side] += s->i.Bpl; + } - DBG (15, "read_from_scanner: eof2: %d %d\n", s->i.bytes_tot[side], s->i.bytes_sent[side]); + DBG (15, "read_from_scanner: eof2: %d %d\n", s->i.bytes_tot[side], s->i.bytes_sent[side]); - /* pretend we got all the data from scanner */ - s->s.bytes_sent[side] = s->s.bytes_tot[side]; - break; + /* pretend we got all the data from scanner */ + s->s.bytes_sent[side] = s->s.bytes_tot[side]; } s->i.eof[side] = 1; @@ -4441,57 +4811,52 @@ read_from_scanner_duplex(struct scanner *s,int exact) if(ret == SANE_STATUS_EOF){ - switch (s->s.format){ - -#ifdef SANE_FRAME_JPEG - /* this is jpeg data, we need to change the total size */ - case SANE_FRAME_JPEG: - s->s.bytes_tot[SIDE_FRONT] = s->s.bytes_sent[SIDE_FRONT]; - s->s.bytes_tot[SIDE_BACK] = s->s.bytes_sent[SIDE_BACK]; - s->i.bytes_tot[SIDE_FRONT] = s->i.bytes_sent[SIDE_FRONT]; - s->i.bytes_tot[SIDE_BACK] = s->i.bytes_sent[SIDE_BACK]; - s->u.bytes_tot[SIDE_FRONT] = s->i.bytes_sent[SIDE_FRONT]; - s->u.bytes_tot[SIDE_BACK] = s->i.bytes_sent[SIDE_BACK]; - break; -#endif - - /* this is non-jpeg data, fill remainder, change rx'd size */ - default: + /* this is jpeg data, we need to change the total size */ + if(s->s.format == SANE_FRAME_JPEG){ + s->s.bytes_tot[SIDE_FRONT] = s->s.bytes_sent[SIDE_FRONT]; + s->s.bytes_tot[SIDE_BACK] = s->s.bytes_sent[SIDE_BACK]; + s->i.bytes_tot[SIDE_FRONT] = s->i.bytes_sent[SIDE_FRONT]; + s->i.bytes_tot[SIDE_BACK] = s->i.bytes_sent[SIDE_BACK]; + s->u.bytes_tot[SIDE_FRONT] = s->i.bytes_sent[SIDE_FRONT]; + s->u.bytes_tot[SIDE_BACK] = s->i.bytes_sent[SIDE_BACK]; + } - DBG (15, "read_from_scanner_duplex: eof: %d %d %d %d\n", - s->i.bytes_tot[SIDE_FRONT], s->i.bytes_sent[SIDE_FRONT], - s->i.bytes_tot[SIDE_BACK], s->i.bytes_sent[SIDE_BACK] - ); + /* this is non-jpeg data, fill remainder, change rx'd size */ + else{ - /* clone the last line repeatedly until the end */ - while(s->i.bytes_tot[SIDE_FRONT] > s->i.bytes_sent[SIDE_FRONT]){ - memcpy( - s->buffers[SIDE_FRONT]+s->i.bytes_sent[SIDE_FRONT]-s->i.Bpl, - s->buffers[SIDE_FRONT]+s->i.bytes_sent[SIDE_FRONT], - s->i.Bpl - ); - s->i.bytes_sent[SIDE_FRONT] += s->i.Bpl; - } + DBG (15, "read_from_scanner_duplex: eof: %d %d %d %d\n", + s->i.bytes_tot[SIDE_FRONT], s->i.bytes_sent[SIDE_FRONT], + s->i.bytes_tot[SIDE_BACK], s->i.bytes_sent[SIDE_BACK] + ); - /* clone the last line repeatedly until the end */ - while(s->i.bytes_tot[SIDE_BACK] > s->i.bytes_sent[SIDE_BACK]){ - memcpy( - s->buffers[SIDE_BACK]+s->i.bytes_sent[SIDE_BACK]-s->i.Bpl, - s->buffers[SIDE_BACK]+s->i.bytes_sent[SIDE_BACK], - s->i.Bpl - ); - s->i.bytes_sent[SIDE_BACK] += s->i.Bpl; - } + /* clone the last line repeatedly until the end */ + while(s->i.bytes_tot[SIDE_FRONT] > s->i.bytes_sent[SIDE_FRONT]){ + memcpy( + s->buffers[SIDE_FRONT]+s->i.bytes_sent[SIDE_FRONT]-s->i.Bpl, + s->buffers[SIDE_FRONT]+s->i.bytes_sent[SIDE_FRONT], + s->i.Bpl + ); + s->i.bytes_sent[SIDE_FRONT] += s->i.Bpl; + } - DBG (15, "read_from_scanner_duplex: eof2: %d %d %d %d\n", - s->i.bytes_tot[SIDE_FRONT], s->i.bytes_sent[SIDE_FRONT], - s->i.bytes_tot[SIDE_BACK], s->i.bytes_sent[SIDE_BACK] + /* clone the last line repeatedly until the end */ + while(s->i.bytes_tot[SIDE_BACK] > s->i.bytes_sent[SIDE_BACK]){ + memcpy( + s->buffers[SIDE_BACK]+s->i.bytes_sent[SIDE_BACK]-s->i.Bpl, + s->buffers[SIDE_BACK]+s->i.bytes_sent[SIDE_BACK], + s->i.Bpl ); + s->i.bytes_sent[SIDE_BACK] += s->i.Bpl; + } - /* pretend we got all the data from scanner */ - s->s.bytes_sent[SIDE_FRONT] = s->s.bytes_tot[SIDE_FRONT]; - s->s.bytes_sent[SIDE_BACK] = s->s.bytes_tot[SIDE_BACK]; - break; + DBG (15, "read_from_scanner_duplex: eof2: %d %d %d %d\n", + s->i.bytes_tot[SIDE_FRONT], s->i.bytes_sent[SIDE_FRONT], + s->i.bytes_tot[SIDE_BACK], s->i.bytes_sent[SIDE_BACK] + ); + + /* pretend we got all the data from scanner */ + s->s.bytes_sent[SIDE_FRONT] = s->s.bytes_tot[SIDE_FRONT]; + s->s.bytes_sent[SIDE_BACK] = s->s.bytes_tot[SIDE_BACK]; } s->i.eof[SIDE_FRONT] = 1; @@ -4522,6 +4887,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) unsigned char * line = NULL; int line_next = 0; + int inter = get_color_inter(s,side,s->s.dpi_x); /* jpeg data should not pass thru this function, so copy and bail out */ if(s->s.format > SANE_FRAME_RGB){ @@ -4592,7 +4958,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) else if (s->s.format == SANE_FRAME_RGB){ - switch (s->color_interlace[side]) { + switch (inter) { /* scanner returns color data as bgrbgr... */ case COLOR_INTERLACE_BGR: @@ -4604,6 +4970,26 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) } break; + /* scanner returns color data as gbrgbr... */ + case COLOR_INTERLACE_GBR: + DBG (17, "copy_simplex: color, GBR\n"); + for (j=0; jduplex_interlace == DUPLEX_INTERLACE_FFBB){ for(i=0; ii.width != s->s.width){ - offset = ((s->valid_x-s->i.page_x) / 2 + s->i.tl_x) * s->i.dpi_x/1200*3; + offset = ((s->valid_x-s->i.page_x) / 2 + s->i.tl_x) * s->i.dpi_x/1200; } /* change mode, store line in buffer */ @@ -4905,7 +5291,7 @@ copy_line(struct scanner *s, unsigned char * buff, int side) /*loop over output bits*/ for(j=0;j<8;j++){ - int source = (offset+i)*24 + j*3; + int source = offset*3 + i*24 + j*3; if( (line[source] + line[source+1] + line[source+2]) < thresh ){ curr |= 1 << (7-j); } @@ -5967,6 +6353,7 @@ default_globals(void) { global_buffer_size = global_buffer_size_default; global_padded_read = global_padded_read_default; + global_extra_status = global_extra_status_default; global_duplex_offset = global_duplex_offset_default; global_vendor_name[0] = 0; global_model_name[0] = 0; @@ -6252,7 +6639,6 @@ do_scsi_cmd(struct scanner *s, int runRS, int shortTime, ) { int ret; - size_t actLen = 0; /*shut up compiler*/ runRS=runRS; @@ -6270,7 +6656,6 @@ do_scsi_cmd(struct scanner *s, int runRS, int shortTime, if (inBuff && inLen){ DBG(25, "in: reading %d bytes\n", (int)*inLen); memset(inBuff,0,*inLen); - actLen = *inLen; } ret = sanei_scsi_cmd2(s->fd, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen); @@ -6285,7 +6670,7 @@ do_scsi_cmd(struct scanner *s, int runRS, int shortTime, DBG(25, "in: short read, remainder %lu bytes\n", (u_long)s->rs_info); *inLen -= s->rs_info; } - hexdump(30, "in: <<", inBuff, *inLen); + hexdump(31, "in: <<", inBuff, *inLen); DBG(25, "in: read %d bytes\n", (int)*inLen); } @@ -6319,16 +6704,15 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * inBuffer = NULL; int inTimeout = 0; - size_t statOffset = 0; - size_t statLength = 0; - size_t statActual = 0; - unsigned char * statBuffer = NULL; - int statTimeout = 0; + size_t extraLength = 0; int ret = 0; int ret2 = 0; - DBG (10, "do_usb_cmd: start\n"); + struct timeval timer; + gettimeofday(&timer,NULL); + + DBG (10, "do_usb_cmd: start %lu %lu\n", (long unsigned int)timer.tv_sec, (long unsigned int)timer.tv_usec); /****************************************************************/ /* the command stage */ @@ -6375,6 +6759,20 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, free(cmdBuffer); } + /****************************************************************/ + /* the extra status stage, used by few scanners */ + /* this is like the regular status block, with an additional */ + /* length component at the end */ + if(s->extra_status){ + ret2 = do_usb_status(s,runRS,shortTime,&extraLength); + + /* bail out on bad RS status */ + if(ret2){ + DBG(5,"extra: bad RS status, %d\n", ret2); + return ret2; + } + } + /****************************************************************/ /* the output stage */ if(outBuff && outLen){ @@ -6432,6 +6830,12 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, inLength = inOffset+*inLen; inActual = inLength; + /* use the extra length to alter the amount of in we request */ + if(s->extra_status && extraLength && *inLen > extraLength){ + DBG(5,"in: adjust extra, %d %d\n", (int)*inLen, (int)extraLength); + inActual = inOffset+extraLength; + } + /*blast caller's copy in case we error out*/ *inLen = 0; @@ -6443,16 +6847,16 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, sanei_usb_set_timeout(inTimeout); /* build inBuffer */ - inBuffer = calloc(inLength,1); + inBuffer = calloc(inActual,1); if(!inBuffer){ DBG(5,"in: no mem\n"); return SANE_STATUS_NO_MEM; } - DBG(25, "in: reading %d bytes, timeout %d\n", (int)inLength, inTimeout); + DBG(25, "in: reading %d bytes, timeout %d\n", (int)inActual, inTimeout); ret = sanei_usb_read_bulk(s->fd, inBuffer, &inActual); DBG(25, "in: read %d bytes, retval %d\n", (int)inActual, ret); - hexdump(30, "in: <<", inBuffer, inActual); + hexdump(31, "in: <<", inBuffer, inActual); if(!inActual){ DBG(5,"in: got no data, clearing\n"); @@ -6474,49 +6878,8 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, } /****************************************************************/ - /* the status stage */ - statOffset = 0; - if(s->padded_read) - statOffset = USB_HEADER_LEN; - - statLength = statOffset+USB_STATUS_LEN; - statActual = statLength; - statTimeout = USB_STATUS_TIME; - - /* change timeout */ - if(shortTime) - statTimeout/=60; - sanei_usb_set_timeout(statTimeout); - - /* build statBuffer */ - statBuffer = calloc(statLength,1); - if(!statBuffer){ - DBG(5,"stat: no mem\n"); - if(inBuffer) free(inBuffer); - return SANE_STATUS_NO_MEM; - } - - DBG(25, "stat: reading %d bytes, timeout %d\n", (int)statLength, statTimeout); - ret2 = sanei_usb_read_bulk(s->fd, statBuffer, &statActual); - DBG(25, "stat: read %d bytes, retval %d\n", (int)statActual, ret2); - hexdump(30, "stat: <<", statBuffer, statActual); - - /*weird status*/ - if(ret2 != SANE_STATUS_GOOD){ - DBG(5,"stat: clearing error '%s'\n",sane_strstatus(ret2)); - ret2 = do_usb_clear(s,1,runRS); - } - /*short read*/ - else if(statLength != statActual){ - DBG(5,"stat: clearing short %d/%d\n",(int)statLength,(int)statActual); - ret2 = do_usb_clear(s,1,runRS); - } - /*inspect the last byte of the status response*/ - else if(statBuffer[statLength-1]){ - DBG(5,"stat: status %d\n",statBuffer[statLength-1]); - ret2 = do_usb_clear(s,0,runRS); - } - free(statBuffer); + /* the normal status stage */ + ret2 = do_usb_status(s,runRS,shortTime,&extraLength); /* if status said EOF, adjust input with remainder count */ if(ret2 == SANE_STATUS_EOF && inBuffer){ @@ -6524,11 +6887,11 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, /* EOF is ok */ ret2 = SANE_STATUS_GOOD; - if(inActual <= inLength - s->rs_info){ - DBG(5,"in: we read <= RS, ignoring RS: %d <= %d (%d-%d)\n", + if(inActual < inLength - s->rs_info){ + DBG(5,"in: we read < RS, ignoring RS: %d < %d (%d-%d)\n", (int)inActual,(int)(inLength-s->rs_info),(int)inLength,(int)s->rs_info); } - else if(s->rs_info){ + else if(inActual > inLength - s->rs_info){ DBG(5,"in: we read > RS, using RS: %d to %d (%d-%d)\n", (int)inActual,(int)(inLength-s->rs_info),(int)inLength,(int)s->rs_info); inActual = inLength - s->rs_info; @@ -6556,7 +6919,80 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, free(inBuffer); } - DBG (10, "do_usb_cmd: finish\n"); + gettimeofday(&timer,NULL); + + DBG (10, "do_usb_cmd: finish %lu %lu\n", (long unsigned int)timer.tv_sec, (long unsigned int)timer.tv_usec); + + return ret; +} + +static SANE_Status +do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength) +{ + +#define EXTRA_READ_len 4 + + size_t statPadding = 0; + size_t statOffset = 0; + size_t statLength = 0; + size_t statActual = 0; + unsigned char * statBuffer = NULL; + int statTimeout = 0; + + int ret = 0; + + if(s->padded_read) + statPadding = USB_HEADER_LEN; + + statLength = statPadding+USB_STATUS_LEN; + statOffset = statLength-1; + + if(s->extra_status) + statLength += EXTRA_READ_len; + + statActual = statLength; + statTimeout = USB_STATUS_TIME; + + /* change timeout */ + if(shortTime) + statTimeout/=60; + sanei_usb_set_timeout(statTimeout); + + /* build statBuffer */ + statBuffer = calloc(statLength,1); + if(!statBuffer){ + DBG(5,"stat: no mem\n"); + return SANE_STATUS_NO_MEM; + } + + DBG(25, "stat: reading %d bytes, timeout %d\n", (int)statLength, statTimeout); + ret = sanei_usb_read_bulk(s->fd, statBuffer, &statActual); + DBG(25, "stat: read %d bytes, retval %d\n", (int)statActual, ret); + hexdump(30, "stat: <<", statBuffer, statActual); + + /*weird status*/ + if(ret != SANE_STATUS_GOOD){ + DBG(5,"stat: clearing error '%s'\n",sane_strstatus(ret)); + ret = do_usb_clear(s,1,runRS); + } + /*short read*/ + else if(statLength != statActual){ + DBG(5,"stat: clearing short %d/%d\n",(int)statLength,(int)statActual); + ret = do_usb_clear(s,1,runRS); + } + /*inspect the status byte of the response*/ + else if(statBuffer[statOffset]){ + DBG(5,"stat: status %d\n",statBuffer[statLength-1-4]); + ret = do_usb_clear(s,0,runRS); + } + + /*extract the extra length byte of the response*/ + if(s->extra_status){ + *extraLength = get_ES_length(statBuffer); + DBG(15,"stat: extra %d\n",(int)*extraLength); + } + + free(statBuffer); return ret; } @@ -6670,6 +7106,26 @@ wait_scanner(struct scanner *s) return ret; } +/* Some scanners have per-resolution + * color interlacing values, but most + * don't. This helper can tell the + * difference. + */ +static int +get_color_inter(struct scanner *s, int side, int res) +{ + int i; + for(i=0;icolor_inter_by_res[i]) + return s->color_inter_by_res[i]; + + return s->color_interlace[side]; +} + /* s->u.page_x stores the user setting * for the paper width in adf. sometimes, * we need a value that differs from this @@ -6789,7 +7245,8 @@ hexdump (int level, char *comment, unsigned char *p, int l) } /* print last (partial) line */ - DBG (level, "%s\n", line); + if (i) + DBG (level, "%s\n", line); } /** diff --git a/backend/canon_dr.conf.in b/backend/canon_dr.conf.in index ef1dfdf..e946d9b 100644 --- a/backend/canon_dr.conf.in +++ b/backend/canon_dr.conf.in @@ -15,8 +15,9 @@ ####################################################################### # Set data buffer size, in bytes. The value ranges from 4096 - infinity -# large values may cause timeouts, small causes slow scans. 4MB default -#option buffer-size 4194304 +# Large values may cause timeouts, or long pauses at the end of each +# page. Small values may cause slow scans. 2MB is the default. +#option buffer-size 2097152 ####################################################################### # Most scanners dont pad their reads @@ -138,9 +139,68 @@ usb 0x1083 0x1638 # CR-135i usb 0x1083 0x1639 +# DR-M160 +option extra-status 1 +option duplex-offset 400 +usb 0x1083 0x163e + +# DR-M140 +option extra-status 1 +option duplex-offset 400 +usb 0x1083 0x163f + +# DR-C125 +usb 0x1083 0x1640 + +# DR-P215 +usb 0x1083 0x1641 + # P-215 usb 0x1083 0x1646 +# FSU-201 +usb 0x1083 0x1648 + +# DR-C130 +usb 0x1083 0x164a + +# DR-P208 +usb 0x1083 0x164b + # P-208 usb 0x1083 0x164c +# DR-G1130 +option buffer-size 8000000 +usb 0x1083 0x164f + +# DR-G1100 +option buffer-size 8000000 +usb 0x1083 0x1650 + +# DR-C120 +usb 0x1083 0x1651 + +# P-201 +usb 0x1083 0x1652 + +# DR-F120 +usb 0x1083 0x1654 + +# DR-M1060 +usb 0x1083 0x1657 + +# DR-C225 +usb 0x1083 0x1658 + +# DR-P215II +usb 0x1083 0x1659 + +# P-215II +usb 0x1083 0x165b + +# DR-P208II +usb 0x1083 0x165d + +# P-208II +usb 0x1083 0x165f diff --git a/backend/canon_dr.h b/backend/canon_dr.h index 1bf95a0..4a19f55 100644 --- a/backend/canon_dr.h +++ b/backend/canon_dr.h @@ -58,6 +58,8 @@ enum scanner_Option OPT_COUNTONLY, OPT_BYPASSMODE, OPT_COUNTER, + OPT_ADF_LOADED, + OPT_CARD_LOADED, /* must come last: */ NUM_OPTIONS @@ -174,13 +176,16 @@ struct scanner int has_flatbed; int has_duplex; int has_back; /* not all duplex scanners can do adf back side only */ + int has_card; /* P215 has a card reader instead of fb */ int has_comp_JPEG; int has_buffer; int has_df; + int has_df_ultra; int has_btc; int has_ssm; /* older scanners use this set scan mode command */ int has_ssm2; /* newer scanners user this similar command */ int has_ssm_pay_head_len; /* newer scanners put the length twice in ssm */ + int can_read_sensors; int can_read_panel; int can_write_panel; int rgb_format; /* meaning unknown */ @@ -190,11 +195,13 @@ struct scanner int invert_tly; /* weird bug in some smaller scanners */ int unknown_byte2; /* weird byte, required, meaning unknown */ int padded_read; /* some machines need extra 12 bytes on reads */ + int extra_status; /* some machines need extra status read after cmd */ int fixed_width; /* some machines always scan full width */ int even_Bpl; /* some machines require even bytes per line */ int gray_interlace[2]; /* different models interlace heads differently */ int color_interlace[2]; /* different models interlace colors differently */ + int color_inter_by_res[16]; /* and some even change by resolution */ int duplex_interlace; /* different models interlace sides differently */ int jpeg_interlace; /* different models interlace jpeg sides differently */ int duplex_offset; /* number of lines of padding added to front (1/1200)*/ @@ -224,7 +231,7 @@ struct scanner /*mode group*/ SANE_String_Const mode_list[7]; - SANE_String_Const source_list[5]; + SANE_String_Const source_list[8]; SANE_Int res_list[17]; SANE_Range res_range; @@ -334,9 +341,12 @@ struct scanner int panel_bypass_mode; int panel_enable_led; int panel_counter; + int sensor_adf_loaded; + int sensor_card_loaded; /* values which are used to track the frontend's access to sensors */ - char hw_read[NUM_OPTIONS-OPT_START]; + char panel_read[OPT_COUNTER - OPT_START + 1]; + char sensors_read[OPT_CARD_LOADED - OPT_ADF_LOADED + 1]; }; #define CONNECTION_SCSI 0 /* SCSI interface */ @@ -353,6 +363,9 @@ struct scanner #define SOURCE_ADF_FRONT 1 #define SOURCE_ADF_BACK 2 #define SOURCE_ADF_DUPLEX 3 +#define SOURCE_CARD_FRONT 4 +#define SOURCE_CARD_BACK 5 +#define SOURCE_CARD_DUPLEX 6 static const int dpi_list[] = { 60,75,100,120,150,160,180,200, @@ -406,11 +419,14 @@ enum { #define GRAY_INTERLACE_2510 1 #define GRAY_INTERLACE_gG 2 -#define COLOR_INTERLACE_RGB 0 -#define COLOR_INTERLACE_BGR 1 -#define COLOR_INTERLACE_RRGGBB 2 -#define COLOR_INTERLACE_rRgGbB 3 -#define COLOR_INTERLACE_2510 4 +#define COLOR_INTERLACE_UNK 0 +#define COLOR_INTERLACE_RGB 1 +#define COLOR_INTERLACE_BGR 2 +#define COLOR_INTERLACE_BRG 3 +#define COLOR_INTERLACE_GBR 4 +#define COLOR_INTERLACE_RRGGBB 5 +#define COLOR_INTERLACE_rRgGbB 6 +#define COLOR_INTERLACE_2510 7 #define DUPLEX_INTERLACE_NONE 0 #define DUPLEX_INTERLACE_FFBB 1 @@ -510,6 +526,9 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * inBuff, size_t * inLen ); +static SANE_Status +do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength); + static SANE_Status do_usb_clear(struct scanner *s, int clear, int runRS); static SANE_Status wait_scanner (struct scanner *s); @@ -520,6 +539,8 @@ static SANE_Status ssm_buffer (struct scanner *s); static SANE_Status ssm_do (struct scanner *s); static SANE_Status ssm_df (struct scanner *s); +static int get_color_inter(struct scanner *s, int side, int res); + static int get_page_width (struct scanner *s); static int get_page_height (struct scanner *s); @@ -528,6 +549,7 @@ static SANE_Status update_params (struct scanner *s, int calib); static SANE_Status update_i_params (struct scanner *s); static SANE_Status clean_params (struct scanner *s); +static SANE_Status read_sensors(struct scanner *s, SANE_Int option); static SANE_Status read_panel(struct scanner *s, SANE_Int option); static SANE_Status send_panel(struct scanner *s); diff --git a/backend/coolscan.c b/backend/coolscan.c index 00a12e4..d3c7749 100644 --- a/backend/coolscan.c +++ b/backend/coolscan.c @@ -179,7 +179,7 @@ request_sense_parse (unsigned char *sensed_data) case 0x2: if ((0x4 == asc) && (0x1 == ascq)) { - DBG (10, "\t%d/%d/%d: Logical unit is in process of becomming ready\n", + DBG (10, "\t%d/%d/%d: Logical unit is in process of becoming ready\n", sense, asc, ascq); ret = SANE_STATUS_DEVICE_BUSY; } diff --git a/backend/epjitsu-cmd.h b/backend/epjitsu-cmd.h index 2e914d9..77793df 100644 --- a/backend/epjitsu-cmd.h +++ b/backend/epjitsu-cmd.h @@ -38,31 +38,55 @@ static unsigned char coarseCalData_S300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static unsigned char coarseCalData_S1300i[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static unsigned char coarseCalData_S1100[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x26, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; /*************** fi-60F 150dpi *************/ -/* 1b d1 (set window) before coarse cal (read 1 line of 0x____ bytes) */ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x1c20 bytes) */ static unsigned char setWindowCoarseCal_FI60F_150[] = { -0 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/* 1b d1 (set window) before fine cal (read 16 lines of 0x____ bytes) */ +/* 1b d1 (set window) before fine cal (read 16 lines of 0x1c20 bytes) */ static unsigned char setWindowFineCal_FI60F_150[] = { -0 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/* 1b d1 (set window) before gain/offset tables (write 1 line of 0x____ bytes) */ +/* 1b d1 (set window) before gain/offset tables (write 1 line of 0x3840 bytes) */ static unsigned char setWindowSendCal_FI60F_150[] = { -0 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ -static unsigned char sendCal1Header_FI60F_150[] = { -0 +static unsigned char sendCal1Header_FI60F_150[] = { /* plus 0x3840 data bytes */ +0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_FI60F_150[] = { -0 +0x39, 0x3f, 0x39, 0x3f, 0x39, 0x3f, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_FI60F_150[] = { -0 +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x96, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x01, 0x48, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 300dpi *************/ @@ -323,8 +347,8 @@ static unsigned char setWindowScan_S300_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/*S300 can also use a USB power cable, but it requires a different set of params?*/ -/*************** S300 150dpi USB *************/ +/*S300/S1300/S1300i can also use a USB power cable, but it requires a different set of params?*/ +/*************** S300/S1300/S1300i 150dpi USB *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_150_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, @@ -338,7 +362,7 @@ static unsigned char setWindowFineCal_S300_150_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x08, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ @@ -368,7 +392,7 @@ static unsigned char setWindowScan_S300_150_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/*************** S300 225dpi USB *************/ +/*************** S300/S1300/S1300i 225dpi USB *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_225_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, @@ -412,7 +436,8 @@ static unsigned char setWindowScan_S300_225_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/*************** S300 300dpi USB *************/ +/*************** S300/S1300/S1300i 300dpi USB *************/ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, @@ -456,4 +481,229 @@ static unsigned char setWindowScan_S300_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/*************** S300 600dpi USB is same as AC power *************/ +/*************** S300/S1300/S1300i USB is same as AC power *************/ + +/*************** S1300i 150dpi *************/ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x5e24 bytes) */ +static unsigned char setWindowCoarseCal_S1300i_150[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before fine cal (read 16 lines of 0x5e24 bytes) */ +static unsigned char setWindowFineCal_S1300i_150[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before gain/offset tables (write 1 line of 0xbc40 bytes) */ +static unsigned char setWindowSendCal_S1300i_150[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b c3 (gain?) command header */ +static unsigned char sendCal1Header_S1300i_150[] = { /* plus 0xc780 data bytes */ +0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0x00, 0x04 +}; +/* 1b c4 (offset?) command header */ +static unsigned char sendCal2Header_S1300i_150[] = { /* plus 0xc780 data bytes */ +0xd7, 0x3b, 0xd7, 0x3b, 0xd7, 0x3b, 0x07 +}; +/* 1b d1 (set window) before scan */ +static unsigned char setWindowScan_S1300i_150[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x01, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/*************** S1300i 225dpi *************/ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ +static unsigned char setWindowCoarseCal_S1300i_225[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before fine cal (read 16 lines of 0x63c0 bytes) */ +static unsigned char setWindowFineCal_S1300i_225[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ +static unsigned char setWindowSendCal_S1300i_225[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b c3 (gain?) command header */ +static unsigned char sendCal1Header_S1300i_225[] = { /* plus 0xc780 data bytes */ +0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x00, 0x04 +}; +/* 1b c4 (offset?) command header */ +static unsigned char sendCal2Header_S1300i_225[] = { /* plus 0xc780 data bytes */ +0xa5, 0x3b, 0xa5, 0x3b, 0xa5, 0x3b, 0x07 +}; +/* 1b d1 (set window) before scan */ +static unsigned char setWindowScan_S1300i_225[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xc8, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/*************** S1300i 300dpi *************/ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x5ee0 bytes) */ +static unsigned char setWindowCoarseCal_S1300i_300[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before fine cal (read 16 lines of 0x5ee0 bytes) */ +static unsigned char setWindowFineCal_S1300i_300[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before gain/offset tables (write 1 line of 0xbdc0 bytes) */ +static unsigned char setWindowSendCal_S1300i_300[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b c3 (gain?) command header */ +static unsigned char sendCal1Header_S1300i_300[] = { /* plus 0xc000 data bytes */ +0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0x00, 0x04 +}; +/* 1b c4 (offset?) command header */ +static unsigned char sendCal2Header_S1300i_300[] = { /* plus 0xc000 data bytes */ +0x75, 0x3c, 0x75, 0x3c, 0x75, 0x3c, 0x07 +}; +/* 1b d1 (set window) before scan */ +static unsigned char setWindowScan_S1300i_300[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x0d, 0xc4, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/*************** S1300i 600dpi AC power is same as S300 *************/ +/*************** except the calibration headers *************/ + +/* 1b c3 (gain?) command header */ +static unsigned char sendCal1Header_S1300i_USB[] = { +0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x00, 0x04 +}; +/* 1b c4 (offset?) command header */ +static unsigned char sendCal2Header_S1300i_USB[] = { +0x8f, 0x40, 0x8f, 0x40, 0x8f, 0x40, 0x07 +}; + +/*************** S1300i all resolutions USB power is same as S300 *************/ + +/*************** S1100 300dpi USB *************/ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x45a0 bytes) */ +static unsigned char setWindowCoarseCal_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before fine cal (read 16 lines of 0x45a0 bytes) */ +static unsigned char setWindowFineCal_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before gain/offset tables (write 1 line of 0x45a0 bytes) */ +static unsigned char setWindowSendCal_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b c3 (gain?) command header */ +static unsigned char sendCal1Header_S1100_300_U[] = { /* plus 0x45a0 data bytes */ +0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x00, 0x03 +}; +/* 1b c4 (offset?) command header */ +static unsigned char sendCal2Header_S1100_300_U[] = { /* plus 0x45a0 data bytes */ +0x63, 0x86, 0x63, 0x86, 0x63, 0x86, 0x07 +}; +/* 1b d1 (set window) before scan */ +static unsigned char setWindowScan_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x1b, 0xe1, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x01, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/*************** S1100 600dpi USB *************/ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x3e20 bytes) */ +static unsigned char setWindowCoarseCal_S1100_600_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before fine cal (read 16 lines of 0x3e20 bytes) */ +static unsigned char setWindowFineCal_S1100_600_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before gain/offset tables (write 1 line of 0x7c40 bytes) */ +static unsigned char setWindowSendCal_S1100_600_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b c3 (gain?) command header */ +static unsigned char sendCal1Header_S1100_600_U[] = { /* plus 0x7c40 data bytes */ +0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0x00, 0x03 +}; +/* 1b c4 (offset?) command header */ +static unsigned char sendCal2Header_S1100_600_U[] = { /* plus 0x7c40 data bytes */ +0x4b, 0x81, 0x4b, 0x81, 0x4b, 0x81, 0x07 +}; +/* 1b d1 (set window) before scan */ +static unsigned char setWindowScan_S1100_600_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 0x00, 0x00, 0x37, 0xbf, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 3e102da..08e78b2 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -123,9 +123,29 @@ - dont export private symbols v19 2009-08-31, RG - rewritten calibration routines - v20 2010-02-09, MAN (SANE 1.0.21 & 1.0.22) + v20 2010-02-09, MAN (SANE 1.0.21 to 1.0.24) - cleanup #include lines & copyright - add S1300 + v21 2011-04-15, MAN + - unreleased attempt at S1100 support + v22 2014-05-15, MAN/Hiroshi Miura + - port some S1100 changes from v21 + - add paper size support + v23 2014-05-20, MAN + - add S1300i support + - fix buffer overruns in read_from_scanner + - set default page width + - simplified the 225x200 resolution code + v24 2014-06-01, MAN + - enable fine calibration for S1300i 225 & 300 dpi, and S300 150 dpi + v25 2014-06-04, MAN + - initial support for fi-65F + - initial support for S1100 + v26 2014-06-28, MAN + - add resolution scaling + - fix 150 dpi settings for fi-60F and fi-65F + - make adf_height_padding variable + - make white_factor variable SANE FLOW DIAGRAM @@ -174,7 +194,7 @@ #include "epjitsu-cmd.h" #define DEBUG 1 -#define BUILD 20 +#define BUILD 26 #ifndef MAX3 #define MAX3(a,b,c) ((a) > (b) ? ((a) > (c) ? a : c) : ((b) > (c) ? b : c)) @@ -197,7 +217,6 @@ unsigned char global_firmware_filename[PATH_MAX]; static int coarse_gain_min[3] = { 88, 88, 88 }; /* front, back, FI-60F 3rd plane */ static int coarse_gain_max[3] = { 92, 92, 92 }; static int fine_gain_target[3] = {185, 150, 170}; /* front, back, FI-60F is this ok? */ -static float white_factor[3] = {1.0, 0.93, 0.98}; /* Blue, Red, Green */ /* ------------------------------------------------------------------------- */ #define STRING_FLATBED SANE_I18N("Flatbed") @@ -458,7 +477,39 @@ attach_one (const char *name) DBG (15, "attach_one: Found %s scanner %s at %s\n", s->sane.vendor, s->sane.model, s->sane.name); - if (strstr (s->sane.model, "S300") || strstr (s->sane.model, "S1300")){ + if (strstr (s->sane.model, "S1300i")){ + unsigned char stat; + + DBG (15, "attach_one: Found S1300i\n"); + + stat = get_stat(s); + if(stat & 0x01){ + DBG (5, "attach_one: on USB power?\n"); + s->usb_power=1; + } + + s->model = MODEL_S1300i; + + s->has_adf = 1; + s->has_adf_duplex = 1; + s->min_res = 50; + s->max_res = 600; + s->adf_height_padding = 600; + /* Blue, Red, Green */ + s->white_factor[0] = 1.0; + s->white_factor[1] = 0.93; + s->white_factor[2] = 0.98; + + s->source = SOURCE_ADF_FRONT; + s->mode = MODE_LINEART; + s->resolution = 300; + s->page_height = 11.5 * 1200; + s->page_width = 8.5 * 1200; + + s->threshold = 120; + s->threshold_curve = 55; + } + else if (strstr (s->sane.model, "S300") || strstr (s->sane.model, "S1300")){ unsigned char stat; DBG (15, "attach_one: Found S300/S1300\n"); @@ -472,46 +523,93 @@ attach_one (const char *name) s->model = MODEL_S300; s->has_adf = 1; - s->x_res_150 = 1; - s->x_res_225 = 1; - s->x_res_300 = 1; - s->x_res_600 = 1; - s->y_res_150 = 1; - s->y_res_225 = 1; - s->y_res_300 = 1; - s->y_res_600 = 1; + s->has_adf_duplex = 1; + s->min_res = 50; + s->max_res = 600; + s->adf_height_padding = 600; + /* Blue, Red, Green */ + s->white_factor[0] = 1.0; + s->white_factor[1] = 0.93; + s->white_factor[2] = 0.98; s->source = SOURCE_ADF_FRONT; - s->mode = MODE_LINEART; - s->resolution_x = 300; + s->mode = MODE_LINEART; + s->resolution = 300; s->page_height = 11.5 * 1200; + s->page_width = 8.5 * 1200; s->threshold = 120; s->threshold_curve = 55; } + else if (strstr (s->sane.model, "S1100")){ + DBG (15, "attach_one: Found S1100\n"); + s->model = MODEL_S1100; + + s->usb_power = 1; + s->has_adf = 1; + s->has_adf_duplex = 0; + s->min_res = 50; + s->max_res = 600; + s->adf_height_padding = 450; + /* Blue, Red, Green */ + s->white_factor[0] = 0.95; + s->white_factor[1] = 1.0; + s->white_factor[2] = 1.0; + s->source = SOURCE_ADF_FRONT; + s->mode = MODE_LINEART; + s->resolution = 300; + s->page_height = 11.5 * 1200; + s->page_width = 8.5 * 1200; + + s->threshold = 120; + s->threshold_curve = 55; + } else if (strstr (s->sane.model, "fi-60F")){ DBG (15, "attach_one: Found fi-60F\n"); s->model = MODEL_FI60F; s->has_fb = 1; - s->x_res_150 = 0; - s->x_res_300 = 1; - s->x_res_600 = 1; - s->y_res_150 = 0; - s->y_res_300 = 1; - s->y_res_600 = 1; + s->min_res = 50; + s->max_res = 600; + /* Blue, Red, Green */ + s->white_factor[0] = 1.0; + s->white_factor[1] = 0.93; + s->white_factor[2] = 0.98; s->source = SOURCE_FLATBED; - s->mode = MODE_COLOR; - s->resolution_x = 300; + s->mode = MODE_COLOR; + s->resolution = 300; s->page_height = 5.83 * 1200; + s->page_width = 4.1 * 1200; s->threshold = 120; s->threshold_curve = 55; } + else if (strstr (s->sane.model, "fi-65F")){ + DBG (15, "attach_one: Found fi-65F\n"); + + s->model = MODEL_FI65F; + + s->has_fb = 1; + s->min_res = 50; + s->max_res = 600; + /* Blue, Red, Green */ + s->white_factor[0] = 1.0; + s->white_factor[1] = 0.93; + s->white_factor[2] = 0.98; + + s->source = SOURCE_FLATBED; + s->mode = MODE_COLOR; + s->resolution = 300; + s->page_height = 5.83 * 1200; + s->page_width = 4.1 * 1200; + + s->threshold = 120; + s->threshold_curve = 55; + } else{ DBG (15, "attach_one: Found other\n"); } @@ -615,6 +713,7 @@ load_fw (struct scanner *s) return SANE_STATUS_NO_DOCS; } + /* skip first 256 (=0x100) bytes */ if(lseek(file,0x100,SEEK_SET) != 0x100){ DBG (5, "load_fw: failed to lseek file %s\n",global_firmware_filename); close(file); @@ -761,7 +860,7 @@ load_fw (struct scanner *s) } /* - * try to load fw into scanner + * get status from scanner */ static unsigned char get_stat(struct scanner *s) @@ -795,6 +894,10 @@ get_stat(struct scanner *s) return stat[0]; } +/* + * get scanner identification + */ + static SANE_Status get_ident(struct scanner *s) { @@ -946,8 +1049,10 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) } if(s->has_adf){ s->source_list[i++]=STRING_ADFFRONT; - s->source_list[i++]=STRING_ADFBACK; - s->source_list[i++]=STRING_ADFDUPLEX; + if(s->has_adf_duplex){ + s->source_list[i++]=STRING_ADFBACK; + s->source_list[i++]=STRING_ADFDUPLEX; + } } s->source_list[i]=NULL; @@ -983,33 +1088,19 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) } } - else if(option==OPT_X_RES){ - i=0; - if(s->x_res_150){ - s->x_res_list[++i] = 150; - } - if(s->x_res_225){ - s->x_res_list[++i] = 225; - } - if(s->x_res_300){ - s->x_res_list[++i] = 300; - } - if(s->x_res_600){ - s->x_res_list[++i] = 600; - } - s->x_res_list[0] = i; - + else if(option==OPT_RES){ opt->name = SANE_NAME_SCAN_RESOLUTION; - opt->title = SANE_TITLE_SCAN_X_RESOLUTION; - opt->desc = SANE_DESC_SCAN_X_RESOLUTION; + opt->title = SANE_TITLE_SCAN_RESOLUTION; + opt->desc = SANE_DESC_SCAN_RESOLUTION; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_DPI; - if(i > 1){ - opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; - } + opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; - opt->constraint_type = SANE_CONSTRAINT_WORD_LIST; - opt->constraint.word_list = s->x_res_list; + s->res_range.min = s->min_res; + s->res_range.max = s->max_res; + s->res_range.quant = 1; + opt->constraint_type = SANE_CONSTRAINT_RANGE; + opt->constraint.range = &s->res_range; } /* "Geometry" group ---------------------------------------------------- */ @@ -1056,7 +1147,6 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; - opt->cap = SANE_CAP_INACTIVE; } /* bottom-right x */ @@ -1122,7 +1212,6 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) else{ opt->cap = SANE_CAP_INACTIVE; } - opt->cap = SANE_CAP_INACTIVE; } /* page height */ @@ -1421,8 +1510,8 @@ sane_control_option (SANE_Handle handle, SANE_Int option, } return SANE_STATUS_GOOD; - case OPT_X_RES: - *val_p = s->resolution_x; + case OPT_RES: + *val_p = s->resolution; return SANE_STATUS_GOOD; case OPT_TL_X: @@ -1569,17 +1658,17 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->mode = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; - return change_params(s); + return SANE_STATUS_GOOD; - case OPT_X_RES: + case OPT_RES: - if (s->resolution_x == val_c) + if (s->resolution == val_c) return SANE_STATUS_GOOD; - s->resolution_x = val_c; + s->resolution = val_c; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; - return change_params(s); + return SANE_STATUS_GOOD; /* Geometry Group */ case OPT_TL_X: @@ -1598,7 +1687,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->tl_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; - return SANE_STATUS_GOOD; + return change_params(s); case OPT_BR_X: if (s->br_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) @@ -1685,16 +1774,15 @@ struct model_res { int max_y; int min_y; - int act_width; /* total data width output, in pixels per side (always 3 sides) */ - int req_width; /* stride in pixels per side between color planes (always 3 sides) */ - int head_width; - int pad_width; + int line_stride; /* byte width of 1 raw side, with padding */ + int plane_stride; /* byte width of 1 raw color plane, with padding */ + int plane_width; /* byte width of 1 raw color plane, without padding */ int block_height; - int cal_width; - int cal_headwidth; - int cal_reqwidth; + int cal_line_stride; + int cal_plane_stride; + int cal_plane_width; unsigned char * sw_coarsecal; unsigned char * sw_finecal; @@ -1709,67 +1797,141 @@ struct model_res { static struct model_res settings[] = { /*S300 AC*/ -/* model xres yres u mxx mnx mxy mny actw reqw hedw padw bh calw cal_hedw cal_reqw */ - { MODEL_S300, 150, 150, 0, 1296, 32, 2662, 32, 4256, 1480, 1296, 184, 41, 8512, 2592, 2960, +/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ + { MODEL_S300, 150, 150, 0, 1296, 32, 2662, 32, 4256*3, 1480*3, 1296, 41, 8512*3, 2960*3, 2592, setWindowCoarseCal_S300_150, setWindowFineCal_S300_150, setWindowSendCal_S300_150, sendCal1Header_S300_150, sendCal2Header_S300_150, setWindowScan_S300_150 }, - { MODEL_S300, 225, 200, 0, 1944, 32, 3993, 32, 6144, 2100, 1944, 156, 28, 8192, 2592, 2800, + { MODEL_S300, 225, 200, 0, 1944, 32, 3993, 32, 6144*3, 2100*3, 1944, 28, 8192*3, 2800*3, 2592, setWindowCoarseCal_S300_225, setWindowFineCal_S300_225, setWindowSendCal_S300_225, sendCal1Header_S300_225, sendCal2Header_S300_225, setWindowScan_S300_225 }, - { MODEL_S300, 300, 300, 0, 2592, 32, 5324, 32, 8192, 2800, 2592, 208, 21, 8192, 2592, 2800, + { MODEL_S300, 300, 300, 0, 2592, 32, 5324, 32, 8192*3, 2800*3, 2592, 21, 8192*3, 2800*3, 2592, setWindowCoarseCal_S300_300, setWindowFineCal_S300_300, setWindowSendCal_S300_300, sendCal1Header_S300_300, sendCal2Header_S300_300, setWindowScan_S300_300 }, - { MODEL_S300, 600, 600, 0, 5184, 32, 10648, 32, 16064, 5440, 5184, 256, 10, 16064, 5184, 5440, + { MODEL_S300, 600, 600, 0, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, setWindowSendCal_S300_600, sendCal1Header_S300_600, sendCal2Header_S300_600, setWindowScan_S300_600 }, /*S300 USB*/ -/* model xres yres u mxx mnx mxy mny actw reqw hedw padw bh calw cal_hedw cal_reqw */ - { MODEL_S300, 150, 150, 1, 1296, 32, 2662, 32, 7216, 2960, 1296, 1664, 24, 14432, 2592, 5920, +/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ + { MODEL_S300, 150, 150, 1, 1296, 32, 2662, 32, 7216*3, 2960*3, 1296, 24, 14432*3, 5920*3, 2592, setWindowCoarseCal_S300_150_U, setWindowFineCal_S300_150_U, setWindowSendCal_S300_150_U, sendCal1Header_S300_150_U, sendCal2Header_S300_150_U, setWindowScan_S300_150_U }, - { MODEL_S300, 225, 200, 1, 1944, 32, 3993, 32, 10584, 4320, 1944, 2376, 16, 14112, 2592, 5760, + { MODEL_S300, 225, 200, 1, 1944, 32, 3993, 32, 10584*3, 4320*3, 1944, 16, 14112*3, 5760*3, 2592, setWindowCoarseCal_S300_225_U, setWindowFineCal_S300_225_U, setWindowSendCal_S300_225_U, sendCal1Header_S300_225_U, sendCal2Header_S300_225_U, setWindowScan_S300_225_U }, - { MODEL_S300, 300, 300, 1, 2592, 32, 5324, 32, 15872, 6640, 2592, 4048, 11, 15872, 2592, 6640, + { MODEL_S300, 300, 300, 1, 2592, 32, 5324, 32, 15872*3, 6640*3, 2592, 11, 15872*3, 6640*3, 2592, setWindowCoarseCal_S300_300_U, setWindowFineCal_S300_300_U, setWindowSendCal_S300_300_U, sendCal1Header_S300_300_U, sendCal2Header_S300_300_U, setWindowScan_S300_300_U }, - { MODEL_S300, 600, 600, 1, 5184, 32, 10648, 32, 16064, 5440, 5184, 256, 10, 16064, 5184, 5440, + { MODEL_S300, 600, 600, 1, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, + setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, + setWindowSendCal_S300_600, sendCal1Header_S300_600, + sendCal2Header_S300_600, setWindowScan_S300_600 }, + + /*S1300i AC*/ +/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ + { MODEL_S1300i, 150, 150, 0, 1296, 32, 2662, 32, 4016*3, 1360*3, 1296, 43, 8032*3, 2720*3, 2592, + setWindowCoarseCal_S1300i_150, setWindowFineCal_S1300i_150, + setWindowSendCal_S1300i_150, sendCal1Header_S1300i_150, + sendCal2Header_S1300i_150, setWindowScan_S1300i_150 }, + + { MODEL_S1300i, 225, 200, 0, 1944, 32, 3993, 32, 6072*3, 2063*3, 1944, 28, 8096*3, 2752*3, 2592, + setWindowCoarseCal_S1300i_225, setWindowFineCal_S1300i_225, + setWindowSendCal_S1300i_225, sendCal1Header_S1300i_225, + sendCal2Header_S1300i_225, setWindowScan_S1300i_225 }, + + { MODEL_S1300i, 300, 300, 0, 2592, 32, 5324, 32, 8096*3, 2751*3, 2592, 21, 8096*3, 2752*3, 2592, + setWindowCoarseCal_S1300i_300, setWindowFineCal_S1300i_300, + setWindowSendCal_S1300i_300, sendCal1Header_S1300i_300, + sendCal2Header_S1300i_300, setWindowScan_S1300i_300 }, + + /*NOTE: S1300i uses S300 data blocks for remainder*/ + { MODEL_S1300i, 600, 600, 0, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, setWindowSendCal_S300_600, sendCal1Header_S300_600, sendCal2Header_S300_600, setWindowScan_S300_600 }, + /*S1300i USB*/ +/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ + { MODEL_S1300i, 150, 150, 1, 1296, 32, 2662, 32, 7216*3, 2960*3, 1296, 24, 14432*3, 5920*3, 2592, + setWindowCoarseCal_S300_150_U, setWindowFineCal_S300_150_U, + setWindowSendCal_S300_150_U, sendCal1Header_S1300i_USB, + sendCal2Header_S1300i_USB, setWindowScan_S300_150_U }, + + { MODEL_S1300i, 225, 200, 1, 1944, 32, 3993, 32, 10584*3, 4320*3, 1944, 16, 14112*3, 5760*3, 2592, + setWindowCoarseCal_S300_225_U, setWindowFineCal_S300_225_U, + setWindowSendCal_S300_225_U, sendCal1Header_S1300i_USB, + sendCal2Header_S1300i_USB, setWindowScan_S300_225_U }, + + { MODEL_S1300i, 300, 300, 1, 2592, 32, 5324, 32, 15872*3, 6640*3, 2592, 11, 15872*3, 6640*3, 2592, + setWindowCoarseCal_S300_300_U, setWindowFineCal_S300_300_U, + setWindowSendCal_S300_300_U, sendCal1Header_S1300i_USB, + sendCal2Header_S1300i_USB, setWindowScan_S300_300_U }, + + { MODEL_S1300i, 600, 600, 1, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, + setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, + setWindowSendCal_S300_600, sendCal1Header_S1300i_USB, + sendCal2Header_S1300i_USB, setWindowScan_S300_600 }, + /*fi-60F*/ -/* model xres yres u mxx mnx mxy mny actw reqw hedw padw bh calw cal_hedw cal_reqw */ - { MODEL_FI60F, 150, 150, 0, 648, 32, 875, 32, 1480, 632, 216, 416, 41, 1480, 216, 632, +/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ + { MODEL_FI60F, 300, 150, 0, 1296, 32, 875, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432, + setWindowCoarseCal_FI60F_150, setWindowFineCal_FI60F_150, + setWindowSendCal_FI60F_150, sendCal1Header_FI60F_150, + sendCal2Header_FI60F_150, setWindowScan_FI60F_150 }, + + { MODEL_FI60F, 300, 300, 0, 1296, 32, 1749, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432, + setWindowCoarseCal_FI60F_300, setWindowFineCal_FI60F_300, + setWindowSendCal_FI60F_300, sendCal1Header_FI60F_300, + sendCal2Header_FI60F_300, setWindowScan_FI60F_300 }, + + { MODEL_FI60F, 600, 600, 0, 2592, 32, 3498, 32, 2848*3, 978*3, 864, 61, 2848*3, 978*3, 864, + setWindowCoarseCal_FI60F_600, setWindowFineCal_FI60F_600, + setWindowSendCal_FI60F_600, sendCal1Header_FI60F_600, + sendCal2Header_FI60F_600, setWindowScan_FI60F_600 }, + + /*fi-65F*/ +/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ + { MODEL_FI65F, 300, 150, 0, 1296, 32, 875, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432, setWindowCoarseCal_FI60F_150, setWindowFineCal_FI60F_150, setWindowSendCal_FI60F_150, sendCal1Header_FI60F_150, sendCal2Header_FI60F_150, setWindowScan_FI60F_150 }, - { MODEL_FI60F, 300, 300, 0, 1296, 32, 1749, 32, 2400, 958, 432, 526, 72, 2400, 432, 958, + { MODEL_FI65F, 300, 300, 0, 1296, 32, 1749, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432, setWindowCoarseCal_FI60F_300, setWindowFineCal_FI60F_300, setWindowSendCal_FI60F_300, sendCal1Header_FI60F_300, sendCal2Header_FI60F_300, setWindowScan_FI60F_300 }, - { MODEL_FI60F, 600, 600, 0, 2592, 32, 3498, 32, 2848, 978, 864, 114, 61, 2848, 864, 978, + { MODEL_FI65F, 600, 600, 0, 2592, 32, 3498, 32, 2848*3, 978*3, 864, 61, 2848*3, 978*3, 864, setWindowCoarseCal_FI60F_600, setWindowFineCal_FI60F_600, setWindowSendCal_FI60F_600, sendCal1Header_FI60F_600, sendCal2Header_FI60F_600, setWindowScan_FI60F_600 }, - { MODEL_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /*S1100 USB*/ +/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ + { MODEL_S1100, 300, 300, 1, 2592, 32, 5324, 32, 8912, 3160, 2592, 58, 8912, 3160, 2592, + setWindowCoarseCal_S1100_300_U, setWindowFineCal_S1100_300_U, + setWindowSendCal_S1100_300_U, sendCal1Header_S1100_300_U, + sendCal2Header_S1100_300_U, setWindowScan_S1100_300_U }, + + { MODEL_S1100, 600, 600, 1, 5184, 32, 10648, 32, 15904, 5360, 5184, 32, 15904, 5360, 5184, + setWindowCoarseCal_S1100_600_U, setWindowFineCal_S1100_600_U, + setWindowSendCal_S1100_600_U, sendCal1Header_S1100_600_U, + sendCal2Header_S1100_600_U, setWindowScan_S1100_600_U }, + + { MODEL_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }, }; @@ -1789,86 +1951,130 @@ change_params(struct scanner *s) do { if(settings[i].model == s->model - && settings[i].x_res == s->resolution_x - && settings[i].usb_power == s->usb_power){ - - /*pull in closest y resolution*/ - s->resolution_y = settings[i].y_res; - - /*1200 dpi*/ - s->max_x = settings[i].max_x * 1200/s->resolution_x; - s->min_x = settings[i].min_x * 1200/s->resolution_x; - s->max_y = settings[i].max_y * 1200/s->resolution_y; - s->min_y = settings[i].min_y * 1200/s->resolution_y; + && settings[i].x_res >= s->resolution + && settings[i].y_res >= s->resolution + && settings[i].usb_power == s->usb_power + ){ + break; + } + i++; + } while (settings[i].model); - s->page_width = s->max_x; - s->br_x = s->max_x; - s->br_y = s->max_y; + if (!settings[i].model){ + return SANE_STATUS_INVAL; + } - /*current dpi*/ - s->setWindowCoarseCal = settings[i].sw_coarsecal; - s->setWindowCoarseCalLen = SET_WINDOW_LEN; + /*1200 dpi*/ + s->max_x = PIX_TO_SCANNER_UNIT( settings[i].max_x, settings[i].x_res ); + s->min_x = PIX_TO_SCANNER_UNIT( settings[i].min_x, settings[i].x_res ); + s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, settings[i].y_res ); + s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, settings[i].y_res ); - s->setWindowFineCal = settings[i].sw_finecal; - s->setWindowFineCalLen = SET_WINDOW_LEN; + /* wrong place for this?*/ + s->page_width = s->max_x; + s->br_x = s->max_x; + s->br_y = s->max_y; - s->setWindowSendCal = settings[i].sw_sendcal; - s->setWindowSendCalLen = SET_WINDOW_LEN; + /*current dpi*/ + s->setWindowCoarseCal = settings[i].sw_coarsecal; + s->setWindowCoarseCalLen = SET_WINDOW_LEN; - s->sendCal1Header = settings[i].head_cal1; - s->sendCal1HeaderLen = 14; + s->setWindowFineCal = settings[i].sw_finecal; + s->setWindowFineCalLen = SET_WINDOW_LEN; - s->sendCal2Header = settings[i].head_cal2; - s->sendCal2HeaderLen = 7; + s->setWindowSendCal = settings[i].sw_sendcal; + s->setWindowSendCalLen = SET_WINDOW_LEN; - s->setWindowScan = settings[i].sw_scan; - s->setWindowScanLen = SET_WINDOW_LEN; + s->sendCal1Header = settings[i].head_cal1; + s->sendCal1HeaderLen = 14; - break; - } - i++; - } while (settings[i].model); + s->sendCal2Header = settings[i].head_cal2; + s->sendCal2HeaderLen = 7; - if (!settings[i].model) - { - return SANE_STATUS_INVAL; - } + s->setWindowScan = settings[i].sw_scan; + s->setWindowScanLen = SET_WINDOW_LEN; - if (s->model == MODEL_S300) + if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { img_heads = 1; /* image width is the same as the plane width on the S300 */ img_pages = 2; } - else /* (s->model == MODEL_FI60F) */ + else if (s->model == MODEL_S1100) + { + img_heads = 1; /* image width is the same as the plane width on the S1000 */ + img_pages = 1; + } + else /* MODEL_FI60F or MODEL_FI65F */ { img_heads = 3; /* image width is 3* the plane width on the FI-60F */ img_pages = 1; } + + /* height */ + if (s->tl_y > s->max_y - s->min_y) + s->tl_y = s->max_y - s->min_y - s->adf_height_padding; + if (s->tl_y + s->page_height > s->max_y - s->adf_height_padding) + s->page_height = s->max_y - s->adf_height_padding - s->tl_y; + if (s->page_height < s->min_y && s->page_height > 0) + s->page_height = s->min_y; + if (s->tl_y + s->page_height > s->max_y) + s->tl_y = s->max_y - s->adf_height_padding - s->page_height ; + + if (s->page_height > 0) { + s->br_y = s->tl_y + s->page_height; + } + else + { + s->br_y = s->max_y; + } + + /*width*/ + if (s->page_width > s->max_x) + s->page_width = s->max_x; + else if (s->page_width < s->min_x) + s->page_width = s->min_x; + s->tl_x = (s->max_x - s->page_width)/2; + s->br_x = (s->max_x + s->page_width)/2; - /* set up the transfer structs */ - s->cal_image.plane_width = settings[i].cal_headwidth; - s->cal_image.plane_stride = settings[i].cal_reqwidth * 3; - s->cal_image.line_stride = settings[i].cal_width * 3; + /*=============================================================*/ + /* set up the calibration structs */ + /* generally full width, short height, full resolution */ + s->cal_image.line_stride = settings[i].cal_line_stride; + s->cal_image.plane_stride = settings[i].cal_plane_stride; + s->cal_image.plane_width = settings[i].cal_plane_width; + s->cal_image.x_res = settings[i].x_res; + s->cal_image.y_res = settings[i].y_res; s->cal_image.raw_data = NULL; s->cal_image.image = NULL; - s->cal_data.plane_width = settings[i].cal_headwidth; /* width is the same, but there are 2 bytes per pixel component */ - s->cal_data.plane_stride = settings[i].cal_reqwidth * 6; - s->cal_data.line_stride = settings[i].cal_width * 6; + /* width is the same, but there are 2 bytes per pixel component */ + s->cal_data.line_stride = settings[i].cal_line_stride * 2; + s->cal_data.plane_stride = settings[i].cal_plane_stride * 2; + s->cal_data.plane_width = settings[i].cal_plane_width; + s->cal_data.x_res = settings[i].x_res; + s->cal_data.y_res = settings[i].y_res; s->cal_data.raw_data = NULL; s->cal_data.image = &s->sendcal; - s->block_xfr.plane_width = settings[i].head_width; - s->block_xfr.plane_stride = settings[i].req_width * 3; - s->block_xfr.line_stride = settings[i].act_width * 3; + /*=============================================================*/ + /* set up the input scan structs */ + s->block_xfr.line_stride = settings[i].line_stride; + s->block_xfr.plane_stride = settings[i].plane_stride; + s->block_xfr.plane_width = settings[i].plane_width; + s->block_xfr.x_res = settings[i].x_res; + s->block_xfr.y_res = settings[i].y_res; s->block_xfr.raw_data = NULL; s->block_xfr.image = &s->block_img; /* set up the block image used during scanning operation */ - width = s->block_xfr.plane_width * img_heads; + /* note that this is the same width/x_res as the final output image */ + /* but the height/y_res are the same as block_xfr */ + width = (s->block_xfr.plane_width*s->resolution/settings[i].x_res) * img_heads; s->block_img.width_pix = width; s->block_img.width_bytes = width * 3; s->block_img.height = settings[i].block_height; + s->block_img.x_res = s->resolution; + s->block_img.y_res = settings[i].y_res; s->block_img.pages = img_pages; s->block_img.buffer = NULL; @@ -1877,6 +2083,8 @@ change_params(struct scanner *s) s->coarsecal.width_pix = s->darkcal.width_pix = s->lightcal.width_pix = width; s->coarsecal.width_bytes = s->darkcal.width_bytes = s->lightcal.width_bytes = width * 3; s->coarsecal.height = 1; + s->coarsecal.x_res = s->darkcal.x_res = s->lightcal.x_res = settings[i].x_res; + s->coarsecal.y_res = s->darkcal.y_res = s->lightcal.y_res = settings[i].y_res; s->darkcal.height = s->lightcal.height = 16; s->coarsecal.pages = s->darkcal.pages = s->lightcal.pages = img_pages; s->coarsecal.buffer = s->darkcal.buffer = s->lightcal.buffer = NULL; @@ -1886,50 +2094,95 @@ change_params(struct scanner *s) s->sendcal.width_pix = width; s->sendcal.width_bytes = width * 6; /* 2 bytes of cal data per pixel component */ s->sendcal.height = 1; + s->sendcal.x_res = settings[i].x_res; + s->sendcal.y_res = settings[i].y_res; s->sendcal.pages = img_pages; s->sendcal.buffer = NULL; /* set up the fullscan parameters */ s->fullscan.width_bytes = s->block_xfr.line_stride; + s->fullscan.x_res = settings[i].x_res; + s->fullscan.y_res = settings[i].y_res; if(s->source == SOURCE_FLATBED || !s->page_height) { /* flatbed and adf in autodetect always ask for all*/ - s->fullscan.height = s->max_y * s->resolution_y / 1200; + s->fullscan.height = SCANNER_UNIT_TO_PIX(s->max_y, s->fullscan.y_res); } else { - /* adf with specified paper size requires padding (~1/2in) */ - s->fullscan.height = (s->page_height+600) * s->resolution_y / 1200; + /* adf with specified paper size requires padding on top of page_height (~1/2in) */ + s->fullscan.height = SCANNER_UNIT_TO_PIX((s->page_height + s->tl_y + s->adf_height_padding), s->fullscan.y_res); } - /* fill in front settings */ + /*=============================================================*/ + /* set up the output image structs */ + /* output image might be different from scan due to interpolation */ + s->front.x_res = s->resolution; + s->front.y_res = s->resolution; + if(s->source == SOURCE_FLATBED) + { + /* flatbed ignores the tly */ + s->front.height = SCANNER_UNIT_TO_PIX(s->max_y - s->tl_y, s->front.y_res); + } + else if(!s->page_height) + { + /* adf in autodetect always asks for all */ + s->front.height = SCANNER_UNIT_TO_PIX(s->max_y, s->front.y_res); + } + else + { + /* adf with specified paper size */ + s->front.height = SCANNER_UNIT_TO_PIX(s->page_height, s->front.y_res); + } s->front.width_pix = s->block_img.width_pix; + s->front.x_start_offset = (s->block_xfr.image->width_pix - s->front.width_pix)/2; switch (s->mode) { case MODE_COLOR: s->front.width_bytes = s->front.width_pix*3; + s->front.x_offset_bytes = s->front.x_start_offset *3; break; case MODE_GRAYSCALE: s->front.width_bytes = s->front.width_pix; + s->front.x_offset_bytes = s->front.x_start_offset; break; default: /*binary*/ s->front.width_bytes = s->front.width_pix/8; + s->front.width_pix = s->front.width_bytes * 8; + /*s->page_width = PIX_TO_SCANNER_UNIT(s->front.width_pix, (img_heads * s->resolution_x));*/ + s->front.x_offset_bytes = s->front.x_start_offset/8; break; } - /*output image might be taller than scan due to interpolation*/ - s->front.height = s->fullscan.height * s->resolution_x / s->resolution_y; + + /* ADF front need to remove padding header */ + if (s->source != SOURCE_FLATBED) + { + s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y+s->adf_height_padding, s->fullscan.y_res); + } + else + { + s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->fullscan.y_res); + } + s->front.pages = 1; s->front.buffer = NULL; /* back settings always same as front settings */ s->back.width_pix = s->front.width_pix; s->back.width_bytes = s->front.width_bytes; + s->back.x_res = s->front.x_res; + s->back.y_res = s->front.y_res; s->back.height = s->front.height; + s->back.x_start_offset = s->front.x_start_offset; + s->back.x_offset_bytes = s->front.x_offset_bytes; + s->back.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->fullscan.y_res); s->back.pages = 1; s->back.buffer = NULL; /* dynamic threshold temp buffer, in gray */ s->dt.width_pix = s->front.width_pix; s->dt.width_bytes = s->front.width_pix; + s->dt.x_res = s->front.x_res; + s->dt.y_res = s->front.y_res; s->dt.height = 1; s->dt.pages = 1; s->dt.buffer = NULL; @@ -2120,7 +2373,7 @@ sane_start (SANE_Handle handle) /* ingest paper with adf */ if( s->source == SOURCE_ADF_BACK || s->source == SOURCE_ADF_FRONT || (s->source == SOURCE_ADF_DUPLEX && s->side == SIDE_FRONT) ){ - ret = ingest(s); + ret = object_position(s,EPJITSU_PAPER_INGEST); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to ingest\n"); sane_cancel((SANE_Handle)s); @@ -2222,6 +2475,9 @@ sane_start (SANE_Handle handle) s->pages[i].bytes_total = page_img->width_bytes * page_img->height; s->pages[i].bytes_scanned = 0; s->pages[i].bytes_read = 0; + s->pages[i].lines_rx = 0; + s->pages[i].lines_pass = 0; + s->pages[i].lines_tx = 0; s->pages[i].done = 0; } @@ -2343,43 +2599,123 @@ setup_buffers(struct scanner *s) */ static SANE_Status -coarsecal(struct scanner *s) +coarsecal_send_cal(struct scanner *s, unsigned char *pay) { SANE_Status ret = SANE_STATUS_GOOD; - - size_t cmdLen = 2; unsigned char cmd[2]; - - size_t statLen = 1; unsigned char stat[1]; + size_t cmdLen,statLen,payLen; + + DBG (5, "coarsecal_send_cal: start\n"); + /* send coarse cal (c6) */ + cmd[0] = 0x1b; + cmd[1] = 0xc6; + cmdLen = 2; + stat[0] = 0; + statLen = 1; + + ret = do_cmd( + s, 0, + cmd, cmdLen, + NULL, 0, + stat, &statLen + ); + if(ret){ + DBG (5, "coarsecal_send_cal: error sending c6 cmd\n"); + return ret; + } + if(stat[0] != 6){ + DBG (5, "coarsecal_send_cal: cmd bad c6 status?\n"); + return SANE_STATUS_IO_ERROR; + } + + /*send coarse cal payload*/ + stat[0] = 0; + statLen = 1; + payLen = 28; - size_t payLen = 28; - unsigned char pay[28]; + ret = do_cmd( + s, 0, + pay, payLen, + NULL, 0, + stat, &statLen + ); + if(ret){ + DBG (5, "coarsecal_send_cal: error sending c6 payload\n"); + return ret; + } + if(stat[0] != 6){ + DBG (5, "coarsecal_send_cal: c6 payload bad status?\n"); + return SANE_STATUS_IO_ERROR; + } - int try_count, cal_good[2], x, i, j; - int param[2], zcount[2], high_param[2], low_param[2], avg[2], maxval[2]; - int rgb_avg[2][3], rgb_hicount[2][3]; + DBG (5, "coarsecal_send_cal: finish\n"); + return ret; +} - DBG (10, "coarsecal: start\n"); +static SANE_Status +coarsecal_get_line(struct scanner *s, struct image *img) +{ + SANE_Status ret = SANE_STATUS_GOOD; + unsigned char cmd[2]; + unsigned char stat[1]; + size_t cmdLen,statLen; - if(s->model == MODEL_S300){ - memcpy(pay,coarseCalData_S300,payLen); - } - else{ - memcpy(pay,coarseCalData_FI60F,payLen); - } + DBG (5, "coarsecal_get_line: start\n"); - /* ask for 1 line */ - ret = set_window(s, WINDOW_COARSECAL); + /* send scan d2 command */ + cmd[0] = 0x1b; + cmd[1] = 0xd2; + cmdLen = 2; + stat[0] = 0; + statLen = 1; + + ret = do_cmd( + s, 0, + cmd, cmdLen, + NULL, 0, + stat, &statLen + ); if(ret){ - DBG (5, "coarsecal: error sending setwindow\n"); + DBG (5, "coarsecal_get_line: error sending d2 cmd\n"); return ret; } + if(stat[0] != 6){ + DBG (5, "coarsecal_get_line: cmd bad d2 status?\n"); + return SANE_STATUS_IO_ERROR; + } + + s->cal_image.image = img; + update_transfer_totals(&s->cal_image); + + while(!s->cal_image.done){ + ret = read_from_scanner(s,&s->cal_image); + if(ret){ + DBG (5, "coarsecal_get_line: cant read from scanner\n"); + return ret; + } + } + /* convert the raw data into normal packed pixel data */ + descramble_raw(s, &s->cal_image); + + DBG (5, "coarsecal_get_line: finish\n"); + return ret; +} + +static SANE_Status +coarsecal_dark(struct scanner *s, unsigned char *pay) +{ + SANE_Status ret = SANE_STATUS_GOOD; + + int try_count, cal_good[2], x, j; + int param[2], zcount[2], high_param[2], low_param[2], avg[2], maxval[2]; + + DBG (5, "coarsecal_dark: start\n"); /* dark cal, lamp off */ ret = lamp(s,0); if(ret){ - DBG (5, "coarsecal: error lamp off\n"); + DBG (5, "coarsecal_dark: error lamp off\n"); return ret; } @@ -2394,93 +2730,23 @@ coarsecal(struct scanner *s) try_count--; /* update the coarsecal payload to use our new dark offset parameters */ - if (s->model == MODEL_S300) + if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { pay[5] = param[0]; pay[7] = param[1]; } - else /* (s->model == MODEL_FI60F) */ + else /* MODEL_S1100 or MODEL_FI60F or MODEL_FI65F */ { pay[5] = param[0]; pay[7] = param[0]; pay[9] = param[0]; } - /* send coarse cal (c6) */ - cmd[0] = 0x1b; - cmd[1] = 0xc6; - stat[0] = 0; - statLen = 1; - - ret = do_cmd( - s, 0, - cmd, cmdLen, - NULL, 0, - stat, &statLen - ); - if(ret){ - DBG (5, "coarsecal: error sending c6 cmd\n"); - return ret; - } - if(stat[0] != 6){ - DBG (5, "coarsecal: cmd bad c6 status?\n"); - return SANE_STATUS_IO_ERROR; - } - - /*send coarse cal payload*/ - stat[0] = 0; - statLen = 1; - - ret = do_cmd( - s, 0, - pay, payLen, - NULL, 0, - stat, &statLen - ); - if(ret){ - DBG (5, "coarsecal: error sending c6 payload\n"); - return ret; - } - if(stat[0] != 6){ - DBG (5, "coarsecal: c6 payload bad status?\n"); - return SANE_STATUS_IO_ERROR; - } + ret = coarsecal_send_cal(s, pay); - DBG(15, "coarsecal offset: parameter front: %i back: %i\n", param[0], param[1]); + DBG(15, "coarsecal_dark offset: parameter front: %i back: %i\n", param[0], param[1]); - /* send scan d2 command */ - cmd[0] = 0x1b; - cmd[1] = 0xd2; - stat[0] = 0; - statLen = 1; - - ret = do_cmd( - s, 0, - cmd, cmdLen, - NULL, 0, - stat, &statLen - ); - if(ret){ - DBG (5, "coarsecal: error sending d2 cmd\n"); - return ret; - } - if(stat[0] != 6){ - DBG (5, "coarsecal: cmd bad d2 status?\n"); - return SANE_STATUS_IO_ERROR; - } - - s->cal_image.image = &s->coarsecal; - update_transfer_totals(&s->cal_image); - - while(!s->cal_image.done){ - ret = read_from_scanner(s,&s->cal_image); - if(ret){ - DBG (5, "coarsecal: cant read from scanner\n"); - return ret; - } - } - /* convert the raw data into normal packed pixel data */ - descramble_raw(s, &s->cal_image); + ret = coarsecal_get_line(s, &s->coarsecal); /* gather statistics: count the proportion of 0-valued pixels */ /* since the lamp is off, there's no point in looking at the green or blue data - they're all from the same sensor anyway */ @@ -2504,9 +2770,9 @@ coarsecal(struct scanner *s) avg[j] /= s->coarsecal.width_bytes; zcount[j] = zcount[j] * 1000 / s->coarsecal.width_bytes; } - DBG(15, "coarsecal offset: average pixel values front: %i back: %i\n", avg[0], avg[1]); - DBG(15, "coarsecal offset: maximum pixel values front: %i back: %i\n", maxval[0], maxval[1]); - DBG(15, "coarsecal offset: 0-valued pixel count front: %f%% back: %f%%\n", zcount[0] / 10.0f, zcount[1] / 10.0f); + DBG(15, "coarsecal_dark offset: average pixel values front: %i back: %i\n", avg[0], avg[1]); + DBG(15, "coarsecal_dark offset: maximum pixel values front: %i back: %i\n", maxval[0], maxval[1]); + DBG(15, "coarsecal_dark offset: 0-valued pixel count front: %f%% back: %f%%\n", zcount[0] / 10.0f, zcount[1] / 10.0f); /* check the values, adjust parameters if they are not within the target range */ for (j = 0; j < s->coarsecal.pages; j++) @@ -2530,10 +2796,25 @@ coarsecal(struct scanner *s) } /* continue looping for up to 8 tries */ + DBG (5, "coarsecal_dark: finish\n"); + return ret; +} + +static SANE_Status +coarsecal_light(struct scanner *s, unsigned char *pay) +{ + SANE_Status ret = SANE_STATUS_GOOD; + + int try_count, cal_good[2], x, i, j; + int param[2], zcount[2], high_param[2], low_param[2], avg[2]; + int rgb_avg[2][3], rgb_hicount[2][3]; + + DBG (5, "coarsecal_light: start\n"); + /* light cal, lamp on */ ret = lamp(s,1); if(ret){ - DBG (5, "coarsecal: error lamp on\n"); + DBG (5, "coarsecal_light: error lamp on\n"); return ret; } @@ -2547,82 +2828,12 @@ coarsecal(struct scanner *s) while (try_count > 0){ try_count--; - /* send coarse cal (c6) */ - cmd[0] = 0x1b; - cmd[1] = 0xc6; - stat[0] = 0; - statLen = 1; - - ret = do_cmd( - s, 0, - cmd, cmdLen, - NULL, 0, - stat, &statLen - ); - if(ret){ - DBG (5, "coarsecal: error sending c6 cmd\n"); - return ret; - } - if(stat[0] != 6){ - DBG (5, "coarsecal: cmd bad c6 status?\n"); - return SANE_STATUS_IO_ERROR; - } - - /*send coarse cal payload*/ - stat[0] = 0; - statLen = 1; - - ret = do_cmd( - s, 0, - pay, payLen, - NULL, 0, - stat, &statLen - ); - if(ret){ - DBG (5, "coarsecal: error sending c6 payload\n"); - return ret; - } - if(stat[0] != 6){ - DBG (5, "coarsecal: c6 payload bad status?\n"); - return SANE_STATUS_IO_ERROR; - } - - DBG(15, "coarsecal gain: parameter front: %i back: %i\n", param[0], param[1]); + ret = coarsecal_send_cal(s, pay); - /* send scan d2 command */ - cmd[0] = 0x1b; - cmd[1] = 0xd2; - stat[0] = 0; - statLen = 1; - - ret = do_cmd( - s, 0, - cmd, cmdLen, - NULL, 0, - stat, &statLen - ); - if(ret){ - DBG (5, "coarsecal: error sending d2 cmd\n"); - return ret; - } - if(stat[0] != 6){ - DBG (5, "coarsecal: cmd bad d2 status?\n"); - return SANE_STATUS_IO_ERROR; - } + DBG(15, "coarsecal_light gain: parameter front: %i back: %i\n", param[0], param[1]); - s->cal_image.image = &s->coarsecal; - update_transfer_totals(&s->cal_image); + ret = coarsecal_get_line(s, &s->coarsecal); - while(!s->cal_image.done){ - ret = read_from_scanner(s,&s->cal_image); - if(ret){ - DBG (5, "coarsecal: cant read from scanner\n"); - return ret; - } - } - /* convert the raw data into normal packed pixel data */ - descramble_raw(s, &s->cal_image); - /* gather statistics: count the proportion of 255-valued pixels in each color channel */ /* count the average pixel value in each color channel */ for (i = 0; i < s->coarsecal.pages; i++) @@ -2645,7 +2856,7 @@ coarsecal(struct scanner *s) /* apply the color correction factors to the averages */ for (i = 0; i < s->coarsecal.pages; i++) for (j = 0; j < 3; j++) - rgb_avg[i][j] *= white_factor[j]; + rgb_avg[i][j] *= s->white_factor[j]; /* set the gain so that none of the color channels are clipping, ie take the highest channel values */ for (i = 0; i < s->coarsecal.pages; i++) { @@ -2662,9 +2873,9 @@ coarsecal(struct scanner *s) } zcount[i] = MAX3(rgb_hicount[i][0], rgb_hicount[i][1], rgb_hicount[i][2]); } - DBG(15, "coarsecal gain: average RGB values front: (%i,%i,%i) back: (%i,%i,%i)\n", + DBG(15, "coarsecal_light gain: average RGB values front: (%i,%i,%i) back: (%i,%i,%i)\n", rgb_avg[0][0], rgb_avg[0][1], rgb_avg[0][2], rgb_avg[1][0], rgb_avg[1][1], rgb_avg[1][2]); - DBG(15, "coarsecal gain: 255-valued pixel count front: (%g,%g,%g) back: (%g,%g,%g)\n", + DBG(15, "coarsecal_light gain: 255-valued pixel count front: (%g,%g,%g) back: (%g,%g,%g)\n", rgb_hicount[0][0]/10.0f, rgb_hicount[0][1]/10.0f, rgb_hicount[0][2]/10.0f, rgb_hicount[1][0]/10.0f, rgb_hicount[1][1]/10.0f, rgb_hicount[1][2]/10.0f); @@ -2689,12 +2900,12 @@ coarsecal(struct scanner *s) if (cal_good[0] + cal_good[1] == s->coarsecal.pages) break; /* update the coarsecal payload to use the new gain parameters */ - if (s->model == MODEL_S300) + if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { pay[11] = param[0]; pay[13] = param[1]; } - else /* (s->model == MODEL_FI60F) */ + else /* MODEL_S1100 or MODEL_FI60F or MODEL_FI65F */ { pay[11] = param[0]; pay[13] = param[0]; @@ -2702,6 +2913,49 @@ coarsecal(struct scanner *s) } } + DBG (5, "coarsecal_light: finish\n"); + return ret; +} + +static SANE_Status +coarsecal(struct scanner *s) +{ + SANE_Status ret = SANE_STATUS_GOOD; + unsigned char pay[28]; + size_t payLen; + + DBG (10, "coarsecal: start\n"); + + payLen = sizeof(pay); + + if(s->model == MODEL_S300){ + memcpy(pay,coarseCalData_S300,payLen); + } + else if(s->model == MODEL_S1300i){ + memcpy(pay,coarseCalData_S1300i,payLen); + } + else if(s->model == MODEL_S1100){ + memcpy(pay,coarseCalData_S1100,payLen); + } + else{ + memcpy(pay,coarseCalData_FI60F,payLen); + } + + /* ask for 1 line */ + ret = set_window(s, WINDOW_COARSECAL); + if(ret){ + DBG (5, "coarsecal: error sending setwindow\n"); + return ret; + } + + if(s->model == MODEL_S1100){ + ret = coarsecal_send_cal(s, pay); + } + else{ + ret = coarsecal_dark(s, pay); + ret = coarsecal_light(s, pay); + } + DBG (10, "coarsecal: finish\n"); return ret; } @@ -2718,18 +2972,63 @@ finecal_send_cal(struct scanner *s) unsigned char stat[2]; int i, j, k; - unsigned short *p_out, *p_in = (unsigned short *) s->sendcal.buffer; - int planes = (s->model == MODEL_S300) ? 2 : 3; + unsigned char *p_out, *p_in = s->sendcal.buffer; + int planes; + + if(s->model == MODEL_FI60F || s->model == MODEL_FI65F) + planes = 3; + if(s->model == MODEL_S300 || s->model == MODEL_S1300i) + planes = 2; /* scramble the raster buffer data into scanner raw format */ + /* this is reverse of descramble_raw */ memset(s->cal_data.raw_data, 0, s->cal_data.line_stride); - for (i = 0; i < planes; i++) + + if(s->model == MODEL_S1100){ + planes = 1; + + for (k = 0; k < s->sendcal.width_pix; k++){ /* column (x) */ + + /* input is RrGgBb (capital is offset, small is gain) */ + /* output is Bb...BbRr...RrGg...Gg*/ + + /*red*/ + p_out = s->cal_data.raw_data + s->cal_data.plane_stride + k*2; + *p_out = *p_in; + p_out++; + p_in++; + *p_out = *p_in; + p_in++; + + /*green*/ + p_out = s->cal_data.raw_data + 2*s->cal_data.plane_stride + k*2; + *p_out = *p_in; + p_out++; + p_in++; + *p_out = *p_in; + p_in++; + + /*blue*/ + p_out = s->cal_data.raw_data + k*2; + *p_out = *p_in; + p_out++; + p_in++; + *p_out = *p_in; + p_in++; + } + } + + else{ + for (i = 0; i < planes; i++) for (j = 0; j < s->cal_data.plane_width; j++) for (k = 0; k < 3; k++) { - p_out = (unsigned short *) (s->cal_data.raw_data + k * s->cal_data.plane_stride + j * 6 + i * 2); - *p_out = *p_in++; /* dark offset, gain */ + p_out = (s->cal_data.raw_data + k * s->cal_data.plane_stride + j * 6 + i * 2); + *p_out = *p_in++; /* dark offset */ + p_out++; + *p_out = *p_in++; /* gain */ } + } ret = set_window(s, WINDOW_SENDCAL); if(ret){ @@ -2906,13 +3205,21 @@ finecal(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; - const int max_pages = (s->model == MODEL_S300 ? 2 : 1); + int max_pages; int gain_delta = 0xff - 0xbf; float *gain_slope, *last_error; int i, j, k, idx, try_count, cal_good; DBG (10, "finecal: start\n"); + if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { /* S300, S1300 */ + max_pages = 2; + } + else /* fi-60f, S1100 */ + { + max_pages = 1; + } + /* set fine dark offset to 0 and fix all fine gains to lowest parameter (0xFF) */ for (i = 0; i < s->sendcal.width_bytes * s->sendcal.pages / 2; i++) { @@ -3008,7 +3315,7 @@ finecal(struct scanner *s) for (k = 0; k < 3; k++) { int pixvalue = s->lightcal.buffer[idx]; - float pixerror = (fine_gain_target[i] * white_factor[k] - pixvalue); + float pixerror = (fine_gain_target[i] * s->white_factor[k] - pixvalue); int oldgain = s->sendcal.buffer[idx * 2 + 1]; int newgain; /* if we overshot the last correction, reduce the gain_slope */ @@ -3084,6 +3391,9 @@ finecal(struct scanner *s) return ret; } +/* + * set scanner lamp brightness + */ static SANE_Status lamp(struct scanner *s, unsigned char set) { @@ -3247,16 +3557,36 @@ send_lut (struct scanner *s) size_t cmdLen = 2; unsigned char stat[1]; size_t statLen = 1; - unsigned char out[0x6000]; - size_t outLen = 0x6000; + unsigned char *out; + size_t outLen; int i, j; double b, slope, offset; - int width = outLen / 6; /* 3 colors, 2 bytes */ - int height = width; /* square table */ + int width; + int height; DBG (10, "send_lut: start\n"); + if (s->model == MODEL_S1100){ + outLen = 0x200; + width = outLen / 2; /* 1 color, 2 bytes */ + height = width; /* square table */ + } + else if (s->model == MODEL_FI65F){ + outLen = 0x600; + width = outLen / 6; /* 3 color, 2 bytes */ + height = width; /* square table */ + } + else { + outLen = 0x6000; + width = outLen / 6; /* 3 colors, 2 bytes */ + height = width; /* square table */ + } + out = ( unsigned char *)malloc(outLen*sizeof(unsigned char)); + if (out == NULL){ + return SANE_STATUS_NO_MEM; + } + /* contrast is converted to a slope [0,90] degrees: * first [-127,127] to [0,254] then to [0,1] * then multiply by PI/2 to convert to radians @@ -3287,18 +3617,38 @@ send_lut (struct scanner *s) if(j>(height-1)){ j=height-1; } - - /*first table, le order*/ - out[i*2] = j & 0xff; - out[i*2+1] = (j >> 8) & 0x0f; - /*second table, le order*/ - out[width*2 + i*2] = j & 0xff; - out[width*2 + i*2+1] = (j >> 8) & 0x0f; - - /*third table, le order*/ - out[width*4 + i*2] = j & 0xff; - out[width*4 + i*2+1] = (j >> 8) & 0x0f; + if (s->model == MODEL_S1100){ + /*only one table, be order*/ + out[i*2] = (j >> 8) & 0xff; + out[i*2+1] = j & 0xff; + } + else if (s->model == MODEL_FI65F){ + /*first table, be order*/ + out[i*2] = (j >> 8) & 0xff; + out[i*2+1] = j & 0xff; + + /*second table, be order*/ + out[width*2 + i*2] = (j >> 8) & 0xff; + out[width*2 + i*2+1] = j & 0xff; + + /*third table, be order*/ + out[width*4 + i*2] = (j >> 8) & 0xff; + out[width*4 + i*2+1] = j & 0xff; + } + else { + /*first table, le order*/ + out[i*2] = j & 0xff; + out[i*2+1] = (j >> 8) & 0x0f; + + /*second table, le order*/ + out[width*2 + i*2] = j & 0xff; + out[width*2 + i*2+1] = (j >> 8) & 0x0f; + + /*third table, le order*/ + out[width*4 + i*2] = j & 0xff; + out[width*4 + i*2+1] = (j >> 8) & 0x0f; + } } ret = do_cmd( @@ -3386,11 +3736,10 @@ get_hardware_status (struct scanner *s) } static SANE_Status -ingest(struct scanner *s) +object_position(struct scanner *s, int ingest) { SANE_Status ret = SANE_STATUS_GOOD; int i; - unsigned char cmd[2]; size_t cmdLen = sizeof(cmd); unsigned char stat[1]; @@ -3398,10 +3747,11 @@ ingest(struct scanner *s) unsigned char pay[2]; size_t payLen = sizeof(pay); - DBG (10, "ingest: start\n"); + DBG (10, "object_position: start\n"); - for(i=0;i<5;i++){ - + i = (ingest)?5:1; + + while(i--){ /*send paper load cmd*/ cmd[0] = 0x1b; cmd[1] = 0xd4; @@ -3414,18 +3764,18 @@ ingest(struct scanner *s) stat, &statLen ); if(ret){ - DBG (5, "ingest: error sending cmd\n"); + DBG (5, "object_position: error sending cmd\n"); return ret; } if(stat[0] != 6){ - DBG (5, "ingest: cmd bad status? %d\n",stat[0]); + DBG (5, "object_position: cmd bad status? %d\n",stat[0]); continue; } /*send payload*/ statLen = 1; payLen = 1; - pay[0] = 1; + pay[0] = ingest; ret = do_cmd( s, 0, @@ -3434,25 +3784,25 @@ ingest(struct scanner *s) stat, &statLen ); if(ret){ - DBG (5, "ingest: error sending payload\n"); + DBG (5, "object_position: error sending payload\n"); return ret; } if(stat[0] == 6){ - DBG (5, "ingest: found paper?\n"); + DBG (5, "object_position: found paper?\n"); break; } else if(stat[0] == 0x15 || stat[0] == 0){ - DBG (5, "ingest: no paper?\n"); + DBG (5, "object_position: no paper?\n"); ret=SANE_STATUS_NO_DOCS; continue; } else{ - DBG (5, "ingest: payload bad status?\n"); + DBG (5, "object_position: payload bad status?\n"); return SANE_STATUS_IO_ERROR; } } - DBG (10, "ingest: finish\n"); + DBG (10, "object_position: finish\n"); return ret; } @@ -3467,7 +3817,7 @@ scan(struct scanner *s) DBG (10, "scan: start\n"); - if(s->model == MODEL_S300){ + if(s->model == MODEL_S300 || s->model == MODEL_S1100 || s->model == MODEL_S1300i){ cmd[1] = 0xd6; } @@ -3525,9 +3875,29 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len page = &s->pages[s->side]; /* have sent all of current buffer */ - if(page->done){ + if(s->fullscan.done && page->done){ DBG (10, "sane_read: returning eof\n"); - return SANE_STATUS_EOF; + + /*S1100 needs help to turn off button*/ + if(s->model == MODEL_S1100){ + usleep(15000); + + /* eject paper */ + ret = object_position(s,EPJITSU_PAPER_EJECT); + if (ret != SANE_STATUS_GOOD && ret != SANE_STATUS_NO_DOCS) { + DBG (5, "sane_read: ERROR: failed to eject\n"); + return ret; + } + + /* reset flashing button? */ + ret = six5(s); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "sane_read: ERROR: failed to six5\n"); + return ret; + } + } + + return SANE_STATUS_EOF; } /* scan not finished, get more into block buffer */ @@ -3543,8 +3913,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len DBG (15, "sane_read: shrinking block to %lu\n", (unsigned long)remainTotal); s->block_xfr.total_bytes = remainTotal; } - /* send d3 cmd for S300 */ - if(s->model == MODEL_S300) + /* send d3 cmd for S300, S1100, S1300 */ + if(s->model == MODEL_S300 || s->model == MODEL_S1100 || s->model == MODEL_S1300i) { unsigned char cmd[] = {0x1b, 0xd3}; size_t cmdLen = 2; @@ -3586,8 +3956,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len s->block_xfr.done = 0; - /* get the 0x43 cmd for the S300 */ - if(s->model == MODEL_S300){ + /* get the 0x43 cmd for the S300, S1100, S1300 */ + if(s->model == MODEL_S300 || s->model == MODEL_S1100 || s->model == MODEL_S1300i){ unsigned char cmd[] = {0x1b, 0x43}; size_t cmdLen = 2; @@ -3672,7 +4042,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len page->bytes_read += *len; /* sent it all, return eof on next read */ - if(s->fullscan.done && page->bytes_read == page->bytes_scanned){ + if(page->bytes_read == page->bytes_scanned && s->fullscan.done){ DBG (10, "sane_read: side done\n"); page->done = 1; } @@ -3683,36 +4053,180 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len return ret; } +static SANE_Status +six5 (struct scanner *s) +{ + SANE_Status ret = SANE_STATUS_GOOD; + + unsigned char cmd[2]; + size_t cmdLen = sizeof(cmd); + unsigned char stat[1]; + size_t statLen = sizeof(stat); + + DBG (10, "six5: start\n"); + + cmd[0] = 0x1b; + cmd[1] = 0x65; + statLen = 1; + + ret = do_cmd( + s, 0, + cmd, cmdLen, + NULL, 0, + stat, &statLen + ); + if(ret){ + DBG (5, "six5: error sending cmd\n"); + return ret; + } + if(stat[0] != 6){ + DBG (5, "six5: cmd bad status? %d\n",stat[0]); + return SANE_STATUS_IO_ERROR; + } + + DBG (10, "six5: finish\n"); + + return ret; +} + /* de-scrambles the raw data from the scanner into the image buffer */ +/* the output image might be lower dpi than input image, so we scale horizontally */ static SANE_Status descramble_raw(struct scanner *s, struct transfer * tp) { SANE_Status ret = SANE_STATUS_GOOD; - unsigned char *p_in, *p_out = tp->image->buffer; + unsigned char *p_out = tp->image->buffer; int height = tp->total_bytes / tp->line_stride; - int i, j, k, l; + int i, j, k; - if (s->model == MODEL_S300) - { - for (i = 0; i < 2; i++) /* page, front/back */ - for (j = 0; j < height; j++) /* row (y)*/ - for (k = 0; k < tp->plane_width; k++) /* column (x) */ - for (l = 0; l < 3; l++) /* color component */ - { - p_in = (unsigned char *) tp->raw_data + (j * tp->line_stride) + (l * tp->plane_stride) + k * 3 + i; - *p_out++ = *p_in; - } + if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { + for (i = 0; i < 2; i++){ /* page, front/back */ + for (j = 0; j < height; j++){ /* row (y)*/ + int curr_col = 0; + int r=0, g=0, b=0, ppc=0; + + for (k = 0; k <= tp->plane_width; k++){ /* column (x) */ + int this_col = k*tp->image->x_res/tp->x_res; + + /* going to change output pixel, dump rgb and reset */ + if(ppc && curr_col != this_col){ + *p_out = r/ppc; + p_out++; + + *p_out = g/ppc; + p_out++; + + *p_out = b/ppc; + p_out++; + + r = g = b = ppc = 0; + + curr_col = this_col; + } + + if(k == tp->plane_width || this_col >= tp->image->width_pix){ + break; + } + + /*red is first*/ + r += tp->raw_data[j*tp->line_stride + k*3 + i]; + + /*green is second*/ + g += tp->raw_data[j*tp->line_stride + tp->plane_stride + k*3 + i]; + + /*blue is third*/ + b += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k*3 + i]; + + ppc++; + } + } + } } - else /* MODEL_FI60F */ - { - for (i = 0; i < height; i++) /* row (y)*/ - for (j = 0; j < 3; j++) /* read head */ - for (k = 0; k < tp->plane_width; k++) /* column within the read head */ - for (l = 0; l < 3; l++) /* color component */ - { - p_in = (unsigned char *) tp->raw_data + (i * tp->line_stride) + (l * tp->plane_stride) + k * 3 + j; - *p_out++ = *p_in; - } + else if (s->model == MODEL_S1100){ + for (j = 0; j < height; j++){ /* row (y)*/ + int curr_col = 0; + int r=0, g=0, b=0, ppc=0; + + for (k = 0; k <= tp->plane_width; k++){ /* column (x) */ + int this_col = k*tp->image->x_res/tp->x_res; + + /* going to change output pixel, dump rgb and reset */ + if(ppc && curr_col != this_col){ + *p_out = r/ppc; + p_out++; + + *p_out = g/ppc; + p_out++; + + *p_out = b/ppc; + p_out++; + + r = g = b = ppc = 0; + + curr_col = this_col; + } + + if(k == tp->plane_width || this_col >= tp->image->width_pix){ + break; + } + + /*red is second*/ + r += tp->raw_data[j*tp->line_stride + tp->plane_stride + k]; + + /*green is third*/ + g += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k]; + + /*blue is first*/ + b += tp->raw_data[j*tp->line_stride + k]; + + ppc++; + } + } + } + else { /* MODEL_FI60F or MODEL_FI65F */ + + for (j = 0; j < height; j++){ /* row (y)*/ + int curr_col = 0; + + for (i = 0; i < 3; i++){ /* read head */ + int r=0, g=0, b=0, ppc=0; + + for (k = 0; k <= tp->plane_width; k++){ /* column (x) within the read head */ + int this_col = (k+i*tp->plane_width)*tp->image->x_res/tp->x_res; + + /* going to change output pixel, dump rgb and reset */ + if(ppc && curr_col != this_col){ + *p_out = r/ppc; + p_out++; + + *p_out = g/ppc; + p_out++; + + *p_out = b/ppc; + p_out++; + + r = g = b = ppc = 0; + + curr_col = this_col; + } + + if(k == tp->plane_width || this_col >= tp->image->width_pix){ + break; + } + + /*red is first*/ + r += tp->raw_data[j*tp->line_stride + k*3 + i]; + + /*green is second*/ + g += tp->raw_data[j*tp->line_stride + tp->plane_stride + k*3 + i]; + + /*blue is third*/ + b += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k*3 + i]; + + ppc++; + } + } + } } return ret; @@ -3725,9 +4239,11 @@ read_from_scanner(struct scanner *s, struct transfer * tp) SANE_Status ret=SANE_STATUS_GOOD; size_t bytes = MAX_IMG_PASS; size_t remainBlock = tp->total_bytes - tp->rx_bytes + 8; - - /* determine amount to ask for */ - if(bytes > remainBlock){ + unsigned char * buf; + size_t bufLen; + + /* determine amount to ask for, S1300i wants big requests */ + if(bytes > remainBlock && s->model != MODEL_S1300i){ bytes = remainBlock; } @@ -3745,70 +4261,141 @@ read_from_scanner(struct scanner *s, struct transfer * tp) return SANE_STATUS_INVAL; } + bufLen = bytes; + buf = malloc(bufLen); + if(!buf){ + DBG (5, "read_from_scanner: failed to alloc mem\n"); + return SANE_STATUS_NO_MEM; + } + ret = do_cmd( s, 0, NULL, 0, NULL, 0, - tp->raw_data + tp->rx_bytes, &bytes + buf, &bytes ); - + /* full read or short read */ if (ret == SANE_STATUS_GOOD || (ret == SANE_STATUS_EOF && bytes) ) { DBG(15,"read_from_scanner: got GOOD/EOF (%lu)\n",(unsigned long)bytes); + if(bytes > remainBlock){ + DBG(15,"read_from_scanner: block too big?\n"); + bytes = remainBlock; + } + if(bytes == remainBlock){ DBG(15,"read_from_scanner: block done, ignoring trailer\n"); bytes -= 8; tp->done = 1; } - ret = SANE_STATUS_GOOD; + memcpy(tp->raw_data + tp->rx_bytes, buf, bytes); tp->rx_bytes += bytes; + + ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_scanner: error reading status = %d\n", ret); } - + + free(buf); + DBG (10, "read_from_scanner: finish rB:%lu len:%lu\n", - (unsigned long)(tp->total_bytes - tp->rx_bytes), (unsigned long)bytes); + (unsigned long)(tp->total_bytes - tp->rx_bytes + 8), (unsigned long)bytes); return ret; } /* copies block buffer into front or back image buffer */ /* converts pixel data from RGB Color to the output format */ +/* the output image might be lower dpi than input image, so we scale vertically */ static SANE_Status copy_block_to_page(struct scanner *s,int side) { SANE_Status ret = SANE_STATUS_GOOD; struct transfer * block = &s->block_xfr; struct page * page = &s->pages[side]; - int height = block->total_bytes / block->line_stride; - int width = block->image->width_pix; + int image_height = block->total_bytes / block->line_stride; + int page_height = SCANNER_UNIT_TO_PIX(s->page_height, s->resolution); + int page_width = page->image->width_pix; int block_page_stride = block->image->width_bytes * block->image->height; - int page_y_offset = page->bytes_scanned / page->image->width_bytes; - int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F); - int i,j; + int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F) || (s->model == MODEL_FI65F); + int i,j,k=0,l=0; + + int curr_in_row = s->fullscan.rx_bytes/s->fullscan.width_bytes; + int last_out_row = (page->bytes_scanned / page->image->width_bytes) - 1; DBG (10, "copy_block_to_page: start\n"); + /* skip padding and tl_y */ + if (s->fullscan.rx_bytes + s->block_xfr.rx_bytes < block->line_stride * page->image->y_skip_offset) + { + DBG (10, "copy_block_to_page: before the start? %d\n", side); + return ret; + } + else if (s->fullscan.rx_bytes < block->line_stride * page->image->y_skip_offset) + { + k = page->image->y_skip_offset - s->fullscan.rx_bytes / block->line_stride; + DBG (10, "copy_block_to_page: k start? %d\n", k); + } + + /* skip trailer */ + if (s->page_height) + { + DBG (10, "copy_block_to_page: ph %d\n", s->page_height); + if (s->fullscan.rx_bytes > block->line_stride * page->image->y_skip_offset + page_height * block->line_stride) + { + DBG (10, "copy_block_to_page: off the end? %d\n", side); + return ret; + } + else if (s->fullscan.rx_bytes + s->block_xfr.rx_bytes + > block->line_stride * page->image->y_skip_offset + page_height * block->line_stride) + { + l = (s->fullscan.rx_bytes + s->block_xfr.rx_bytes) / block->line_stride + - page_height - page->image->y_skip_offset; + } + } + /* loop over all the lines in the block */ - for (i = 0; i < height; i++) + for (i = k; i < image_height-l; i++) { - unsigned char * p_in = block->image->buffer + (side * block_page_stride) + (i * block->image->width_bytes); - unsigned char * p_out = page->image->buffer + ((i + page_y_offset) * page->image->width_bytes); + /* determine source and dest rows (dpi scaling) */ + int this_in_row = curr_in_row + i; + int this_out_row = (this_in_row - page->image->y_skip_offset) * page->image->y_res / s->fullscan.y_res; + DBG (15, "copy_block_to_page: in %d out %d lastout %d\n", this_in_row, this_out_row, last_out_row); + DBG (15, "copy_block_to_page: bs %d wb %d\n", page->bytes_scanned, page->image->width_bytes); + + /* don't walk off the end of the output buffer */ + if(this_out_row >= page->image->height || this_out_row < 0){ + DBG (10, "copy_block_to_page: out of space? %d\n", side); + DBG (10, "copy_block_to_page: rx:%d tx:%d tot:%d line:%d\n", + page->bytes_scanned, page->bytes_read, page->bytes_total,page->image->width_bytes); + return ret; + } + + /* ok, different output row, so we do the math */ + if(this_out_row > last_out_row){ + + unsigned char * p_in = block->image->buffer + (side * block_page_stride) + + (i * block->image->width_bytes) + page->image->x_start_offset * 3; + unsigned char * p_out = page->image->buffer + this_out_row * page->image->width_bytes; unsigned char * lineStart = p_out; + + last_out_row = this_out_row; + /* reverse order for back side or FI-60F scanner */ if (line_reverse) - p_in += (width - 1) * 3; + p_in += (page_width - 1) * 3; + /* convert all of the pixels in this row */ - for (j = 0; j < width; j++) + for (j = 0; j < page_width; j++) { unsigned char r, g, b; - if (s->model == MODEL_S300) + if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { r = p_in[1]; g = p_in[2]; b = p_in[0]; } - else /* (s->model == MODEL_FI60F) */ + else /* MODEL_FI60F or MODEL_FI65F or MODEL_S1100 */ { r = p_in[0]; g = p_in[1]; b = p_in[2]; } if (s->mode == MODE_COLOR) { @@ -3822,28 +4409,28 @@ copy_block_to_page(struct scanner *s,int side) } else if (s->mode == MODE_LINEART) { - s->dt.buffer[j] = (r + g + b) / 3; + s->dt.buffer[j] = (r + g + b) / 3; /* stores dt temp image buffer and binarize afterword */ } if (line_reverse) p_in -= 3; else p_in += 3; } - /* for MODE_LINEART, binarize the gray line stored in the temp image buffer */ + + /* skip non-transfer pixels in block image buffer */ + if (line_reverse) + p_in -= page->image->x_offset_bytes; + else + p_in += page->image->x_offset_bytes; + + /* for MODE_LINEART, binarize the gray line stored in the temp image buffer(dt) */ + /* bacause dt.width = page_width, we pass page_width */ if (s->mode == MODE_LINEART) - binarize_line(s, lineStart, width); - /*add a periodic row because of non-square pixels*/ - /*FIXME: only works with 225x200*/ - if (s->resolution_x > s->resolution_y && (i + page_y_offset) % 9 == 8) - { - memcpy(lineStart + page->image->width_bytes, lineStart, page->image->width_bytes); - page_y_offset += 1; - page->bytes_scanned += page->image->width_bytes; - } - } + binarize_line(s, lineStart, page_width); - /* update the page counter of bytes scanned */ - page->bytes_scanned += page->image->width_bytes * height; + page->bytes_scanned += page->image->width_bytes; + } + } DBG (10, "copy_block_to_page: finish\n"); @@ -3858,7 +4445,7 @@ binarize_line(struct scanner *s, unsigned char *lineOut, int width) int j, windowX, sum = 0; /* ~1mm works best, but the window needs to have odd # of pixels */ - windowX = 6 * s->resolution_x / 150; + windowX = 6 * s->resolution / 150; if (!(windowX % 2)) windowX++; /*second, prefill the sliding sum*/ diff --git a/backend/epjitsu.conf.in b/backend/epjitsu.conf.in index cabe6b2..155befc 100644 --- a/backend/epjitsu.conf.in +++ b/backend/epjitsu.conf.in @@ -17,6 +17,35 @@ # find them. They should be ~65K, and have the scanner's name as part of the # file name. They are often inside a .cab file. +# To extract .nal files from cabinet files on Linux, use the following steps: +# (you need the "unshield" tool, which is - in Debian - in the unshield package) +# +# 1) Mount the ScanSnap installation DVD +# (mount point e.g. /media/dvd) +# +# 2) Extract the .nal files c$ from the cabinet files on the DVD +# using the following shell script: +# +# # loop over all cabinet files found on the DVD +# for cab in $(find /media/dvd/ -name \*.cab); do +# # search for .nal files in the cabinet files +# nalinfo=$(unshield l $cab | grep '\.nal$') +# +# # we found something +# if [ -n "$nalinfo" ]; then +# #echo -e "=== $cab ===\n$nalinfo" +# +# # loop over all fields in $nalinfo +# for nal in $nalinfo; do +# # if the element of $nalinfo is a .nal file name +# if echo "$nal" | grep -q '\.nal$' - 2>/dev/null; then +# # extract .nal file form the cabinet file +# unshield x "$cab" "${nal##*\\}" +# fi +# done +# fi +# done + # Copy the file someplace sane can reach it. Then update the line below. # NOTE: the firmware line must occur BEFORE the usb line for your scanner @@ -32,6 +61,14 @@ usb 0x04c5 0x1156 firmware @DATADIR@/sane/epjitsu/300M_0C00.nal usb 0x04c5 0x117f +# Fujitsu S1100 +firmware @DATADIR@/sane/epjitsu/1100_0B00.nal +usb 0x04c5 0x1200 + # Fujitsu S1300 firmware @DATADIR@/sane/epjitsu/1300_0C26.nal usb 0x04c5 0x11ed + +# Fujitsu S1300i +firmware @DATADIR@/sane/epjitsu/1300i_0D12.nal +usb 0x04c5 0x128d diff --git a/backend/epjitsu.h b/backend/epjitsu.h index ed63504..7bb1ccc 100644 --- a/backend/epjitsu.h +++ b/backend/epjitsu.h @@ -18,8 +18,7 @@ enum scanner_Option OPT_MODE_GROUP, OPT_SOURCE, /*adffront/adfback/adfduplex/fb*/ OPT_MODE, /*mono/gray/color*/ - OPT_X_RES, - OPT_Y_RES, + OPT_RES, OPT_GEOMETRY_GROUP, OPT_TL_X, @@ -56,7 +55,11 @@ struct image { int width_bytes; int height; int pages; - + int x_res; + int y_res; + int x_start_offset; + int x_offset_bytes; + int y_skip_offset; unsigned char * buffer; }; @@ -68,6 +71,8 @@ struct transfer { int total_bytes; int rx_bytes; int done; + int x_res; + int y_res; unsigned char * raw_data; struct image * image; @@ -77,6 +82,9 @@ struct page { int bytes_total; int bytes_scanned; int bytes_read; + int lines_rx; /* received from scanner */ + int lines_pass; /* passed thru from scanner to user (might be smaller than tx for 225dpi) */ + int lines_tx; /* transmitted to user */ int done; struct image *image; }; @@ -94,15 +102,13 @@ struct scanner int has_fb; int has_adf; - int x_res_150; - int x_res_225; - int x_res_300; - int x_res_600; + int has_adf_duplex; + + int min_res; + int max_res; - int y_res_150; - int y_res_225; - int y_res_300; - int y_res_600; + float white_factor[3]; + int adf_height_padding; /* the scan size in 1/1200th inches, NOT basic_units or sane units */ int max_x; @@ -127,8 +133,7 @@ struct scanner /*mode group, room for lineart, gray, color, null */ SANE_String_Const source_list[5]; SANE_String_Const mode_list[4]; - SANE_Int x_res_list[4]; - SANE_Int y_res_list[4]; + SANE_Range res_range; /*geometry group*/ SANE_Range tl_x_range; @@ -151,9 +156,7 @@ struct scanner /*mode group*/ int source; /* adf or fb */ int mode; /* color,lineart,etc */ - int res; /* from a limited list, x and y same */ - int resolution_x; /* unused dummy */ - int resolution_y; /* unused dummy */ + int resolution; /* dpi */ /*geometry group*/ /* The desired size of the scan, all in 1/1200 inch */ @@ -213,6 +216,8 @@ struct scanner /* the scan struct holds these larger numbers, but image buffer is unused */ struct { int done; + int x_res; + int y_res; int height; int rx_bytes; int width_bytes; @@ -257,6 +262,9 @@ struct scanner #define MODEL_NONE 0 #define MODEL_S300 1 #define MODEL_FI60F 2 +#define MODEL_S1100 3 +#define MODEL_S1300i 4 +#define MODEL_FI65F 5 #define USB_COMMAND_TIME 10000 #define USB_DATA_TIME 10000 @@ -278,6 +286,9 @@ struct scanner #define WINDOW_SENDCAL 2 #define WINDOW_SCAN 3 +#define EPJITSU_PAPER_INGEST 1 +#define EPJITSU_PAPER_EJECT 0 + /* ------------------------------------------------------------------------- */ #define MM_PER_UNIT_UNFIX SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) @@ -286,6 +297,9 @@ struct scanner #define SCANNER_UNIT_TO_FIXED_MM(number) SANE_FIX((number) * MM_PER_UNIT_UNFIX) #define FIXED_MM_TO_SCANNER_UNIT(number) SANE_UNFIX(number) / MM_PER_UNIT_UNFIX +#define PIX_TO_SCANNER_UNIT(number, dpi) SANE_UNFIX(SANE_FIX((number) * 1200 / dpi )) +#define SCANNER_UNIT_TO_PIX(number, dpi) SANE_UNFIX(SANE_FIX((number) * dpi / 1200 )) + #define CONFIG_FILE "epjitsu.conf" #ifndef PATH_MAX @@ -354,7 +368,8 @@ static SANE_Status destroy(struct scanner *s); static SANE_Status teardown_buffers(struct scanner *s); static SANE_Status setup_buffers(struct scanner *s); -static SANE_Status ingest(struct scanner *s); +static SANE_Status object_position(struct scanner *s, int ingest); +static SANE_Status six5 (struct scanner *s); static SANE_Status coarsecal(struct scanner *s); static SANE_Status finecal(struct scanner *s); static SANE_Status send_lut(struct scanner *s); diff --git a/backend/epson.c b/backend/epson.c index 2cae65a..3b063b9 100644 --- a/backend/epson.c +++ b/backend/epson.c @@ -818,6 +818,12 @@ typedef struct } EpsonIdentRec, *EpsonIdent; +typedef union +{ + EpsonHdrRec hdr; + EpsonIdentRec ident; +} EpsonHdrUnionRec, *EpsonHdrUnion; + typedef struct { @@ -843,7 +849,7 @@ typedef struct * */ -static EpsonHdr command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, +static EpsonHdrUnion command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, SANE_Status * status); static SANE_Status get_identity_information (SANE_Handle handle); static SANE_Status get_identity2_information (SANE_Handle handle); @@ -1844,21 +1850,24 @@ static Epson_Device *first_dev = NULL; /* first EPSON scanner in list */ static Epson_Scanner *first_handle = NULL; -static EpsonHdr +static EpsonHdrUnion command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, SANE_Status * status) { + EpsonHdrUnion hdrunion, hdrunion_bak; EpsonHdr head; u_char *buf; int count; - if (NULL == (head = walloc (EpsonHdrRec))) + if (NULL == (hdrunion = walloc (EpsonHdrUnionRec))) { DBG (1, "out of memory (line %d)\n", __LINE__); *status = SANE_STATUS_NO_MEM; - return (EpsonHdr) 0; + return (EpsonHdrUnion) 0; } + head = &(hdrunion->hdr); + send (s, cmd, cmd_size, status); if (SANE_STATUS_GOOD != *status) @@ -1869,7 +1878,7 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, *status = SANE_STATUS_GOOD; send (s, cmd, cmd_size, status); if (SANE_STATUS_GOOD != *status) - return (EpsonHdr) 0; + return (EpsonHdrUnion) 0; } buf = (u_char *) head; @@ -1892,7 +1901,7 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, } if (SANE_STATUS_GOOD != *status) - return (EpsonHdr) 0; + return (EpsonHdrUnion) 0; DBG (4, "code %02x\n", (int) head->code); @@ -1921,25 +1930,30 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, } if (SANE_STATUS_GOOD != *status) - return (EpsonHdr) 0; + return (EpsonHdrUnion) 0; DBG (4, "status %02x\n", (int) head->status); count = head->count2 * 255 + head->count1; DBG (4, "count %d\n", count); - if (NULL == (head = realloc (head, sizeof (EpsonHdrRec) + count))) + hdrunion_bak = hdrunion; + if (NULL == (hdrunion = realloc (hdrunion, + sizeof (EpsonHdrUnionRec) + count))) { + free(hdrunion_bak); DBG (1, "out of memory (line %d)\n", __LINE__); *status = SANE_STATUS_NO_MEM; - return (EpsonHdr) 0; + return (EpsonHdrUnion) 0; } + head = &(hdrunion->hdr); + buf = head->buf; receive (s, buf, count, status); if (SANE_STATUS_GOOD != *status) - return (EpsonHdr) 0; + return (EpsonHdrUnion) 0; break; @@ -1953,7 +1967,7 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, break; } - return head; + return hdrunion; } diff --git a/backend/epson2-commands.c b/backend/epson2-commands.c index a84630b..0c28eab 100644 --- a/backend/epson2-commands.c +++ b/backend/epson2-commands.c @@ -333,7 +333,7 @@ esci_set_gamma_table(Epson_Scanner * s) /* Print the gamma tables before sending them to the scanner */ - if (DBG_LEVEL >= 10) { + if (DBG_LEVEL >= 16) { int c, i, j; for (c = 0; c < 3; c++) { @@ -347,7 +347,8 @@ esci_set_gamma_table(Epson_Scanner * s) s->gamma_table[c][i + j]); strcat(gammaValues, newValue); } - DBG(11, "gamma table[%d][%d] %s\n", c, i, + + DBG(16, "gamma table[%d][%d] %s\n", c, i, gammaValues); } } diff --git a/backend/epson2-ops.c b/backend/epson2-ops.c index df6958c..d81deaf 100644 --- a/backend/epson2-ops.c +++ b/backend/epson2-ops.c @@ -177,7 +177,7 @@ e2_dev_init(Epson_Device *dev, const char *devname, int conntype) SANE_Status e2_dev_post_init(struct Epson_Device *dev) { - int i; + int i, last; DBG(5, "%s\n", __func__); @@ -231,7 +231,7 @@ e2_dev_post_init(struct Epson_Device *dev) /* try to expand the resolution list where appropriate */ - int last = dev->res_list[dev->res_list_size - 1]; + last = dev->res_list[dev->res_list_size - 1]; DBG(1, "highest available resolution: %d\n", last); @@ -700,6 +700,11 @@ e2_discover_capabilities(Epson_Scanner *s) *source_list_add++ = ADF_STR; dev->ADF = SANE_TRUE; } + + if (buf[44] & EXT_IDTY_CAP1_ADFS) { + dev->duplex = SANE_TRUE; + } + } /* TPU */ @@ -901,25 +906,28 @@ e2_set_extended_scanning_parameters(Epson_Scanner * s) char extensionCtrl; extensionCtrl = (s->hw->use_extension ? 1 : 0); - if (s->hw->use_extension && (s->val[OPT_ADF_MODE].w == 1)) + if (s->hw->use_extension && (s->val[OPT_ADF_MODE].w == 1)) { extensionCtrl = 2; + } /* Test for TPU2 * Epson Perfection 4990 Command Specifications * JZIS-0075 Rev. A, page 31 */ - if (s->hw->use_extension && s->hw->TPU2) + if (s->hw->use_extension && s->hw->TPU2) { extensionCtrl = 5; + } - if (s->val[OPT_MODE].w == MODE_INFRARED) + if (s->val[OPT_MODE].w == MODE_INFRARED) { /* only infrared in TPU mode (NOT in TPU2 or flatbeth) * XXX investigate this ... only tested on GT-X800 */ if (extensionCtrl == 1) /* test for TPU */ - extensionCtrl = 3; + extensionCtrl = 3; else - return SANE_STATUS_UNSUPPORTED; + return SANE_STATUS_UNSUPPORTED; + } /* ESC e */ buf[26] = extensionCtrl; @@ -1689,10 +1697,6 @@ e2_scan_finish(Epson_Scanner * s) if (s->hw->ADF && s->hw->use_extension && s->val[OPT_AUTO_EJECT].w) if (e2_check_adf(s) == SANE_STATUS_NO_DOCS) esci_eject(s); - - /* XXX required? */ - if (s->hw->connection != SANE_EPSON_NET) - esci_reset(s); } void @@ -2132,6 +2136,7 @@ e2_block_read(struct Epson_Scanner *s) * RGB then swap the colors. */ + /* never used, beta testers required */ needStrangeReorder = (strstr(s->hw->model, "GT-2200") || ((strstr(s->hw->model, "1640") diff --git a/backend/epson2-ops.h b/backend/epson2-ops.h index 9c36326..decbd4b 100644 --- a/backend/epson2-ops.h +++ b/backend/epson2-ops.h @@ -33,6 +33,7 @@ extern SANE_Status e2_add_resolution(Epson_Device *dev, int r); extern void e2_set_fbf_area(Epson_Scanner *s, int x, int y, int unit); extern void e2_set_adf_area(struct Epson_Scanner *s, int x, int y, int unit); extern void e2_set_tpu_area(struct Epson_Scanner *s, int x, int y, int unit); +extern void e2_set_tpu2_area(struct Epson_Scanner *s, int x, int y, int unit); extern void e2_add_depth(Epson_Device *dev, SANE_Word depth); extern SANE_Status e2_discover_capabilities(Epson_Scanner *s); extern SANE_Status e2_set_extended_scanning_parameters(Epson_Scanner *s); diff --git a/backend/epson2.c b/backend/epson2.c index 9f39c68..e023010 100644 --- a/backend/epson2.c +++ b/backend/epson2.c @@ -29,6 +29,7 @@ * 20 usb cmd counters * 18 sane_read * 17 setvalue, getvalue, control_option + * 16 gamma table * 15 e2_send, e2_recv calls * 13 e2_cmd_info_block * 12 epson_cmd_simple @@ -409,8 +410,8 @@ e2_network_discovery(void) FD_SET(fd, &rfds); sanei_udp_set_nonblock(fd, SANE_TRUE); - if (select(fd + 1, &rfds, NULL, NULL, &to) > 0) { - while ((len = sanei_udp_recvfrom(fd, buf, 76, &ip)) == 76) { + while (select(fd + 1, &rfds, NULL, NULL, &to) > 0) { + if ((len = sanei_udp_recvfrom(fd, buf, 76, &ip)) == 76) { DBG(5, " response from %s\n", ip); /* minimal check, protocol unknown */ @@ -1752,8 +1753,9 @@ change_source(Epson_Scanner *s, SANE_Int optindex, char *value) s->val[OPT_ADF_MODE].w = 0; } - DBG(1, "adf activated (%d %d)\n", s->hw->use_extension, - s->hw->duplex); + DBG(1, "adf activated (ext: %d, duplex: %d)\n", + s->hw->use_extension, + s->hw->duplex); } else if (strcmp(TPU_STR, value) == 0 || strcmp(TPU_STR2, value) == 0) { if (strcmp(TPU_STR, value) == 0) { diff --git a/backend/epson2_net.c b/backend/epson2_net.c index c7b4873..178b519 100644 --- a/backend/epson2_net.c +++ b/backend/epson2_net.c @@ -28,25 +28,32 @@ #include "sane/sanei_debug.h" -int -sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, size_t wanted, - SANE_Status * status) +static int +sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, + SANE_Status *status) { - size_t size, read = 0; + int ready, read = -1; + fd_set readable; + struct timeval tv; - *status = SANE_STATUS_GOOD; + tv.tv_sec = 10; + tv.tv_usec = 0; - while (read < wanted) { - size = sanei_tcp_read(s->fd, buf + read, wanted - read); + FD_ZERO(&readable); + FD_SET(s->fd, &readable); - if (size == 0) - break; - - read += size; + ready = select(s->fd + 1, &readable, NULL, NULL, &tv); + if (ready > 0) { + read = sanei_tcp_read(s->fd, buf, wanted); + } else { + DBG(15, "%s: select failed: %d\n", __func__, ready); } - if (read < wanted) + *status = SANE_STATUS_GOOD; + + if (read < wanted) { *status = SANE_STATUS_IO_ERROR; + } return read; } @@ -80,9 +87,8 @@ sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, } /* receive net header */ - size = sanei_tcp_read(s->fd, header, 12); + size = sanei_epson_net_read_raw(s, header, 12, status); if (size != 12) { - *status = SANE_STATUS_IO_ERROR; return 0; } @@ -102,7 +108,8 @@ sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, if (size == wanted) { DBG(15, "%s: full read\n", __func__); - read = sanei_tcp_read(s->fd, buf, size); + + read = sanei_epson_net_read_raw(s, buf, size, status); if (s->netbuf) { free(s->netbuf); @@ -111,7 +118,6 @@ sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, } if (read < 0) { - *status = SANE_STATUS_IO_ERROR; return 0; } @@ -119,9 +125,8 @@ sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, } else { DBG(23, "%s: partial read\n", __func__); - read = sanei_tcp_read(s->fd, s->netbuf, size); + read = sanei_epson_net_read_raw(s, s->netbuf, size, status); if (read != size) { - *status = SANE_STATUS_IO_ERROR; return 0; } diff --git a/backend/epson2_net.h b/backend/epson2_net.h index 6a6e8d8..6aef2b7 100644 --- a/backend/epson2_net.h +++ b/backend/epson2_net.h @@ -9,9 +9,6 @@ extern int sanei_epson_net_read(struct Epson_Scanner *s, unsigned char *buf, ssi extern int sanei_epson_net_write(struct Epson_Scanner *s, unsigned int cmd, const unsigned char *buf, size_t buf_size, size_t reply_len, SANE_Status *status); -extern int -sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, size_t wanted, - SANE_Status * status); extern SANE_Status sanei_epson_net_lock(struct Epson_Scanner *s); extern SANE_Status sanei_epson_net_unlock(struct Epson_Scanner *s); diff --git a/backend/epson_usb.c b/backend/epson_usb.c index 848ef63..8ba8efa 100644 --- a/backend/epson_usb.c +++ b/backend/epson_usb.c @@ -28,6 +28,8 @@ SANE_Word sanei_epson_usb_product_ids[] = { 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 */ @@ -72,16 +74,84 @@ SANE_Word sanei_epson_usb_product_ids[] = { 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 */ + 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, /* Stylus SX125 */ + 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 */ 0 /* last entry - this is used for devices that are specified in the config file as "usb " */ }; diff --git a/backend/fujitsu-scsi.h b/backend/fujitsu-scsi.h index 52ac7c6..de6652c 100644 --- a/backend/fujitsu-scsi.h +++ b/backend/fujitsu-scsi.h @@ -330,6 +330,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define get_IN_skew_check(in) getbitfield(in+0x6d, 1, 7) #define get_IN_new_fd_roll(in) getbitfield(in+0x6d, 1, 6) +#define get_IN_paper_prot_2(in) getbitfield(in+0x6d, 1, 1) #define get_IN_evpd_len(in) getnbyte(in + 0x6f, 1) @@ -364,8 +365,20 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) /*byte 75 is poorly documented*/ +#define get_IN_erp_lot6_supp(in) getbitfield(in+0x76, 1, 7) +#define get_IN_mode_change_jpeg(in) getbitfield(in+0x76, 1, 5) +#define get_IN_mode_change_irdc(in) getbitfield(in+0x76, 1, 4) +#define get_IN_mode_change_iomf(in) getbitfield(in+0x76, 1, 3) #define get_IN_sync_next_feed(in) getbitfield(in+0x76, 0x07, 0) +#define get_IN_imp_func3(in) getbitfield(in+0x77, 1, 7) + +#define get_IN_reset_ms(in) getbitfield(in+0x78, 1, 7) +#define get_IN_read_size(in) getbitfield(in+0x78, 1, 6) +#define get_IN_start_end_ms(in) getbitfield(in+0x78, 1, 5) + +#define get_IN_op_halt(in) getbitfield(in+0x7a, 1, 7) + /* some scanners need evpd inquiry data manipulated */ #define set_IN_page_length(in,val) in[0x04]=val @@ -429,6 +442,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define set_MSEL_df_paperprot(sb, val) setbitfield(sb + 3, 3, 6, val) #define set_MSEL_df_stapledet(sb, val) setbitfield(sb + 3, 3, 4, val) #define set_MSEL_df_recovery(sb, val) setbitfield(sb + 3, 3, 2, val) +#define set_MSEL_df_paperprot2(sb, val) setbitfield(sb + 5, 3, 6, val) #define set_MSEL_dropout_front(sb, val) setbitfield(sb + 0x02, 0x0f, 0, val) #define set_MSEL_dropout_back(sb, val) setbitfield(sb + 0x02, 0x0f, 4, val) @@ -548,6 +562,13 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define set_SD_preread_composition(sb, val) putnbyte(sb + 0x1c, val, 1) #define set_SD_preread_escan(sb, val) putnbyte(sb + 0x1d, val, 1) +#define SD_powoff_string "SET POWOFF TIME " +#define SD_powoff_stringlen 16 +#define SD_powoff_len 18 +#define set_SD_powoff_disable(in, val) setbitfield(in + 16, 1, 7, val) +#define set_SD_powoff_interval(in, val) setbitfield(in + 16, 0x7f, 0, val) +#define set_SD_powoff_notify(sb, val) putnbyte(sb + 0x17, val, 1) + /* ==================================================================== */ /* SET_WINDOW */ #define SET_WINDOW_code 0x24 @@ -675,9 +696,10 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define OBJECT_POSITION_code 0x31 #define OBJECT_POSITION_len 10 -#define set_OP_autofeed(b,val) setbitfield(b+0x01, 0x07, 0, val) +#define set_OP_action(b,val) setbitfield(b+0x01, 0x07, 0, val) #define OP_Discharge 0x00 #define OP_Feed 0x01 +#define OP_Halt 0x04 /* ==================================================================== */ /* SET_SUBWINDOW */ diff --git a/backend/fujitsu.c b/backend/fujitsu.c index 48d55dc..7f008d0 100644 --- a/backend/fujitsu.c +++ b/backend/fujitsu.c @@ -6,7 +6,7 @@ Copyright (C) 2000 Randolph Bentson Copyright (C) 2001 Frederik Ramm Copyright (C) 2001-2004 Oliver Schirrmeister - Copyright (C) 2003-2011 m. allan noah + Copyright (C) 2003-2014 m. allan noah JPEG output and low memory usage support funded by: Archivista GmbH, www.archivista.ch @@ -14,7 +14,7 @@ O A S Oilfield Accounting Service Ltd, www.oas.ca Automatic length detection support funded by: Martin G. Miller, mgmiller at optonline.net - Software image enhancement routines funded by: + Software image enhancement routines and recent scanner support funded by: Fujitsu Computer Products of America, Inc. www.fcpa.com -------------------------------------------------------------------------- @@ -533,11 +533,44 @@ v116 2013-03-23, MAN - call set_mode() in init_interlace - add swskip option - v117 2013-06-11, MAN + v117 2013-06-11, MAN (SANE 1.0.24) - default buffer-mode to off - improved error handling in sane_start - image width must be multiple of 8 when swcrop is used before binarization (iX500) - check hopper sensor before calling object_position(load) on iX500 + v118 2013-12-09, MAN + - support fi-7160, fi-7260, fi-7180 and fi-7280 + - remove unused var from do_scsi_cmd() + - added more request_sense options + - add adv_paper_protect option + - enable paper protection by default + - increase max_x_fb for fi-6240 and fi-6230 + v119 2013-12-18, MAN + - call get_pixelsize after start_scan, not before + - extend get_pixelsize to request backside data + - stop using backup/restore_params + - don't use extended get_pixelsize on M3091 or M3092 + - call software crop code on backside images too + v120 2014-01-29, MAN + - only call hopper_before_op code at batch start + - remove unused backup/restore_params + v121 2014-04-07, MAN + - add JFIF APP0 marker with resolution to jpeg images + - improve jpeg duplex parsing code + - simplify jpeg ifdefs + - add offtimer option for more recent scanners + - don't print 0 length line in hexdump + v122 2014-10-28, MAN + - add support for object_position halt + - call object_position halt in check_for_cancel when requested + v123 2014-11-06, MAN + - workaround Linux USB3 bugs by adding command counting code and + sending an even number of reads and writes during disconnect_fd + v124 2014-12-09, MAN + - support resolution controlled max page-height (fi-6/7xxx scanners) + - reorder scanner sections in init_model chronologically + v125 2014-12-16, MAN + - remove USB packet counting code from v123, fix sanei_usb instead SANE FLOW DIAGRAM @@ -587,7 +620,7 @@ #include "fujitsu.h" #define DEBUG 1 -#define BUILD 117 +#define BUILD 125 /* values for SANE_DEBUG_FUJITSU env var: - errors 5 @@ -600,6 +633,12 @@ - useless noise 35 */ +/* ------------------------------------------------------------------------- */ +/* if JPEG support is not enabled in sane.h, we setup our own defines */ +#ifndef SANE_FRAME_JPEG +#define SANE_FRAME_JPEG 0x0B +#define SANE_JPEG_DISABLED 1 +#endif /* ------------------------------------------------------------------------- */ #define STRING_FLATBED SANE_I18N("Flatbed") #define STRING_ADFFRONT SANE_I18N("ADF Front") @@ -1577,9 +1616,8 @@ init_vpd (struct fujitsu *s) s->has_comp_JPG1 = get_IN_compression_JPG_BASE (in); DBG (15, " compression JPG1: %d\n", s->has_comp_JPG1); -#ifndef SANE_FRAME_JPEG +#ifdef SANE_JPEG_DISABLED DBG (15, " (Disabled)\n"); - s->has_comp_JPG1 = 0; #endif s->has_comp_JPG2 = get_IN_compression_JPG_EXT (in); @@ -1671,7 +1709,12 @@ init_vpd (struct fujitsu *s) DBG (15, " rgb lut: %d\n", get_IN_rgb_lut(in)); DBG (15, " num lut dl: %d\n", get_IN_num_lut_dl(in)); + s->has_off_mode = get_IN_erp_lot6_supp(in); + DBG (15, " ErP Lot6 (power off timer): %d\n", s->has_off_mode); DBG (15, " sync next feed: %d\n", get_IN_sync_next_feed(in)); + + s->has_op_halt = get_IN_op_halt(in); + DBG (15, " object postion halt: %d\n", s->has_op_halt); } ret = SANE_STATUS_GOOD; @@ -2012,6 +2055,10 @@ init_model (struct fujitsu *s) s->max_x = s->max_x_basic * 1200 / s->basic_x_res; s->max_y = s->max_y_basic * 1200 / s->basic_y_res; + /* setup the list with a single choice, in 1200dpi units, at max res */ + s->max_y_by_res[0].res = s->max_y_res; + s->max_y_by_res[0].len = s->max_y; + /* assume these are same as adf, override below */ s->max_x_fb = s->max_x; s->max_y_fb = s->max_y; @@ -2062,6 +2109,7 @@ init_model (struct fujitsu *s) s->has_vuid_3091 = 1; s->has_vuid_color = 0; s->has_vuid_mono = 0; + s->has_short_pixelsize = 1; s->color_interlace = COLOR_INTERLACE_3091; s->duplex_interlace = DUPLEX_INTERLACE_3091; @@ -2106,6 +2154,38 @@ init_model (struct fujitsu *s) s->max_y_fb = 14032; } + else if (strstr (s->model_name, "fi-4750") ) { + /* weirdness */ + s->broken_diag_serial = 1; + } + + /* some firmware versions use capital f? */ + else if (strstr (s->model_name, "Fi-4860") + || strstr (s->model_name, "fi-4860") ) { + + /* weirdness */ + s->broken_diag_serial = 1; + + s->ppl_mod_by_mode[MODE_LINEART] = 32; + s->ppl_mod_by_mode[MODE_HALFTONE] = 32; + s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; + s->ppl_mod_by_mode[MODE_COLOR] = 4; + } + + /* some firmware versions use capital f? */ + else if (strstr (s->model_name, "Fi-4990") + || strstr (s->model_name, "fi-4990") ) { + + /* weirdness */ + s->duplex_interlace = DUPLEX_INTERLACE_NONE; + s->color_interlace = COLOR_INTERLACE_RRGGBB; + + s->ppl_mod_by_mode[MODE_LINEART] = 32; + s->ppl_mod_by_mode[MODE_HALFTONE] = 32; + s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; + s->ppl_mod_by_mode[MODE_COLOR] = 4; + } + else if (strstr (s->model_name,"fi-5110C")){ /* missing from vpd */ @@ -2135,49 +2215,44 @@ init_model (struct fujitsu *s) s->adbits = 8; } - /* some firmware versions use capital f? */ - else if (strstr (s->model_name, "Fi-4990") - || strstr (s->model_name, "fi-4990") ) { - - /* weirdness */ - s->duplex_interlace = DUPLEX_INTERLACE_NONE; - s->color_interlace = COLOR_INTERLACE_RRGGBB; - - s->ppl_mod_by_mode[MODE_LINEART] = 32; - s->ppl_mod_by_mode[MODE_HALFTONE] = 32; - s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; - s->ppl_mod_by_mode[MODE_COLOR] = 4; - } + else if (strstr (s->model_name,"S1500")){ - else if (strstr (s->model_name, "fi-4750") ) { - /* weirdness */ - s->broken_diag_serial = 1; + /*lies*/ + s->has_MS_bg=0; + s->has_MS_prepick=0; } - /* some firmware versions use capital f? */ - else if (strstr (s->model_name, "Fi-4860") - || strstr (s->model_name, "fi-4860") ) { + /* also includes the 'Z' models */ + else if (strstr (s->model_name,"fi-6130") + || strstr (s->model_name,"fi-6140")){ /* weirdness */ - s->broken_diag_serial = 1; - - s->ppl_mod_by_mode[MODE_LINEART] = 32; - s->ppl_mod_by_mode[MODE_HALFTONE] = 32; - s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; - s->ppl_mod_by_mode[MODE_COLOR] = 4; + /* these machines have longer max paper at lower res */ + s->max_y_by_res[1].res = 200; + s->max_y_by_res[1].len = 151512; } /* also includes the 'Z' models */ else if (strstr (s->model_name,"fi-6230") || strstr (s->model_name,"fi-6240")){ + /* weirdness */ + /* these machines have longer max paper at lower res */ + s->max_y_by_res[1].res = 200; + s->max_y_by_res[1].len = 151512; + /* missing from vpd */ - s->max_x_fb = 10488; + s->max_x_fb = 10764; /* was previously 10488 */ s->max_y_fb = 14032; /* some scanners can be slightly more? */ } - else if (strstr (s->model_name,"S1500") - || strstr (s->model_name,"fi-6110")){ + else if (strstr (s->model_name,"fi-6110")){ + + /* weirdness */ + /* these machines have longer max paper at lower res */ + s->max_y_by_res[1].res = 200; + s->max_y_by_res[1].len = 151512; + /*lies*/ s->has_MS_bg=0; s->has_MS_prepick=0; @@ -2212,6 +2287,42 @@ init_model (struct fujitsu *s) s->can_mode[MODE_HALFTONE] = 0; } + else if (strstr (s->model_name,"fi-7180") + || strstr (s->model_name,"fi-7160")){ + + /* weirdness */ + /* these machines have longer max paper at lower res */ + s->max_y_by_res[1].res = 400; + s->max_y_by_res[1].len = 194268; + s->max_y_by_res[2].res = 300; + s->max_y_by_res[2].len = 260268; + s->max_y_by_res[3].res = 200; + s->max_y_by_res[3].len = 266268; + + /* missing from vpd */ + s->has_df_recovery=1; + s->has_adv_paper_prot=1; + } + + else if (strstr (s->model_name,"fi-7280") + || strstr (s->model_name,"fi-7260")){ + + /* weirdness */ + /* these machines have longer max paper at lower res */ + s->max_y_by_res[1].res = 400; + s->max_y_by_res[1].len = 194268; + s->max_y_by_res[2].res = 300; + s->max_y_by_res[2].len = 260268; + s->max_y_by_res[3].res = 200; + s->max_y_by_res[3].len = 266268; + + /* missing from vpd */ + s->has_df_recovery=1; + s->has_adv_paper_prot=1; + s->max_x_fb = 10764; + s->max_y_fb = 14032; /* some scanners can be slightly more? */ + } + DBG (10, "init_model: finish\n"); return SANE_STATUS_GOOD; @@ -2277,6 +2388,7 @@ init_user (struct fujitsu *s) /* page height US-Letter */ s->page_height = 11 * 1200; + set_max_y(s); if(s->page_height > s->max_y){ s->page_height = s->max_y; } @@ -2310,6 +2422,23 @@ init_user (struct fujitsu *s) * even when the user only wants one */ s->buff_mode = MSEL_OFF; + /* useful features of newer scanners which we turn on, + * even though the scanner defaults to off */ + if(s->has_paper_protect){ + s->paper_protect = MSEL_ON; + } + if(s->has_staple_detect){ + s->staple_detect = MSEL_ON; + } + if(s->has_df_recovery){ + s->df_recovery = MSEL_ON; + } + if(s->has_adv_paper_prot){ + s->adv_paper_prot = MSEL_ON; + } + + s->off_time = 240; + DBG (10, "init_user: finish\n"); return SANE_STATUS_GOOD; @@ -3377,7 +3506,9 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->compress_list[i++]=STRING_NONE; if(s->has_comp_JPG1){ +#ifndef SANE_JPEG_DISABLED s->compress_list[i++]=STRING_JPEG; +#endif } s->compress_list[i]=NULL; @@ -3528,7 +3659,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } - /*df recovery*/ + /*df_recovery*/ if(option==OPT_DF_RECOVERY){ s->df_recovery_list[0] = STRING_DEFAULT; s->df_recovery_list[1] = STRING_OFF; @@ -3548,7 +3679,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } - /*paper protection*/ + /*paper_protect*/ if(option==OPT_PAPER_PROTECT){ s->paper_protect_list[0] = STRING_DEFAULT; s->paper_protect_list[1] = STRING_OFF; @@ -3568,6 +3699,26 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } + /*adv_paper_prot*/ + if(option==OPT_ADV_PAPER_PROT){ + s->adv_paper_prot_list[0] = STRING_DEFAULT; + s->adv_paper_prot_list[1] = STRING_OFF; + s->adv_paper_prot_list[2] = STRING_ON; + s->adv_paper_prot_list[3] = NULL; + + opt->name = "adv-paper-protect"; + opt->title = "Advanced paper protection"; + opt->desc = "Request scanner to predict jams in the ADF using improved sensors"; + opt->type = SANE_TYPE_STRING; + opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; + opt->constraint.string_list = s->adv_paper_prot_list; + opt->size = maxStringSize (opt->constraint.string_list); + if (s->has_MS_df && s->has_adv_paper_prot) + opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; + else + opt->cap = SANE_CAP_INACTIVE; + } + /*staple detection*/ if(option==OPT_STAPLE_DETECT){ s->staple_detect_list[0] = STRING_DEFAULT; @@ -3693,7 +3844,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } - /*sleep time*/ + /*sleep_time*/ if(option==OPT_SLEEP_TIME){ s->sleep_time_range.min = 0; s->sleep_time_range.max = 60; @@ -3712,6 +3863,25 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } + /*off_time*/ + if(option==OPT_OFF_TIME){ + s->off_time_range.min = 0; + s->off_time_range.max = 960; + s->off_time_range.quant = 1; + + opt->name = "offtimer"; + opt->title = "Off timer"; + opt->desc = "Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off."; + opt->type = SANE_TYPE_INT; + opt->unit = SANE_UNIT_NONE; + opt->constraint_type = SANE_CONSTRAINT_RANGE; + opt->constraint.range=&s->off_time_range; + if(s->has_off_mode) + opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; + else + opt->cap = SANE_CAP_INACTIVE; + } + /*duplex offset*/ if(option==OPT_DUPLEX_OFFSET){ s->duplex_offset_range.min = -16; @@ -3862,13 +4032,25 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->swskip_range; - s->swskip_range.quant=1; + s->swskip_range.quant=SANE_FIX(0.10001); s->swskip_range.min=SANE_FIX(0); s->swskip_range.max=SANE_FIX(100); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } + /*halt scanner feeder when cancelling*/ + if(option==OPT_HALT_ON_CANCEL){ + opt->name = "halt-on-cancel"; + opt->title = "Halt on Cancel"; + opt->desc = "Request driver to halt the paper feed instead of eject during a cancel."; + opt->type = SANE_TYPE_BOOL; + if (s->has_op_halt) + opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; + else + opt->cap = SANE_CAP_INACTIVE; + } + /* "Endorser" group ------------------------------------------------------ */ if(option==OPT_ENDORSER_GROUP){ opt->name = "endorser-options"; @@ -4689,6 +4871,20 @@ sane_control_option (SANE_Handle handle, SANE_Int option, } return SANE_STATUS_GOOD; + case OPT_ADV_PAPER_PROT: + switch (s->adv_paper_prot) { + case MSEL_DEFAULT: + strcpy (val, STRING_DEFAULT); + break; + case MSEL_ON: + strcpy (val, STRING_ON); + break; + case MSEL_OFF: + strcpy (val, STRING_OFF); + break; + } + return SANE_STATUS_GOOD; + case OPT_STAPLE_DETECT: switch (s->staple_detect) { case MSEL_DEFAULT: @@ -4780,6 +4976,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option, *val_p = s->sleep_time; return SANE_STATUS_GOOD; + case OPT_OFF_TIME: + *val_p = s->off_time; + return SANE_STATUS_GOOD; + case OPT_DUPLEX_OFFSET: *val_p = s->duplex_offset; return SANE_STATUS_GOOD; @@ -4820,6 +5020,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option, *val_p = SANE_FIX(s->swskip); return SANE_STATUS_GOOD; + case OPT_HALT_ON_CANCEL: + *val_p = s->halt_on_cancel; + return SANE_STATUS_GOOD; + /* Endorser Group */ case OPT_ENDORSER: *val_p = s->u_endorser; @@ -5080,6 +5284,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->resolution_x = val_c; s->resolution_y = val_c; + set_max_y(s); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; @@ -5341,6 +5546,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->paper_protect = MSEL_OFF; return SANE_STATUS_GOOD; + case OPT_ADV_PAPER_PROT: + if (!strcmp(val, STRING_DEFAULT)) + s->adv_paper_prot = MSEL_DEFAULT; + else if (!strcmp(val, STRING_ON)) + s->adv_paper_prot = MSEL_ON; + else if (!strcmp(val, STRING_OFF)) + s->adv_paper_prot = MSEL_OFF; + return SANE_STATUS_GOOD; + case OPT_STAPLE_DETECT: if (!strcmp(val, STRING_DEFAULT)) s->staple_detect = MSEL_DEFAULT; @@ -5403,6 +5617,14 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->sleep_time = val_c; return set_sleep_mode(s); + case OPT_OFF_TIME: + /* do our own constrain, because we want to round up */ + s->off_time = (val_c + 14)/15*15; + if(s->off_time != val_c){ + *info |= SANE_INFO_INEXACT; + } + return set_off_mode(s); + case OPT_DUPLEX_OFFSET: s->duplex_offset = val_c; return SANE_STATUS_GOOD; @@ -5439,6 +5661,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->swskip = SANE_UNFIX(val_c); return SANE_STATUS_GOOD; + case OPT_HALT_ON_CANCEL: + s->halt_on_cancel = val_c; + return SANE_STATUS_GOOD; + /* Endorser Group */ case OPT_ENDORSER: s->u_endorser = val_c; @@ -5549,6 +5775,50 @@ set_sleep_mode(struct fujitsu *s) return ret; } +static SANE_Status +set_off_mode(struct fujitsu *s) +{ + SANE_Status ret = SANE_STATUS_GOOD; + + unsigned char cmd[SEND_DIAGNOSTIC_len]; /*also big enough for READ_DIAG*/ + size_t cmdLen = SEND_DIAGNOSTIC_len; + + unsigned char out[SD_powoff_len]; + size_t outLen = SD_powoff_len; + + DBG (10, "set_off_mode: start\n"); + + if (!s->has_cmd_sdiag || !s->has_cmd_rdiag || !s->has_off_mode){ + DBG (5, "set_off_mode: not supported, returning\n"); + return ret; + } + + memset(cmd,0,cmdLen); + set_SCSI_opcode(cmd, SEND_DIAGNOSTIC_code); + set_SD_slftst(cmd, 0); + set_SD_xferlen(cmd, outLen); + + memcpy(out,SD_powoff_string,SD_powoff_stringlen); + set_SD_powoff_disable(out,!s->off_time); + set_SD_powoff_interval(out,s->off_time/15); + + ret = do_cmd ( + s, 1, 0, + cmd, cmdLen, + out, outLen, + NULL, NULL + ); + + if (ret != SANE_STATUS_GOOD){ + DBG (5, "set_off_mode: send diag error: %d\n", ret); + return ret; + } + + DBG (10, "set_off_mode: finish\n"); + + return SANE_STATUS_GOOD; +} + static SANE_Status get_hardware_status (struct fujitsu *s, SANE_Int option) { @@ -6092,6 +6362,7 @@ mode_select_df (struct fujitsu *s) set_MSEL_df_paperprot(page,s->paper_protect); set_MSEL_df_stapledet(page,s->staple_detect); set_MSEL_df_recovery(page,s->df_recovery); + set_MSEL_df_paperprot2(page,s->adv_paper_prot); ret = do_cmd ( s, 1, 0, @@ -6408,7 +6679,6 @@ update_params (struct fujitsu * s) if (s->s_mode == MODE_COLOR) { params->depth = 8; -#ifdef SANE_FRAME_JPEG /* jpeg requires 8x8 squares */ if(s->compress == COMP_JPEG){ params->format = SANE_FRAME_JPEG; @@ -6416,20 +6686,16 @@ update_params (struct fujitsu * s) params->lines -= params->lines % 8; } else{ -#endif params->format = SANE_FRAME_RGB; params->pixels_per_line -= params->pixels_per_line % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); -#ifdef SANE_FRAME_JPEG } -#endif params->bytes_per_line = params->pixels_per_line * 3; } else if (s->s_mode == MODE_GRAYSCALE) { params->depth = 8; -#ifdef SANE_FRAME_JPEG /* jpeg requires 8x8 squares */ if(s->compress == COMP_JPEG){ params->format = SANE_FRAME_JPEG; @@ -6437,13 +6703,10 @@ update_params (struct fujitsu * s) params->lines -= params->lines % 8; } else{ -#endif params->format = SANE_FRAME_GRAY; params->pixels_per_line -= params->pixels_per_line % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); -#ifdef SANE_FRAME_JPEG } -#endif params->bytes_per_line = params->pixels_per_line; } @@ -6526,70 +6789,6 @@ update_u_params (struct fujitsu * s) return ret; } -/* make backup of param data, in case original is overwritten */ -SANE_Status -backup_params (struct fujitsu * s) -{ - SANE_Status ret = SANE_STATUS_GOOD; - SANE_Parameters * params = &(s->s_params); - SANE_Parameters * params_bk = &(s->s_params_bk); - - DBG (10, "backup_params: start\n"); - - params_bk->format = params->format; - params_bk->last_frame = params->last_frame; - params_bk->bytes_per_line = params->bytes_per_line; - params_bk->pixels_per_line = params->pixels_per_line; - params_bk->lines = params->lines; - params_bk->depth = params->depth; - - /* also have to save the user params */ - params = &(s->u_params); - params_bk = &(s->u_params_bk); - - params_bk->format = params->format; - params_bk->last_frame = params->last_frame; - params_bk->bytes_per_line = params->bytes_per_line; - params_bk->pixels_per_line = params->pixels_per_line; - params_bk->lines = params->lines; - params_bk->depth = params->depth; - - DBG (10, "backup_params: finish\n"); - return ret; -} - -/* restore backup of param data, in case original was overwritten */ -SANE_Status -restore_params (struct fujitsu * s) -{ - SANE_Status ret = SANE_STATUS_GOOD; - SANE_Parameters * params = &(s->s_params); - SANE_Parameters * params_bk = &(s->s_params_bk); - - DBG (10, "restore_params: start\n"); - - params->format = params_bk->format; - params->last_frame = params_bk->last_frame; - params->bytes_per_line = params_bk->bytes_per_line; - params->pixels_per_line = params_bk->pixels_per_line; - params->lines = params_bk->lines; - params->depth = params_bk->depth; - - /* also have to restore the user params */ - params = &(s->u_params); - params_bk = &(s->u_params_bk); - - params->format = params_bk->format; - params->last_frame = params_bk->last_frame; - params->bytes_per_line = params_bk->bytes_per_line; - params->pixels_per_line = params_bk->pixels_per_line; - params->lines = params_bk->lines; - params->depth = params_bk->depth; - - DBG (10, "restore_params: finish\n"); - return ret; -} - /* * Called by SANE when a page acquisition operation is to be started. * commands: scanner control (lampon), send (lut), send (dither), @@ -6721,20 +6920,6 @@ sane_start (SANE_Handle handle) DBG (5, "sane_start: WARNING: cannot send_q_table %d\n", ret); } - /* try to read scan size from scanner */ - ret = get_pixelsize(s,0); - if (ret != SANE_STATUS_GOOD) { - DBG (5, "sane_start: ERROR: cannot get pixelsize\n"); - goto errors; - } - - /* make backup copy of params because later functions overwrite */ - ret = backup_params(s); - if (ret != SANE_STATUS_GOOD) { - DBG (5, "sane_start: ERROR: cannot backup params\n"); - goto errors; - } - /* start/stop endorser */ ret = endorser(s); if (ret != SANE_STATUS_GOOD) { @@ -6747,19 +6932,23 @@ sane_start (SANE_Handle handle) if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: WARNING: cannot start lamp, ignoring\n"); } + + /* iX500 errors if op is called with no paper + * at the beginning of a batch, so we check */ + if(s->hopper_before_op && s->source != SOURCE_FLATBED){ + ret = get_hardware_status(s,0); + if(!s->hw_hopper){ + ret = SANE_STATUS_NO_DOCS; + DBG (5, "sane_start: ERROR: hopper empty\n"); + goto errors; + } + } } /* if already running, duplex needs to switch sides */ else if(s->source == SOURCE_ADF_DUPLEX){ s->side = !s->side; } - /* restore backup copy of params at the start of each image */ - ret = restore_params(s); - if (ret != SANE_STATUS_GOOD) { - DBG (5, "sane_start: ERROR: cannot restore params\n"); - goto errors; - } - /* set clean defaults with new sheet of paper */ /* dont reset the transfer vars on backside of duplex page */ /* otherwise buffered back page will be lost */ @@ -6788,11 +6977,30 @@ sane_start (SANE_Handle handle) s->buff_tx[1]=0; /* reset jpeg just in case... */ - s->jpeg_stage = JPEG_STAGE_HEAD; - s->jpeg_ff_offset = 0; + s->jpeg_stage = JPEG_STAGE_NONE; + s->jpeg_ff_offset = -1; s->jpeg_front_rst = 0; s->jpeg_back_rst = 0; + ret = object_position (s, OP_Feed); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "sane_start: ERROR: cannot load page\n"); + goto errors; + } + + ret = start_scan (s); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "sane_start: ERROR: cannot start_scan\n"); + goto errors; + } + + /* try to read scan size from scanner */ + ret = get_pixelsize(s,0); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "sane_start: ERROR: cannot get pixelsize\n"); + goto errors; + } + /* store the number of front bytes */ if ( s->source != SOURCE_ADF_BACK ){ s->bytes_tot[SIDE_FRONT] = s->s_params.bytes_per_line * s->s_params.lines; @@ -6840,16 +7048,12 @@ sane_start (SANE_Handle handle) s->started=1; } - - ret = object_position (s, SANE_TRUE); - if (ret != SANE_STATUS_GOOD) { - DBG (5, "sane_start: ERROR: cannot load page\n"); - goto errors; - } - - ret = start_scan (s); + } + else{ + /* try to read scan size from scanner */ + ret = get_pixelsize(s,0); if (ret != SANE_STATUS_GOOD) { - DBG (5, "sane_start: ERROR: cannot start_scan\n"); + DBG (5, "sane_start: ERROR: cannot get pixelsize\n"); goto errors; } } @@ -7249,13 +7453,11 @@ set_window (struct fujitsu *s) set_WD_compress_type(desc1, COMP_NONE); set_WD_compress_arg(desc1, 0); -#ifdef SANE_FRAME_JPEG /* some scanners support jpeg image compression, for color/gs only */ if(s->s_params.format == SANE_FRAME_JPEG){ set_WD_compress_type(desc1, COMP_JPEG); set_WD_compress_arg(desc1, s->compress_arg); } -#endif /* the remainder of the block varies based on model and mode, * except for gamma and paper size, those are in the same place */ @@ -7435,7 +7637,8 @@ get_pixelsize(struct fujitsu *s, int actual) memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, R_datatype_pixelsize); - if(s->source == SOURCE_ADF_BACK){ + + if(s->side == SIDE_BACK){ set_R_window_id (cmd, WD_wid_back); } else{ @@ -7453,7 +7656,7 @@ get_pixelsize(struct fujitsu *s, int actual) /* when we are called post-scan, the scanner may give * more accurate data in other fields */ - if(actual && get_PSIZE_paper_w(in)){ + if(actual && !s->has_short_pixelsize && get_PSIZE_paper_w(in)){ s->s_params.pixels_per_line = get_PSIZE_paper_w(in); DBG(5,"get_pixelsize: Actual width\n"); } @@ -7469,7 +7672,7 @@ get_pixelsize(struct fujitsu *s, int actual) } /* when we are called post-scan, the scanner may give * more accurate data in other fields */ - else if(actual && get_PSIZE_paper_l(in)){ + else if(actual && !s->has_short_pixelsize && get_PSIZE_paper_l(in)){ s->s_params.lines = get_PSIZE_paper_l(in); DBG(5,"get_pixelsize: Actual length\n"); } @@ -7489,7 +7692,7 @@ get_pixelsize(struct fujitsu *s, int actual) } /* some scanners can request that the driver clean img */ - if(get_PSIZE_req_driv_valid(in)){ + if(!s->has_short_pixelsize && get_PSIZE_req_driv_valid(in)){ s->req_driv_crop = get_PSIZE_req_driv_crop(in); s->req_driv_lut = get_PSIZE_req_driv_lut(in); DBG(5,"get_pixelsize: scanner requests: crop=%d, lut=%d\n", @@ -7530,38 +7733,23 @@ get_pixelsize(struct fujitsu *s, int actual) * Issues the SCSI OBJECT POSITION command if an ADF is in use. */ static SANE_Status -object_position (struct fujitsu *s, int i_load) +object_position (struct fujitsu *s, int action) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[OBJECT_POSITION_len]; size_t cmdLen = OBJECT_POSITION_len; - DBG (10, "object_position: start\n"); + DBG (10, "object_position: start %d\n", action); - if (s->source == SOURCE_FLATBED) { + if (s->source == SOURCE_FLATBED && action < OP_Halt) { DBG (10, "object_position: flatbed no-op\n"); return SANE_STATUS_GOOD; } - if(s->hopper_before_op && i_load){ - ret = get_hardware_status(s,0); - if(!s->hw_hopper){ - return SANE_STATUS_NO_DOCS; - } - } - memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, OBJECT_POSITION_code); - - if (i_load) { - DBG (15, "object_position: load\n"); - set_OP_autofeed (cmd, OP_Feed); - } - else { - DBG (15, "object_position: eject\n"); - set_OP_autofeed (cmd, OP_Discharge); - } + set_OP_action (cmd, action); ret = do_cmd ( s, 1, 0, @@ -7630,22 +7818,30 @@ check_for_cancel(struct fujitsu *s) { SANE_Status ret=SANE_STATUS_GOOD; - DBG (10, "check_for_cancel: start\n"); + DBG (10, "check_for_cancel: start %d %d\n",s->started,s->cancelled); if(s->started && s->cancelled){ - DBG (15, "check_for_cancel: cancelling\n"); - /* cancel scan */ + /* halt scan */ + if(s->halt_on_cancel){ + DBG (15, "check_for_cancel: halting\n"); + ret = object_position (s, OP_Halt); + } + /* cancel scan */ + else{ + DBG (15, "check_for_cancel: cancelling\n"); ret = scanner_control(s, SC_function_cancel); - if (ret == SANE_STATUS_GOOD) { - ret = SANE_STATUS_CANCELLED; - } - else{ - DBG (5, "check_for_cancel: ERROR: cannot cancel\n"); - } + } - s->started = 0; - s->cancelled = 0; + if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_CANCELLED) { + ret = SANE_STATUS_CANCELLED; + } + else{ + DBG (5, "check_for_cancel: ERROR: cannot cancel\n"); + } + + s->started = 0; + s->cancelled = 0; } else if(s->cancelled){ DBG (15, "check_for_cancel: already cancelled\n"); @@ -7723,7 +7919,6 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len } } /* end 3091 */ -#ifdef SANE_FRAME_JPEG /* alternating jpeg duplex interlacing */ else if(s->source == SOURCE_ADF_DUPLEX && s->s_params.format == SANE_FRAME_JPEG @@ -7735,11 +7930,10 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len return ret; } } /* end alt jpeg */ -#endif /* alternating pnm duplex interlacing */ else if(s->source == SOURCE_ADF_DUPLEX - && s->s_params.format <= SANE_FRAME_RGB + && s->s_params.format != SANE_FRAME_JPEG && s->duplex_interlace == DUPLEX_INTERLACE_ALT ){ @@ -7808,7 +8002,33 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len return ret; } -#ifdef SANE_FRAME_JPEG +/* bare jpeg images dont contain resolution, but JFIF APP0 does, so we add */ +static SANE_Status +inject_jfif_header(struct fujitsu *s, int side) +{ + SANE_Status ret=SANE_STATUS_GOOD; + + unsigned char out[] = { + 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, + 0x00, 0x01, 0x02, 0x01, 0x00, 0x48, 0x00, 0x48, + 0x00, 0x00 + }; + size_t outLen=JFIF_APP0_LENGTH; + + DBG (10, "inject_jfif_header: start %d\n", side); + + putnbyte(out + 12, s->resolution_x, 2); + putnbyte(out + 14, s->resolution_y, 2); + + memcpy(s->buffers[side]+s->buff_rx[side], out, outLen); + s->buff_rx[side] += outLen; + s->bytes_rx[side] += outLen; + + DBG (10, "inject_jfif_header: finish %d\n", ret); + + return ret; +} + static SANE_Status read_from_JPEGduplex(struct fujitsu *s) { @@ -7834,13 +8054,21 @@ read_from_JPEGduplex(struct fujitsu *s) * so we only get enough to fill whichever is smaller (and not yet done) */ if(!s->eof_rx[SIDE_FRONT]){ int avail = s->buff_tot[SIDE_FRONT] - s->buff_rx[SIDE_FRONT]; - if(bytes > avail) + if(bytes > avail){ bytes = avail; + /* leave space for JFIF header at start of image */ + if(s->bytes_rx[SIDE_FRONT] < 2) + bytes -= JFIF_APP0_LENGTH; + } } if(!s->eof_rx[SIDE_BACK]){ int avail = s->buff_tot[SIDE_BACK] - s->buff_rx[SIDE_BACK]; - if(bytes > avail) + if(bytes > avail){ bytes = avail; + /* leave space for JFIF header at start of image */ + if(s->bytes_rx[SIDE_BACK] < 2) + bytes -= JFIF_APP0_LENGTH; + } } DBG(15, "read_from_JPEGduplex: fto:%d frx:%d bto:%d brx:%d pa:%d\n", @@ -7901,7 +8129,7 @@ read_from_JPEGduplex(struct fujitsu *s) for(i=0;i<(int)inLen;i++){ /* about to change stage */ - if(in[i] == 0xff){ + if(in[i] == 0xff && s->jpeg_ff_offset != 0){ s->jpeg_ff_offset=0; continue; } @@ -7909,9 +8137,21 @@ read_from_JPEGduplex(struct fujitsu *s) /* last byte was an ff, this byte will change stage */ if(s->jpeg_ff_offset == 0){ - /* headers (SOI/HuffTab/QTab/DRI), in both sides */ - if(in[i] == 0xd8 || in[i] == 0xc4 - || in[i] == 0xdb || in[i] == 0xdd){ + /* first marker after SOI is not APP0, add one */ + if(s->jpeg_stage == JPEG_STAGE_SOI && in[i] != 0xe0){ + inject_jfif_header(s,SIDE_FRONT); + inject_jfif_header(s,SIDE_BACK); + s->jpeg_stage = JPEG_STAGE_HEAD; + } + + /* SOI header, in both sides */ + if(in[i] == 0xd8){ + s->jpeg_stage = JPEG_STAGE_SOI; + DBG(15, "read_from_JPEGduplex: stage SOI\n"); + } + + /* headers (HuffTab/QTab/DRI), in both sides */ + else if(in[i] == 0xc4 || in[i] == 0xdb || in[i] == 0xdd){ s->jpeg_stage = JPEG_STAGE_HEAD; DBG(15, "read_from_JPEGduplex: stage head\n"); } @@ -7972,6 +8212,11 @@ read_from_JPEGduplex(struct fujitsu *s) s->jpeg_stage = JPEG_STAGE_EOI; DBG(15, "read_from_JPEGduplex: stage eoi %d %d\n",(int)inLen,i); } + + /* unknown, warn */ + else if(in[i] != 0xff){ + DBG(15, "read_from_JPEGduplex: unknown %02x\n", in[i]); + } } s->jpeg_ff_offset++; @@ -8025,7 +8270,8 @@ read_from_JPEGduplex(struct fujitsu *s) } /* copy these stages to front */ - if(s->jpeg_stage == JPEG_STAGE_HEAD + if(s->jpeg_stage == JPEG_STAGE_SOI + || s->jpeg_stage == JPEG_STAGE_HEAD || s->jpeg_stage == JPEG_STAGE_SOF || s->jpeg_stage == JPEG_STAGE_SOS || s->jpeg_stage == JPEG_STAGE_EOI @@ -8043,7 +8289,8 @@ read_from_JPEGduplex(struct fujitsu *s) /* copy these stages to back */ if( s->jpeg_interlace == JPEG_INTERLACE_ALT && - ( s->jpeg_stage == JPEG_STAGE_HEAD + ( s->jpeg_stage == JPEG_STAGE_SOI + || s->jpeg_stage == JPEG_STAGE_HEAD || s->jpeg_stage == JPEG_STAGE_SOF || s->jpeg_stage == JPEG_STAGE_SOS || s->jpeg_stage == JPEG_STAGE_EOI @@ -8086,7 +8333,6 @@ read_from_JPEGduplex(struct fujitsu *s) return ret; } -#endif static SANE_Status read_from_3091duplex(struct fujitsu *s) @@ -8267,6 +8513,10 @@ read_from_scanner(struct fujitsu *s, int side) if(bytes % 2 && bytes < remain){ bytes -= s->s_params.bytes_per_line; } + + /* jpeg scans leave space for JFIF header at start of image */ + if(s->s_params.format == SANE_FRAME_JPEG && s->bytes_rx[side] < 2) + bytes -= JFIF_APP0_LENGTH; DBG(15, "read_from_scanner: si:%d re:%d bs:%d by:%d av:%d\n", side, remain, s->buffer_size, bytes, avail); @@ -8341,6 +8591,9 @@ read_from_scanner(struct fujitsu *s, int side) if(s->s_mode==MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ copy_3091 (s, in, inLen, side); } + else if(s->s_params.format == SANE_FRAME_JPEG){ + copy_JPEG (s, in, inLen, side); + } else{ copy_buffer (s, in, inLen, side); } @@ -8453,6 +8706,48 @@ copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side) return ret; } +static SANE_Status +copy_JPEG(struct fujitsu *s, unsigned char * buf, int len, int side) +{ + SANE_Status ret=SANE_STATUS_GOOD; + int i, seen = 0; + + DBG (10, "copy_JPEG: start\n"); + + /* A jpeg image starts with the SOI marker, FF D8. + * This is optionally followed by the JFIF APP0 + * marker, FF E0. If that marker is not present, + * we add it, so we can insert the resolution */ + + if(!s->bytes_rx[side] && len >= 4 + && buf[0] == 0xFF && buf[1] == 0xD8 + && buf[2] == 0xFF && buf[3] != 0xE0 + ){ + /* SOI marker */ + for (i=0; i<2; i++){ + s->buffers[side][s->buff_rx[side]++] = buf[i]; + s->bytes_rx[side]++; + seen++; + } + + /* JFIF header after SOI */ + inject_jfif_header(s,side); + } + + memcpy(s->buffers[side]+s->buff_rx[side],buf+seen,len-seen); + s->buff_rx[side] += len-seen; + s->bytes_rx[side] += len-seen; + + /* should never happen with jpeg */ + if(s->bytes_rx[side] == s->bytes_tot[side]){ + s->eof_rx[side] = 1; + } + + DBG (10, "copy_JPEG: finish\n"); + + return ret; +} + static SANE_Status copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side) { @@ -8465,7 +8760,7 @@ copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side) /* invert image if scanner needs it for this mode */ /* jpeg data does not use inverting */ - if(s->s_params.format <= SANE_FRAME_RGB && s->reverse_by_mode[s->s_mode]){ + if(s->s_params.format != SANE_FRAME_JPEG && s->reverse_by_mode[s->s_mode]){ for(i=0; ifd, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen); @@ -9408,9 +9753,7 @@ must_fully_buffer(struct fujitsu *s) if( (s->swdeskew || s->swdespeck || s->swcrop || s->swskip) -#ifdef SANE_FRAME_JPEG && s->s_params.format != SANE_FRAME_JPEG -#endif ){ return 1; } @@ -9424,9 +9767,7 @@ static int must_downsample(struct fujitsu *s) { if(s->s_mode != s->u_mode -#ifdef SANE_FRAME_JPEG && s->compress != COMP_JPEG -#endif ){ return 1; } @@ -9492,6 +9833,23 @@ get_page_height(struct fujitsu *s) return height; } +/* s->max_y gives the maximum height of paper which can be scanned + * this actually varies by resolution, so a helper to change it */ +static int +set_max_y(struct fujitsu *s) +{ + int i; + + for(i=0;i<4;i++){ + if(!s->max_y_by_res[i].res) + break; + if(s->resolution_x <= s->max_y_by_res[i].res){ + s->max_y = s->max_y_by_res[i].len; + } + } + + return s->max_y; +} /** * Convenience method to determine longest string size in a list. @@ -9561,7 +9919,8 @@ hexdump (int level, char *comment, unsigned char *p, int l) } /* print last (partial) line */ - DBG (level, "%s\n", line); + if (i) + DBG (level, "%s\n", line); } /** @@ -9654,37 +10013,23 @@ buffer_crop(struct fujitsu *s, int side) DBG (10, "buffer_crop: start\n"); - /*only find edges on first image from a page, or if first image had error */ - if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->crop_stat){ - - s->crop_stat = sanei_magic_findEdges( - &s->s_params,s->buffers[side],s->resolution_x,s->resolution_y, - &s->crop_vals[0],&s->crop_vals[1],&s->crop_vals[2],&s->crop_vals[3]); + ret = sanei_magic_findEdges( + &s->s_params,s->buffers[side],s->resolution_x,s->resolution_y, + &s->crop_vals[0],&s->crop_vals[1],&s->crop_vals[2],&s->crop_vals[3]); - if(s->crop_stat){ - DBG (5, "buffer_crop: bad edges, bailing\n"); - goto cleanup; - } - - DBG (15, "buffer_crop: t:%d b:%d l:%d r:%d\n", - s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); - - /* we dont listen to the 'top' value, since fujitsu does not pad the top */ - s->crop_vals[0] = 0; - - /* if we will later binarize this image, make sure the width - * is a multiple of 8 pixels, by adjusting the right side */ - if ( must_downsample(s) && s->u_mode < MODE_GRAYSCALE ){ - s->crop_vals[3] -= (s->crop_vals[3]-s->crop_vals[2]) % 8; - } + if(ret){ + DBG (5, "buffer_crop: bad edges, bailing\n"); + ret = SANE_STATUS_GOOD; + goto cleanup; } - /* backside images can use a 'flipped' version of frontside data */ - else{ - int left = s->crop_vals[2]; - int right = s->crop_vals[3]; + + DBG (15, "buffer_crop: t:%d b:%d l:%d r:%d\n", + s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); - s->crop_vals[2] = s->s_params.pixels_per_line - right; - s->crop_vals[3] = s->s_params.pixels_per_line - left; + /* if we will later binarize this image, make sure the width + * is a multiple of 8 pixels, by adjusting the right side */ + if ( must_downsample(s) && s->u_mode < MODE_GRAYSCALE ){ + s->crop_vals[3] -= (s->crop_vals[3]-s->crop_vals[2]) % 8; } /* now crop the image */ diff --git a/backend/fujitsu.conf.in b/backend/fujitsu.conf.in index 8034f25..dc7a131 100644 --- a/backend/fujitsu.conf.in +++ b/backend/fujitsu.conf.in @@ -118,12 +118,6 @@ usb 0x04c5 0x119d #fi-6800-CGA usb 0x04c5 0x119e -#fi-6900 -usb 0x04c5 0x119f - -#fi-6900-CGA -usb 0x04c5 0x11a0 - #S1500 & S1500M usb 0x04c5 0x11a2 @@ -147,3 +141,15 @@ usb 0x04c5 0x1213 #ScanSnap iX500 usb 0x04c5 0x132b + +#fi-7180 +usb 0x04c5 0x132c + +#fi-7280 +usb 0x04c5 0x132d + +#fi-7160 +usb 0x04c5 0x132e + +#fi-7260 +usb 0x04c5 0x132f diff --git a/backend/fujitsu.h b/backend/fujitsu.h index 4c6804b..e1f7d68 100644 --- a/backend/fujitsu.h +++ b/backend/fujitsu.h @@ -72,6 +72,7 @@ enum fujitsu_Option OPT_DF_DIFF, OPT_DF_RECOVERY, OPT_PAPER_PROTECT, + OPT_ADV_PAPER_PROT, OPT_STAPLE_DETECT, OPT_BG_COLOR, OPT_DROPOUT_COLOR, @@ -79,6 +80,7 @@ enum fujitsu_Option OPT_PREPICK, OPT_OVERSCAN, OPT_SLEEP_TIME, + OPT_OFF_TIME, OPT_DUPLEX_OFFSET, OPT_GREEN_OFFSET, OPT_BLUE_OFFSET, @@ -89,6 +91,7 @@ enum fujitsu_Option OPT_SWDESPECK, OPT_SWCROP, OPT_SWSKIP, + OPT_HALT_ON_CANCEL, OPT_ENDORSER_GROUP, OPT_ENDORSER, @@ -127,6 +130,13 @@ enum fujitsu_Option NUM_OPTIONS }; +/* used to control the max page-height, which varies by resolution */ +struct y_size +{ + int res; + int len; +}; + struct fujitsu { /* --------------------------------------------------------------------- */ @@ -242,6 +252,7 @@ struct fujitsu int has_df_recovery; int has_paper_protect; + int has_adv_paper_prot; int has_staple_detect; int has_rif; @@ -257,6 +268,7 @@ struct fujitsu int has_ipc3; int has_rotation; int has_hybrid_crop_deskew; + int has_off_mode; int has_comp_MH; int has_comp_MR; @@ -265,6 +277,7 @@ struct fujitsu int has_comp_JPG1; int has_comp_JPG2; int has_comp_JPG3; + int has_op_halt; /*FIXME: more endorser data? */ int endorser_type_f; @@ -299,6 +312,7 @@ struct fujitsu /* the scan size in 1/1200th inches, NOT basic_units or sane units */ int max_x; int max_y; + struct y_size max_y_by_res[4]; int min_x; int min_y; int max_x_fb; @@ -313,6 +327,7 @@ struct fujitsu int window_gamma; int endorser_string_len; int has_pixelsize; + int has_short_pixelsize; /* m3091/2 put weird stuff at end, ignore it */ int broken_diag_serial; /* some scanners are just plain borked */ int need_q_table; /* some scanners wont work without these */ @@ -382,6 +397,7 @@ struct fujitsu SANE_String_Const df_diff_list[5]; SANE_String_Const df_recovery_list[4]; SANE_String_Const paper_protect_list[4]; + SANE_String_Const adv_paper_prot_list[4]; SANE_String_Const staple_detect_list[4]; SANE_String_Const bg_color_list[4]; SANE_String_Const do_color_list[5]; @@ -390,6 +406,7 @@ struct fujitsu SANE_String_Const prepick_list[4]; SANE_String_Const overscan_list[4]; SANE_Range sleep_time_range; + SANE_Range off_time_range; SANE_Range duplex_offset_range; SANE_Range green_offset_range; SANE_Range blue_offset_range; @@ -467,6 +484,7 @@ struct fujitsu int df_diff; int df_recovery; int paper_protect; + int adv_paper_prot; int staple_detect; int bg_color; int dropout_color; @@ -475,6 +493,7 @@ struct fujitsu int overscan; int lamp_color; int sleep_time; + int off_time; int duplex_offset; int green_offset; int blue_offset; @@ -484,6 +503,7 @@ struct fujitsu int swdespeck; int swcrop; double swskip; + int halt_on_cancel; /*endorser group*/ int u_endorser; @@ -514,8 +534,10 @@ struct fujitsu SANE_Parameters s_params; /* also keep a backup copy, in case the software enhancement code overwrites*/ + /* SANE_Parameters u_params_bk; SANE_Parameters s_params_bk; + */ /* --------------------------------------------------------------------- */ /* values which are set by scanning functions to keep track of pages, etc */ @@ -556,7 +578,6 @@ struct fujitsu int deskew_vals[2]; double deskew_slope; - SANE_Status crop_stat; int crop_vals[4]; /* --------------------------------------------------------------------- */ @@ -622,12 +643,16 @@ struct fujitsu #define COMP_NONE WD_cmp_NONE #define COMP_JPEG WD_cmp_JPG1 -#define JPEG_STAGE_HEAD 0 -#define JPEG_STAGE_SOF 1 -#define JPEG_STAGE_SOS 2 -#define JPEG_STAGE_FRONT 3 -#define JPEG_STAGE_BACK 4 -#define JPEG_STAGE_EOI 5 +#define JPEG_STAGE_NONE 0 +#define JPEG_STAGE_SOI 1 +#define JPEG_STAGE_HEAD 2 +#define JPEG_STAGE_SOF 3 +#define JPEG_STAGE_SOS 4 +#define JPEG_STAGE_FRONT 5 +#define JPEG_STAGE_BACK 6 +#define JPEG_STAGE_EOI 7 + +#define JFIF_APP0_LENGTH 18 /* these are same as scsi data to make code easier */ #define MODE_LINEART WD_comp_LA @@ -771,7 +796,7 @@ do_usb_cmd(struct fujitsu *s, int runRS, int shortTime, static SANE_Status wait_scanner (struct fujitsu *s); -static SANE_Status object_position (struct fujitsu *s, int i_load); +static SANE_Status object_position (struct fujitsu *s, int action); static SANE_Status scanner_control (struct fujitsu *s, int function); static SANE_Status scanner_control_ric (struct fujitsu *s, int bytes, int side); @@ -789,11 +814,13 @@ static SANE_Status mode_select_prepick (struct fujitsu *s); static SANE_Status mode_select_auto (struct fujitsu *s); static SANE_Status set_sleep_mode(struct fujitsu *s); +static SANE_Status set_off_mode(struct fujitsu *s); static int must_downsample (struct fujitsu *s); static int must_fully_buffer (struct fujitsu *s); static int get_page_width (struct fujitsu *s); static int get_page_height (struct fujitsu *s); +static int set_max_y (struct fujitsu *s); static SANE_Status send_lut (struct fujitsu *s); static SANE_Status send_endorser (struct fujitsu *s); @@ -803,19 +830,17 @@ static SANE_Status get_pixelsize(struct fujitsu *s, int actual); static SANE_Status update_params (struct fujitsu *s); static SANE_Status update_u_params (struct fujitsu *s); -static SANE_Status backup_params (struct fujitsu *s); -static SANE_Status restore_params (struct fujitsu *s); + static SANE_Status start_scan (struct fujitsu *s); static SANE_Status check_for_cancel(struct fujitsu *s); -#ifdef SANE_FRAME_JPEG static SANE_Status read_from_JPEGduplex(struct fujitsu *s); -#endif static SANE_Status read_from_3091duplex(struct fujitsu *s); static SANE_Status read_from_scanner(struct fujitsu *s, int side); static SANE_Status copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side); +static SANE_Status copy_JPEG(struct fujitsu *s, unsigned char * buf, int len, int side); static SANE_Status copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side); static SANE_Status read_from_buffer(struct fujitsu *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side); diff --git a/backend/genesys.c b/backend/genesys.c index 6e7caad..913a048 100644 --- a/backend/genesys.c +++ b/backend/genesys.c @@ -16,49 +16,49 @@ noah work in the fujitsu backend This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ /* * SANE backend for Genesys Logic GL646/GL841/GL842/GL843/GL846/GL847/GL124 based scanners */ -#define BUILD 2411 +#define BUILD 2504 #define BACKEND_NAME genesys #include "genesys.h" @@ -231,11 +231,11 @@ sanei_genesys_init_fe (Genesys_Device * dev) /* main function for slope creation */ /** - * This function generates a slope table using the given slope - * truncated at the given exposure time or step count, whichever comes first. + * This function generates a slope table using the given slope + * truncated at the given exposure time or step count, whichever comes first. * The reached step time is then stored in final_exposure and used for the rest * of the table. The summed time of the acceleration steps is returned, and the - * number of accerelation steps is put into used_steps. + * number of accerelation steps is put into used_steps. * * @param slope_table Table to write to * @param max_steps Size of slope_table in steps @@ -248,7 +248,7 @@ sanei_genesys_init_fe (Genesys_Device * dev) * @param used_steps Final number of steps is stored here * @param vfinal Final step time is stored here * @return Time for acceleration - * @note All times in pixel time. Correction for other motor timings is not + * @note All times in pixel time. Correction for other motor timings is not * done. */ SANE_Int @@ -339,10 +339,10 @@ sanei_genesys_generate_slope_table (uint16_t * slope_table, /* Generate slope table for motor movement */ /** * This function generates a slope table using the slope from the motor struct - * truncated at the given exposure time or step count, whichever comes first. + * truncated at the given exposure time or step count, whichever comes first. * The reached step time is then stored in final_exposure and used for the rest * of the table. The summed time of the acceleration steps is returned, and the - * number of accerelation steps is put into used_steps. + * number of accerelation steps is put into used_steps. * * @param dev Device struct * @param slope_table Table to write to @@ -412,7 +412,7 @@ sanei_genesys_create_slope_table3 (Genesys_Device * dev, if (final_exposure) *final_exposure = (vfinal * dev->motor.base_ydpi) / yres; - + DBG (DBG_proc, "sanei_genesys_create_slope_table: returns sum_time=%d, completed\n", sum_time); @@ -753,27 +753,26 @@ sanei_genesys_create_gamma_table (uint16_t * gamma_table, int size, } -/* computes the exposure_time on the basis of the given vertical dpi, +/* computes the exposure_time on the basis of the given vertical dpi, the number of pixels the ccd needs to send, the step_type and the corresponding maximum speed from the motor struct */ /* - Currently considers maximum motor speed at given step_type, minimum + Currently considers maximum motor speed at given step_type, minimum line exposure needed for conversion and led exposure time. TODO: Should also consider maximum transfer rate: ~6.5MB/s. - Note: The enhance option of the scanners does _not_ help. It only halves + Note: The enhance option of the scanners does _not_ help. It only halves the amount of pixels transfered. */ SANE_Int sanei_genesys_exposure_time2 (Genesys_Device * dev, float ydpi, int step_type, int endpixel, - int led_exposure, int power_mode) + int exposure_by_led, int power_mode) { int exposure_by_ccd = endpixel + 32; int exposure_by_motor = (dev->motor.slopes[power_mode][step_type].maximum_speed * dev->motor.base_ydpi) / ydpi; - int exposure_by_led = led_exposure; int exposure = exposure_by_ccd; @@ -783,6 +782,8 @@ sanei_genesys_exposure_time2 (Genesys_Device * dev, float ydpi, if (exposure < exposure_by_led && dev->model->is_cis) exposure = exposure_by_led; + DBG (DBG_info, "%s: ydpi=%d, step=%d, endpixel=%d led=%d, power=%d => exposure=%d\n", + __FUNCTION__, (int)ydpi, step_type, endpixel, exposure_by_led, power_mode, exposure); return exposure; } @@ -898,11 +899,11 @@ sanei_genesys_exposure_time (Genesys_Device * dev, Genesys_Register_Set * reg, -/* Sends a block of shading information to the scanner. - The data is placed at address 0x0000 for color mode, gray mode and +/* Sends a block of shading information to the scanner. + The data is placed at address 0x0000 for color mode, gray mode and unconditionally for the following CCD chips: HP2300, HP2400 and HP5345 - In the other cases (lineart, halftone on ccd chips not mentioned) the - addresses are 0x2a00 for dpihw==0, 0x5500 for dpihw==1 and 0xa800 for + In the other cases (lineart, halftone on ccd chips not mentioned) the + addresses are 0x2a00 for dpihw==0, 0x5500 for dpihw==1 and 0xa800 for dpihw==2. //Note: why this? The data needs to be of size "size", and in little endian byte order. @@ -918,10 +919,11 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data, int start_address; SANE_Status status; - DBG (DBG_proc, "genesys_send_offset_and_shading (size = %d)\n", size); + DBG (DBG_proc, "%s: (size = %d)\n", __FUNCTION__, size); /* ASIC higher than gl843 doesn't have register 2A/2B, so we route to - * a per ASIC shading data loading function if available */ + * a per ASIC shading data loading function if available. + * It is also used for scanners using SHDAREA */ if(dev->model->cmd_set->send_shading_data!=NULL) { status=dev->model->cmd_set->send_shading_data(dev, data, size); @@ -932,7 +934,7 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data, /* gl646, gl84[123] case */ dpihw = sanei_genesys_read_reg_from_set (dev->reg, 0x05) >> 6; - /* TODO invert the test so only the 2 models behaving like that are + /* TODO invert the test so only the 2 models behaving like that are * tested instead of adding all the others */ /* many scanners send coefficient for lineart/gray like in color mode */ if (dev->settings.scan_mode < 2 @@ -945,6 +947,7 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data, && dev->model->ccd_type != CCD_XP300 && dev->model->ccd_type != CCD_DP665 && dev->model->ccd_type != CCD_DP685 + && dev->model->ccd_type != CIS_CANONLIDE80 && dev->model->ccd_type != CCD_ROADWARRIOR && dev->model->ccd_type != CCD_HP2300 && dev->model->ccd_type != CCD_HP2400 @@ -966,17 +969,15 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data, status = sanei_genesys_set_buffer_address (dev, start_address); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "genesys_send_offset_and_shading: failed to set buffer address: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed to set buffer address: %s\n", __FUNCTION__, + sane_strstatus (status)); return status; } - + status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "genesys_send_offset_and_shading: failed to send shading table: %s\n", + DBG (DBG_error, "%s: failed to send shading table: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -1030,22 +1031,22 @@ sanei_genesys_init_shading_data (Genesys_Device * dev, int pixels_per_line) *shading_data_ptr++ = 0x40; /* white hi -> 0x4000 */ } - status = - genesys_send_offset_and_shading (dev, shading_data, - pixels_per_line * 4 * channels); - if (status != SANE_STATUS_GOOD) - DBG (DBG_error, - "sanei_genesys_init_shading_data: failed to send shading data: %s\n", - sane_strstatus (status)); - + status = genesys_send_offset_and_shading (dev, + shading_data, + pixels_per_line * 4 * channels); free (shading_data); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: failed to send shading data: %s\n", __FUNCTION__, + sane_strstatus (status)); + } DBGCOMPLETED; return status; } -/* Find the position of the reference point: +/* Find the position of the reference point: takes gray level 8 bits data and find first CCD usable pixel and top of scanning area */ SANE_Status @@ -1090,7 +1091,7 @@ sanei_genesys_search_reference_point (Genesys_Device * dev, uint8_t * data, if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("laplace.pnm", image, 8, 1, width, height); - /* apply X direction sobel filter + /* apply X direction sobel filter -1 0 1 -2 0 2 -1 0 1 @@ -1144,7 +1145,7 @@ sanei_genesys_search_reference_point (Genesys_Device * dev, uint8_t * data, start_pixel + (left * dev->sensor.optical_res) / dpi; /* find top edge by detecting black strip */ - /* apply Y direction sobel filter + /* apply Y direction sobel filter -1 -2 -1 0 0 0 1 2 1 @@ -1913,7 +1914,7 @@ genesys_dark_shading_calibration (Genesys_Device * dev) /* * this function builds dummy dark calibration data so that we can * compute shading coefficient in a clean way - * todo: current values are hardcoded, we have to find if they + * todo: current values are hardcoded, we have to find if they * can be computed from previous calibration data (when doing offset * calibration ?) */ @@ -2114,7 +2115,7 @@ genesys_white_shading_calibration (Genesys_Device * dev) sanei_genesys_write_pnm_file ("white_shading.pnm", calibration_data, 16, channels, pixels_per_line, dev->calib_lines); - + genesys_average_data (dev->white_average_data, calibration_data, dev->calib_lines, pixels_per_line * channels); @@ -2138,7 +2139,7 @@ genesys_white_shading_calibration (Genesys_Device * dev) return status; } } - + if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) { status = dev->model->cmd_set->slow_back_home (dev, SANE_TRUE); @@ -2149,10 +2150,13 @@ genesys_white_shading_calibration (Genesys_Device * dev) return status; } -/* This calibration uses a scan over the calibration target, comprising a +/* This calibration uses a scan over the calibration target, comprising a * black and a white strip. (So the motor must be on.) */ -static SANE_Status +#ifndef UNIT_TESTING +static +#endif +SANE_Status genesys_dark_white_shading_calibration (Genesys_Device * dev) { SANE_Status status; @@ -2167,8 +2171,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) SANE_Bool motor; - DBG (DBG_proc, "genesys_black_white_shading_calibration (lines = %d)\n", - (unsigned int)dev->calib_lines); + DBG (DBG_proc, "%s: (lines = %d)\n", __FUNCTION__, (unsigned int)dev->calib_lines); pixels_per_line = dev->calib_pixels; channels = dev->calib_channels; @@ -2181,8 +2184,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) dev->white_average_data = malloc (dev->average_size); if (!dev->white_average_data) { - DBG (DBG_error, - "genesys_dark_white_shading_calibration: failed to allocate average memory\n"); + DBG (DBG_error, "%s: failed to allocate white average memory\n", __FUNCTION__); return SANE_STATUS_NO_MEM; } @@ -2192,8 +2194,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) dev->dark_average_data = malloc (channels * 2 * pixels_per_line); if (!dev->dark_average_data) { - DBG (DBG_error, - "genesys_dark_white_shading_shading_calibration: failed to allocate average memory\n"); + DBG (DBG_error, "%s: failed to allocate dark average memory\n", __FUNCTION__); return SANE_STATUS_NO_MEM; } @@ -2202,8 +2203,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) calibration_data = malloc (size); if (!calibration_data) { - DBG (DBG_error, - "genesys_dark_white_shading_calibration: failed to allocate calibration memory\n"); + DBG (DBG_error, "%s: failed to allocate calibration memory\n", __FUNCTION__); return SANE_STATUS_NO_MEM; } @@ -2224,9 +2224,8 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { free (calibration_data); - DBG (DBG_error, - "genesys_dark_white_shading_calibration: failed to bulk write registers: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__, + sane_strstatus (status)); return status; } @@ -2235,8 +2234,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { free (calibration_data); - DBG (DBG_error, - "genesys_dark_white_shading_calibration: Failed to begin scan: %s\n", + DBG (DBG_error, "%s: failed to begin scan: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -2245,8 +2243,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { free (calibration_data); - DBG (DBG_error, - "genesys_dark_white_shading_calibration: Failed to read data: %s\n", + DBG (DBG_error, "%s: failed to read data: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -2255,16 +2252,26 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { free (calibration_data); - DBG (DBG_error, - "genesys_dark_white_shading_calibration: Failed to end scan: %s\n", + DBG (DBG_error, "%s: Failed to end scan: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) - sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data, - 16, channels, pixels_per_line, - dev->calib_lines); + { + if (dev->model->is_cis) + { + sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data, + 16, 1, pixels_per_line*channels, + dev->calib_lines); + } + else + { + sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data, + 16, channels, pixels_per_line, + dev->calib_lines); + } + } average_white = dev->white_average_data; @@ -2375,15 +2382,15 @@ compute_coefficient (unsigned int coeff, unsigned int target, unsigned int value * The dark/white shading is actually performed _after_ reducing * resolution via averaging. only dark/white shading data for what would be * first pixel at full resolution is used. - * + * * scanner raw input to output value calculation: * o=(i-off)*(gain/coeff) - * + * * from datasheet: * off=dark_average * gain=coeff*bright_target/(bright_average-dark_average) * works for dark_target==0 - * + * * what we want is these: * bright_target=(bright_average-off)*(gain/coeff) * dark_target=(dark_average-off)*(gain/coeff) @@ -2406,30 +2413,31 @@ static #endif void compute_averaged_planar (Genesys_Device * dev, - uint8_t * shading_data, - unsigned int pixels_per_line, - unsigned int words_per_color, - unsigned int channels, - unsigned int o, - unsigned int coeff, - unsigned int target_bright, - unsigned int target_dark) + uint8_t * shading_data, + unsigned int pixels_per_line, + unsigned int words_per_color, + unsigned int channels, + unsigned int o, + unsigned int coeff, + unsigned int target_bright, + unsigned int target_dark) { unsigned int x, i, j, br, dk, res, avgpixels, basepixels, val; + unsigned int fill,factor; + + DBG (DBG_info, "%s: pixels=%d, offset=%d\n", __FUNCTION__, pixels_per_line, o); - DBG (DBG_info, "%s: pixels=%d, offset=%d\n", __FUNCTION__, pixels_per_line, - o); /* initialize result */ memset (shading_data, 0xff, words_per_color * 3 * 2); - /* + /* strangely i can write 0x20000 bytes beginning at 0x00000 without overwriting slope tables - which begin at address 0x10000(for 1200dpi hw mode): memory is organized in words(2 bytes) instead of single bytes. explains quite some things */ /* - another one: the dark/white shading is actually performed _after_ reducing + another one: the dark/white shading is actually performed _after_ reducing resolution via averaging. only dark/white shading data for what would be first pixel at full resolution is used. */ @@ -2449,15 +2457,17 @@ compute_averaged_planar (Genesys_Device * dev, off = (dark_average*bright_target - bright_average*dark_target)/(bright_target - dark_target) gain = (bright_target - dark_target)/(bright_average - dark_average)*coeff */ - /* duplicate half-ccd logic */ res = dev->settings.xres; + + /* duplicate half-ccd logic */ if ((dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE) && dev->settings.xres <= dev->sensor.optical_res / 2) - res *= 2; /* scanner is using half-ccd mode */ - /*this should be evenly dividable */ + res *= 2; + + /* this should be evenly dividable */ basepixels = dev->sensor.optical_res / res; -/* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */ + /* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */ if (basepixels < 1) avgpixels = 1; else if (basepixels < 6) @@ -2473,11 +2483,24 @@ compute_averaged_planar (Genesys_Device * dev, else avgpixels = 15; + /* LiDE80 packs shading data */ + if(dev->model->ccd_type != CIS_CANONLIDE80) + { + factor=1; + fill=avgpixels; + } + else + { + factor=avgpixels; + fill=1; + } + DBG (DBG_info, "%s: averaging over %d pixels\n", __FUNCTION__, avgpixels); + DBG (DBG_info, "%s: packing factor is %d\n", __FUNCTION__, factor); + DBG (DBG_info, "%s: fill length is %d\n", __FUNCTION__, fill); for (x = 0; x <= pixels_per_line - avgpixels; x += avgpixels) { - if ((x + o) * 2 * 2 + 3 > words_per_color * 2) break; @@ -2514,59 +2537,47 @@ compute_averaged_planar (Genesys_Device * dev, 65535 * (target_bright - target_dark)) val = 65535; else - val = - (dk * target_bright - br * target_dark) / (target_bright - - target_dark); + { + val = (dk * target_bright - br * target_dark) / (target_bright - target_dark); + } -/*fill all pixels, even if only the last one is relevant*/ - for (i = 0; i < avgpixels; i++) + /*fill all pixels, even if only the last one is relevant*/ + for (i = 0; i < fill; i++) { - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j] = val & 0xff; - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j + 1] = val >> 8; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j] = val & 0xff; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 1] = val >> 8; } val = br - dk; if (65535 * val > (target_bright - target_dark) * coeff) - val = (coeff * (target_bright - target_dark)) / val; + { + val = (coeff * (target_bright - target_dark)) / val; + } else - val = 65535; + { + val = 65535; + } -/*fill all pixels, even if only the last one is relevant*/ - for (i = 0; i < avgpixels; i++) + /*fill all pixels, even if only the last one is relevant*/ + for (i = 0; i < fill; i++) { - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j + 2] = val & 0xff; - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j + 3] = val >> 8; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 2] = val & 0xff; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 3] = val >> 8; } } -/*fill remaining channels*/ + /* fill remaining channels */ for (j = channels; j < 3; j++) { - for (i = 0; i < avgpixels; i++) + for (i = 0; i < fill; i++) { - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j] = - shading_data[(x + o + i) * 2 * 2 + words_per_color * 0]; - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j + 1] = - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * 0 + 1]; - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j + 2] = - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * 0 + 2]; - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * j + 3] = - shading_data[(x + o + i) * 2 * 2 + - words_per_color * 2 * 0 + 3]; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j ] = shading_data[(x/factor + o + i) * 2 * 2 ]; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 1] = shading_data[(x/factor + o + i) * 2 * 2 + 1]; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 2] = shading_data[(x/factor + o + i) * 2 * 2 + 2]; + shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 3] = shading_data[(x/factor + o + i) * 2 * 2 + 3]; } } - } } @@ -2603,7 +2614,7 @@ compute_coefficients (Genesys_Device * dev, DBG (DBG_io, "compute_coefficients: pixels_per_line=%d, coeff=0x%04x\n", pixels_per_line, coeff); - + /* compute start & end values depending of the offset */ if (offset < 0) { @@ -2672,7 +2683,7 @@ compute_planar_coefficients (Genesys_Device * dev, unsigned int channels, unsigned int cmat[3], unsigned int offset, - unsigned int coeff, + unsigned int coeff, unsigned int target) { uint8_t *ptr; /* contains 16bit words in little endian */ @@ -2781,9 +2792,9 @@ compute_shifted_coefficients (Genesys_Device * dev, for (i = 0; i < avgpixels; i++) { for (j = 0; j < channels; j++) { - br_tmp[j] += (dev->white_average_data[((x + i) * channels + j) * 2] | + br_tmp[j] += (dev->white_average_data[((x + i) * channels + j) * 2] | (dev->white_average_data[((x + i) * channels + j) * 2 + 1] << 8)); - dk_tmp[i] += (dev->dark_average_data[((x + i) * channels + j) * 2] | + dk_tmp[i] += (dev->dark_average_data[((x + i) * channels + j) * 2] | (dev->dark_average_data[((x + i) * channels + j) * 2 + 1] << 8)); } } @@ -2826,7 +2837,7 @@ compute_shifted_coefficients (Genesys_Device * dev, } } -static SANE_Status +GENESYS_STATIC SANE_Status genesys_send_shading_coefficient (Genesys_Device * dev) { SANE_Status status; @@ -2869,19 +2880,27 @@ genesys_send_shading_coefficient (Genesys_Device * dev) break; } + /* special case, memory is aligned on 0x5400, this has yet to be explained */ + /* could be 0xa800 because sensor is truly 2400 dpi, then halved because + * we only set 1200 dpi */ + if(dev->model->ccd_type==CIS_CANONLIDE80) + { + words_per_color = 0x5400; + } + length = words_per_color * 3 * 2; + /* allocate computed size */ shading_data = malloc (length); if (!shading_data) { - DBG (DBG_error, - "genesys_send_shading_coefficient: failed to allocate memory\n"); + DBG (DBG_error, "%s: failed to allocate memory\n", __FUNCTION__); return SANE_STATUS_NO_MEM; } memset (shading_data, 0, length); /* TARGET/(Wn-Dn) = white gain -> ~1.xxx then it is multiplied by 0x2000 - or 0x4000 to give an integer + or 0x4000 to give an integer Wn = white average for column n Dn = dark average for column n */ @@ -2974,10 +2993,10 @@ genesys_send_shading_coefficient (Genesys_Device * dev) compute_coefficients (dev, shading_data, pixels_per_line, - 3, - cmat, - o, - coeff, + 3, + cmat, + o, + coeff, target_code); break; case CCD_HP3670: @@ -2999,10 +3018,10 @@ genesys_send_shading_coefficient (Genesys_Device * dev) compute_coefficients (dev, shading_data, pixels_per_line, - 3, - cmat, - o, - coeff, + 3, + cmat, + o, + coeff, target_code); break; case CCD_KVSS080: @@ -3015,10 +3034,10 @@ genesys_send_shading_coefficient (Genesys_Device * dev) compute_coefficients (dev, shading_data, pixels_per_line, - 3, - cmat, - o, - coeff, + 3, + cmat, + o, + coeff, target_code); break; case CIS_CANONLIDE700: @@ -3039,8 +3058,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev) shading_data = malloc (length); if (!shading_data) { - DBG (DBG_error, - "genesys_send_shading_coefficient: failed to allocate memory\n"); + DBG (DBG_error, "%s: failed to allocate memory\n", __FUNCTION__); return SANE_STATUS_NO_MEM; } memset (shading_data, 0, length); @@ -3063,9 +3081,20 @@ genesys_send_shading_coefficient (Genesys_Device * dev) channels, 4, coeff, - 0xfa00, + 0xe000, 0x0a00); break; + case CIS_CANONLIDE80: + compute_averaged_planar (dev, + shading_data, + pixels_per_line, + words_per_color, + channels, + 0, + coeff, + 0xd000, + 0x0800); + break; case CCD_PLUSTEK_3600: compute_shifted_coefficients (dev, shading_data, @@ -3079,23 +3108,21 @@ genesys_send_shading_coefficient (Genesys_Device * dev) 256); /* patch_size: contigous extent */ break; default: - DBG (DBG_error, - "genesys_send_shading_coefficient: sensor %d not supported\n", - dev->model->ccd_type); + DBG (DBG_error, "%s: sensor %d not supported\n", __FUNCTION__, dev->model->ccd_type); return SANE_STATUS_UNSUPPORTED; break; } /* do the actual write of shading calibration data to the scanner */ status = genesys_send_offset_and_shading (dev, shading_data, length); + free (shading_data); if (status != SANE_STATUS_GOOD) - DBG (DBG_error, - "genesys_send_shading_coefficient: failed to send shading data: %s\n", - sane_strstatus (status)); + { + DBG (DBG_error, "%s: failed to send shading data: %s\n", __FUNCTION__, + sane_strstatus (status)); + } - free (shading_data); DBGCOMPLETED; - return SANE_STATUS_GOOD; } @@ -3125,7 +3152,7 @@ genesys_restore_calibration (Genesys_Device * dev) for (cache = dev->calibration_cache; cache; cache = cache->next) { status = dev->model->cmd_set->is_compatible_calibration (dev, cache, SANE_FALSE); - /* SANE_STATUS_GOOD, a matching cache has been found + /* SANE_STATUS_GOOD, a matching cache has been found * so we use it to populate calibration data */ if (status == SANE_STATUS_GOOD) @@ -3270,7 +3297,7 @@ genesys_save_calibration (Genesys_Device * dev) * @param dev device to calibrate * @return SANE_STATUS_GOOD if everything when all right, else the error code. */ -static SANE_Status +GENESYS_STATIC SANE_Status genesys_flatbed_calibration (Genesys_Device * dev) { SANE_Status status; @@ -3514,7 +3541,7 @@ genesys_sheetfed_calibration (Genesys_Device * dev) xres = dev->sensor.optical_res; dev->settings.xres = dev->sensor.optical_res; /* XP200 needs to calibrate a full and half sensor's resolution */ - if (dev->model->ccd_type == CIS_XP200 + if (dev->model->ccd_type == CIS_XP200 && dev->settings.xres <= dev->sensor.optical_res / 2) dev->settings.xres /= 2; @@ -3590,7 +3617,7 @@ genesys_sheetfed_calibration (Genesys_Device * dev) } } - /* search for a full width black strip and then do a 16 bit scan to + /* search for a full width black strip and then do a 16 bit scan to * gather black shading data */ if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) { @@ -3649,8 +3676,7 @@ genesys_sheetfed_calibration (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { dev->model->cmd_set->eject_document (dev); - DBG (DBG_error, - "genesys_sheetfed_calibration: failed eject target: %s\n", + DBG (DBG_error, "%s: failed eject target: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -3935,7 +3961,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) return status; } } - + /* disable power saving*/ status = dev->model->cmd_set->save_power (dev, SANE_FALSE); if (status != SANE_STATUS_GOOD) @@ -4077,7 +4103,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) status = sanei_genesys_load_lut(dev->lineart_lut, 8, 8, 50, 205, dev->settings.threshold_curve, dev->settings.threshold-127); - if (status != SANE_STATUS_GOOD) + if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to build lut\n"); return status; @@ -4094,11 +4120,11 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) } /* no lamp during scan */ - if(lamp_off == SANE_TRUE) + if(lamp_off == SANE_TRUE) { dev->model->cmd_set->set_lamp_power (dev, dev->reg, SANE_FALSE); } - + /* GL124 is using SHDAREA, so we have to wait for scan to be set up before * sending shading data */ if( (dev->model->cmd_set->send_shading_data!=NULL) @@ -4140,7 +4166,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) /*do we really need this? the valid data check should be sufficent -- pierre*/ /* waits for head to reach scanning position */ expected = sanei_genesys_read_reg_from_set (dev->reg, 0x3d) * 65536 - + sanei_genesys_read_reg_from_set (dev->reg, 0x3e) * 256 + + sanei_genesys_read_reg_from_set (dev->reg, 0x3e) * 256 + sanei_genesys_read_reg_from_set (dev->reg, 0x3f); do { @@ -4157,7 +4183,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) } } while (steps < expected); - + /* wait for buffers to be filled */ do { @@ -4173,7 +4199,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) else usleep (500 * 1000); */ - /* then we wait for at least one word of valid scan data + /* then we wait for at least one word of valid scan data this is also done in sanei_genesys_read_data_from_scanner -- pierre */ if (dev->model->is_sheetfed == SANE_FALSE) @@ -4192,12 +4218,12 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) } while (steps < 1); } - + DBGCOMPLETED; return SANE_STATUS_GOOD; } -/* this is _not_ a ringbuffer. +/* this is _not_ a ringbuffer. if we need a block which does not fit at the end of our available data, we move the available data to the beginning. */ @@ -4294,7 +4320,7 @@ static SANE_Status accurate_line_read(Genesys_Device * dev, * must be read and bytes interleaved to get usable by the other stages * of the backend */ -static SANE_Status +static SANE_Status genesys_fill_line_interp_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, size_t size) { size_t count; @@ -4313,7 +4339,7 @@ genesys_fill_line_interp_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, } } - /* copy size bytes of data, copying from a line when line count matches */ + /* copy size bytes of data, copying from a line when line count matches */ count = 0; while (count < size) { @@ -4344,7 +4370,7 @@ genesys_fill_line_interp_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "%s: failed to read %lu bytes (%s)\n", __FUNCTION__, + "%s: failed to read %lu bytes (%s)\n", __FUNCTION__, (u_long) dev->oe_buffer.size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } @@ -4356,17 +4382,17 @@ genesys_fill_line_interp_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, /** @brief fill buffer for segmented sensors * This function fills a read buffer with scanned data from a sensor segmented - * in several parts (multi-lines sensors). Data of the same valid area is read + * in several parts (multi-lines sensors). Data of the same valid area is read * back to back and must be interleaved to get usable by the other stages * of the backend */ -static SANE_Status +static SANE_Status genesys_fill_segmented_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, size_t size) { size_t count; SANE_Status status; int depth,i,n,k; - + depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart==SANE_FALSE) depth = 1; @@ -4397,12 +4423,12 @@ genesys_fill_segmented_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, s count++; dev->cur++; } - else + else { if(depth==1) { while (dev->cur < dev->len && count < size) - { + { for(n=0;nsegnb;n++) { work_buffer_dst[count+n] = 0; @@ -4429,7 +4455,7 @@ genesys_fill_segmented_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, s if(depth==8) { while (dev->cur < dev->len && count < size) - { + { for(n=0;nsegnb;n++) { work_buffer_dst[count+n] = dev->oe_buffer.buffer[dev->cur + dev->skip + dev->dist*dev->order[n] + dev->oe_buffer.pos]; @@ -4442,7 +4468,7 @@ genesys_fill_segmented_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, s if(depth==16) { while (dev->cur < dev->len && count < size) - { + { for(n=0;nsegnb;n++) { work_buffer_dst[count+n*2] = dev->oe_buffer.buffer[dev->cur + dev->skip + dev->dist*dev->order[n] + dev->oe_buffer.pos]; @@ -4469,7 +4495,7 @@ genesys_fill_segmented_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, s if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "%s: failed to read %lu bytes (%s)\n", __FUNCTION__, + "%s: failed to read %lu bytes (%s)\n", __FUNCTION__, (u_long) dev->oe_buffer.size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } @@ -4508,7 +4534,7 @@ genesys_fill_read_buffer (Genesys_Device * dev) size = space; - /* never read an odd number. exception: last read + /* never read an odd number. exception: last read the chip internal counter does not count half words. */ size &= ~1; /* Some setups need the reads to be multiples of 256 bytes */ @@ -4536,10 +4562,10 @@ genesys_fill_read_buffer (Genesys_Device * dev) * may have to be read from another intermediate buffer and then processed. * There are currently 3 intermediate stages: * - handling of odd/even sensors - * - handling of line interpolation for motors that can't have low + * - handling of line interpolation for motors that can't have low * enough dpi * - handling of multi-segments sensors - * + * * This is also the place where full duplex data will be handled. */ if (dev->line_interp>0) @@ -4576,8 +4602,8 @@ genesys_fill_read_buffer (Genesys_Device * dev) return SANE_STATUS_GOOD; } -/* this function does the effective data read in a manner that suits - the scanner. It does data reordering and resizing if need. +/* this function does the effective data read in a manner that suits + the scanner. It does data reordering and resizing if need. It also manages EOF and I/O errors, and line distance correction. */ static SANE_Status @@ -4736,14 +4762,14 @@ genesys_read_ordered_data (Genesys_Device * dev, SANE_Byte * destination, -------------- out_buffer ----------------------- 4. memcpy to destination (for lineart with bit reversal) */ -/*FIXME: for lineart we need sub byte addressing in buffers, or conversion to +/*FIXME: for lineart we need sub byte addressing in buffers, or conversion to bytes at 0. and back to bits at 4. Problems with the first approach: - its not clear how to check if we need to output an incomplete byte because it is the last one. */ -/*FIXME: add lineart support for gl646. in the meantime add logic to convert - from gray to lineart at the end? would suffer the above problem, +/*FIXME: add lineart support for gl646. in the meantime add logic to convert + from gray to lineart at the end? would suffer the above problem, total_bytes_to_read and total_bytes_read help in that case. */ @@ -5061,7 +5087,7 @@ Problems with the first approach: dev->total_bytes_read += *len; RIE (sanei_genesys_buffer_consume (src_buffer, bytes)); - + /* end scan if all needed data have been read */ if(dev->total_bytes_read >= dev->total_bytes_to_read) { @@ -5149,11 +5175,11 @@ calc_parameters (Genesys_Scanner * s) /* we need an even pixels number * TODO invert test logic or generalize behaviour across all ASICs */ if ((s->dev->model->flags & GENESYS_FLAG_SIS_SENSOR) - || s->dev->model->asic_type == GENESYS_GL847 - || s->dev->model->asic_type == GENESYS_GL124 - || s->dev->model->asic_type == GENESYS_GL845 - || s->dev->model->asic_type == GENESYS_GL846 - || s->dev->model->asic_type == GENESYS_GL843) + || s->dev->model->asic_type == GENESYS_GL847 + || s->dev->model->asic_type == GENESYS_GL124 + || s->dev->model->asic_type == GENESYS_GL845 + || s->dev->model->asic_type == GENESYS_GL846 + || s->dev->model->asic_type == GENESYS_GL843) { if (s->dev->settings.xres <= 1200) s->params.pixels_per_line = (s->params.pixels_per_line/4)*4; @@ -5164,7 +5190,7 @@ calc_parameters (Genesys_Scanner * s) /* corner case for true lineart for sensor with several segments * or when xres is doubled to match yres */ if (s->dev->settings.xres >= 1200 - && ( s->dev->model->asic_type == GENESYS_GL124 + && ( s->dev->model->asic_type == GENESYS_GL124 || s->dev->model->asic_type == GENESYS_GL847 || s->dev->current_setup.xres < s->dev->current_setup.yres ) @@ -5182,7 +5208,7 @@ calc_parameters (Genesys_Scanner * s) else if (s->params.depth == 1) { s->params.bytes_per_line /= 8; - /* round down pixel number + /* round down pixel number really? rounding down means loss of at most 7 pixels! -- pierre */ s->params.pixels_per_line = 8 * s->params.bytes_per_line; } @@ -5241,21 +5267,21 @@ calc_parameters (Genesys_Scanner * s) /* hardware lineart works only when we don't have interleave data * for GL847 scanners, ie up to 600 DPI, then we have to rely on * dynamic_lineart */ - if(s->dev->settings.xres > 600 + if(s->dev->settings.xres > 600 && s->dev->model->asic_type==GENESYS_GL847 && s->dev->settings.scan_mode == SCAN_MODE_LINEART) { s->dev->settings.dynamic_lineart = SANE_TRUE; } - + /* threshold curve for dynamic rasterization */ s->dev->settings.threshold_curve=s->val[OPT_THRESHOLD_CURVE].w; /* some digital processing requires the whole picture to be buffered */ /* no digital processing takes place when doing preview, or when bit depth is * higher than 8 bits */ - if ((s->val[OPT_SWDESPECK].b - || s->val[OPT_SWCROP].b + if ((s->val[OPT_SWDESPECK].b + || s->val[OPT_SWCROP].b || s->val[OPT_SWDESKEW].b || s->val[OPT_SWDEROTATE].b ||(SANE_UNFIX(s->val[OPT_SWSKIP].w)>0)) @@ -5339,7 +5365,7 @@ init_gamma_vector_option (Genesys_Scanner * scanner, int option) scanner->val[option].wa = NULL; } -/** +/** * allocate a geometry range * @param size maximum size of the range * @return a pointer to a valid range or NULL @@ -5358,6 +5384,107 @@ SANE_Range *range=NULL; return range; } +/** @brief generate calibration cache file nam + * Generates the calibration cache file name to use. + * Tries to store the chache in $HOME/.sane or + * then fallbacks to $TMPDIR or TMP. The filename + * uses the model name if only one scanner is plugged + * else is uses the device name when several identical + * scanners are in use. + * @param currdev current scanner device + * @return an allocated string containing a file name + */ +GENESYS_STATIC char *calibration_filename(Genesys_Device *currdev) +{ + char *tmpstr; + char *ptr; + char filename[80]; + Genesys_Device *dev; + unsigned int count; + unsigned int i; + + /* allocate space for result */ + tmpstr=malloc(PATH_MAX); + if(tmpstr==NULL) + { + return NULL; + } + + /* first compute the DIR where we can store cache: + * 1 - home dir + * 2 - $TMPDIR + * 3 - $TMP + * 4 - tmp dir + * 5 - temp dir + * 6 - then resort to current dir + */ + ptr = getenv ("HOME"); + if(ptr==NULL) + { + ptr = getenv ("USERPROFILE"); + } + if(ptr==NULL) + { + ptr = getenv ("TMPDIR"); + } + if(ptr==NULL) + { + ptr = getenv ("TMP"); + } + + /* now choose filename: + * 1 - if only one scanner, name of the model + * 2 - if several scanners of the same model, use device name, + * replacing special chars + */ + count=0; + /* count models of the same names if several scanners attached */ + if(num_devices>1) + { + for (dev = first_dev; dev; dev = dev->next) + { + if(strcmp(dev->model->name,currdev->model->name)==0) + { + count++; + } + } + } + if(count>1) + { + snprintf(filename,sizeof(filename),"%s.cal",currdev->file_name); + for(i=0;imodel->name); + } + + /* build final final name : store dir + filename */ + if (NULL == ptr) + { + snprintf (tmpstr, PATH_MAX, "%s", filename); + } + else + { +#ifdef HAVE_MKDIR + /* make sure .sane directory exists in existing store dir */ + snprintf (tmpstr, PATH_MAX, "%s%c.sane", ptr, PATH_SEP); + mkdir(tmpstr,0700); +#endif + snprintf (tmpstr, PATH_MAX, "%s%c.sane%c%s", ptr, PATH_SEP, PATH_SEP, filename); + } + + DBG (DBG_info, "%s: calibration filename >%s<\n", __FUNCTION__, tmpstr); + + return tmpstr; +} + static SANE_Status init_options (Genesys_Scanner * s) @@ -5412,13 +5539,13 @@ init_options (Genesys_Scanner * s) s->opt[OPT_SOURCE].size = max_string_size (source_list); s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].s = strdup (FLATBED); - if (!(model->flags & GENESYS_FLAG_HAS_UTA)) + if (model->flags & GENESYS_FLAG_HAS_UTA) { - DISABLE (OPT_SOURCE); + ENABLE (OPT_SOURCE); } else { - ENABLE (OPT_SOURCE); + DISABLE (OPT_SOURCE); } /* preview */ @@ -5578,7 +5705,7 @@ init_options (Genesys_Scanner * s) DBG (DBG_info, "init_options: custom gamma disabled\n"); } - /* software base image enhancements, these are consuming as many + /* software base image enhancements, these are consuming as many * memory than used by the full scanned image and may fail at high * resolution */ @@ -5589,7 +5716,7 @@ init_options (Genesys_Scanner * s) s->opt[OPT_SWDESKEW].type = SANE_TYPE_BOOL; s->opt[OPT_SWDESKEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; s->val[OPT_SWDESKEW].b = SANE_FALSE; - + /* software deskew */ s->opt[OPT_SWDESPECK].name = "swdespeck"; s->opt[OPT_SWDESPECK].title = "Software despeck"; @@ -5680,7 +5807,7 @@ init_options (Genesys_Scanner * s) s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &percentage_range; s->val[OPT_THRESHOLD].w = SANE_FIX (50); - + /* BW threshold curve */ s->opt[OPT_THRESHOLD_CURVE].name = "threshold-curve"; s->opt[OPT_THRESHOLD_CURVE].title = SANE_I18N ("Threshold curve"); @@ -5690,7 +5817,7 @@ init_options (Genesys_Scanner * s) s->opt[OPT_THRESHOLD_CURVE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_CURVE].constraint.range = &threshold_curve_range; s->val[OPT_THRESHOLD_CURVE].w = 50; - + /* dynamic linart */ s->opt[OPT_DISABLE_DYNAMIC_LINEART].name = "disable-dynamic-lineart"; s->opt[OPT_DISABLE_DYNAMIC_LINEART].title = SANE_I18N ("Disable dynamic lineart"); @@ -5890,7 +6017,7 @@ init_options (Genesys_Scanner * s) s->opt[OPT_POWER_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_POWER_SW].b = 0; s->last_val[OPT_POWER_SW].b = 0; - + /* extra button */ s->opt[OPT_EXTRA_SW].name = "extra"; s->opt[OPT_EXTRA_SW].title = SANE_I18N ("Extra button"); @@ -5971,13 +6098,24 @@ check_present (SANE_String_Const devname) return SANE_STATUS_GOOD; } +/** @brief add a scanner device + * Insert the given device into the backend list of devices. + * @param dev device to add + */ +GENESYS_STATIC void add_device(Genesys_Device *dev) +{ + ++num_devices; + dev->next = first_dev; + first_dev = dev; +} + static SANE_Status attach (SANE_String_Const devname, Genesys_Device ** devp, SANE_Bool may_wait) { Genesys_Device *dev = 0; SANE_Int dn, vendor, product; SANE_Status status; - int i; + unsigned int i; DBG (DBG_proc, "attach: start: devp %s NULL, may_wait = %d\n", @@ -6061,7 +6199,10 @@ attach (SANE_String_Const devname, Genesys_Device ** devp, SANE_Bool may_wait) dev->file_name = strdup (devname); if (!dev->file_name) - return SANE_STATUS_NO_MEM; + { + free(dev); + return SANE_STATUS_NO_MEM; + } dev->model = genesys_usb_device_list[i].model; dev->vendorId = genesys_usb_device_list[i].vendor; @@ -6070,9 +6211,7 @@ attach (SANE_String_Const devname, Genesys_Device ** devp, SANE_Bool may_wait) DBG (DBG_info, "attach: found %s flatbed scanner %s at %s\n", dev->model->vendor, dev->model->model, dev->file_name); - ++num_devices; - dev->next = first_dev; - first_dev = dev; + add_device(dev); if (devp) *devp = dev; @@ -6125,8 +6264,8 @@ attach_one_device (SANE_String_Const devname) static SANE_Status config_attach_genesys (SANEI_Config __sane_unused__ *config, const char *devname) { - /* the devname has been processed and is ready to be used - * directly. Since the backend is an USB only one, we can + /* the devname has been processed and is ready to be used + * directly. Since the backend is an USB only one, we can * call sanei_usb_attach_matching_devices straight */ sanei_usb_attach_matching_devices (devname, attach_one_device); @@ -6164,15 +6303,17 @@ probe_genesys_devices (void) free (new_dev); } + DBG(DBG_info, "%s: %d devices currently attached\n", __FUNCTION__, num_devices); + DBGCOMPLETED; return status; } /** - * This should be changed if one of the substructures of + * This should be changed if one of the substructures of Genesys_Calibration_Cache change, but it must be changed if there are - changes that don't change size -- at least for now, as we store most + changes that don't change size -- at least for now, as we store most of Genesys_Calibration_Cache as is. */ #define CALIBRATION_VERSION 1 @@ -6630,7 +6771,7 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) first_dev = dev->next; num_devices--; free (dev); - dev = prev->next; + dev = first_dev; } } /* case 2 : removed device is not first_dev */ @@ -6661,8 +6802,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) Genesys_Device *dev; SANE_Status status; Genesys_Scanner *s; - char tmp_str[PATH_MAX]; - char *ptr; + char *tmpstr; DBG (DBG_proc, "sane_open: start (devicename = `%s')\n", devicename); @@ -6768,37 +6908,16 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) RIE (dev->model->cmd_set->init (dev)); - /* here is the place to fetch a stored calibration cache */ - - /* create calibration-filename - lifted from plustek-usb.c - */ - /* we should add a unique identifying feature to the file name - to support multiple scanners of the same model, but to my - knowledge, there is no such thing in these scanners. - (At least the usb serial is always "0".) - TODO add an storedir option to genesys.conf - */ + /* some hardware capabilities are detected through sensors */ + RIE (s->dev->model->cmd_set->update_hardware_sensors (s)); - ptr = getenv ("HOME"); - if (NULL == ptr) - { - sprintf (tmp_str, "/tmp/%s.cal", s->dev->model->name); - } - else - { -#ifdef HAVE_MKDIR - /* make sure .sane directory exists */ - sprintf (tmp_str, "%s/.sane", ptr); - mkdir(tmp_str,0700); -#endif - sprintf (tmp_str, "%s/.sane/%s.cal", ptr, s->dev->model->name); - } - - s->val[OPT_CALIBRATION_FILE].s = strdup (tmp_str); - s->dev->calib_file = strdup (tmp_str); + /* here is the place to fetch a stored calibration cache */ + tmpstr=calibration_filename(s->dev); + s->val[OPT_CALIBRATION_FILE].s = strdup (tmpstr); + s->dev->calib_file = strdup (tmpstr); DBG (DBG_info, "Calibration filename set to:\n"); DBG (DBG_info, ">%s<\n", s->dev->calib_file); + free(tmpstr); /* now open file, fetch calibration records */ @@ -6860,7 +6979,7 @@ sane_close (SANE_Handle handle) "sane_close: failed to enable power saving mode: %s\n", sane_strstatus (status)); } - + /* here is the place to store calibration cache */ write_calibration (s->dev); @@ -6903,13 +7022,12 @@ sane_close (SANE_Handle handle) /* LAMP OFF : same register across all the ASICs */ sanei_genesys_write_register (s->dev, 0x03, 0x00); - /* we need this to avoid ASIC getting stuck + /* clear before closing */ + sanei_usb_clear_halt (s->dev->dn); + + /* we need this to avoid these ASIC getting stuck * in bulk writes */ - if(s->dev->model->asic_type==GENESYS_GL847 - ||s->dev->model->asic_type==GENESYS_GL845 - ||s->dev->model->asic_type==GENESYS_GL845 - ||s->dev->model->asic_type==GENESYS_GL843) - sanei_usb_reset (s->dev->dn); + sanei_usb_reset (s->dev->dn); sanei_usb_close (s->dev->dn); free (s); @@ -7082,7 +7200,7 @@ static SANE_Status set_calibration_value (Genesys_Scanner * s, int option, void tmp=dev->calib_file; dev->calib_file=val; status=sanei_genesys_read_calibration (dev); - + /* file exists but is invalid */ if (status!=SANE_STATUS_IO_ERROR && status!=SANE_STATUS_GOOD) { @@ -7617,27 +7735,27 @@ sane_start (SANE_Handle handle) return status; } } - + /* deskew image if required */ if(s->val[OPT_SWDESKEW].b == SANE_TRUE) { RIE(genesys_deskew(s)); } - + /* despeck image if required */ if(s->val[OPT_SWDESPECK].b == SANE_TRUE) { RIE(genesys_despeck(s)); } - + /* crop image if required */ - if(s->val[OPT_SWCROP].b == SANE_TRUE) + if(s->val[OPT_SWCROP].b == SANE_TRUE) { RIE(genesys_crop(s)); } - + /* de-rotate image if required */ - if(s->val[OPT_SWDEROTATE].b == SANE_TRUE) + if(s->val[OPT_SWDEROTATE].b == SANE_TRUE) { RIE(genesys_derotate(s)); } @@ -7661,7 +7779,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, DBG (DBG_error, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } - + dev=s->dev; if (!dev) { @@ -7694,7 +7812,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, DBG (DBG_io2, "sane_read: bytes_to_read=%lu, total_bytes_read=%lu\n", (u_long) dev->total_bytes_to_read, (u_long) dev->total_bytes_read); DBG (DBG_io2, "sane_read: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); - + if(dev->total_bytes_read>=dev->total_bytes_to_read) { DBG (DBG_proc, "sane_read: nothing more to scan: EOF\n"); @@ -7776,11 +7894,11 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, *len = local_len; if(local_len>(size_t)max_len) { - fprintf (stderr, "[genesys] sane_read: returning incorrect length!!\n"); + fprintf (stderr, "[genesys] sane_read: returning incorrect length!!\n"); } DBG (DBG_proc, "sane_read: %d bytes returned\n", *len); return status; -} +} void sane_cancel (SANE_Handle handle) diff --git a/backend/genesys.conf.in b/backend/genesys.conf.in index 58cb351..5300787 100644 --- a/backend/genesys.conf.in +++ b/backend/genesys.conf.in @@ -36,6 +36,9 @@ usb 0x04a9 0x2213 # Canon LiDE 60 usb 0x04a9 0x221c +# Canon LiDE 80 +usb 0x04a9 0x2214 + # Canon 4400F usb 0x04a9 0x2228 diff --git a/backend/genesys.h b/backend/genesys.h index 4d5fd94..fea3f3b 100644 --- a/backend/genesys.h +++ b/backend/genesys.h @@ -4,44 +4,44 @@ Copyright (C) 2005-2013 Stephane Voltz Copyright (C) 2006 Laurent Charpentier Copyright (C) 2009 Pierre Willenbrock - + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #ifndef GENESYS_H @@ -49,6 +49,16 @@ #include "genesys_low.h" +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +#if defined(_WIN32) || defined(HAVE_OS2_H) +# define PATH_SEP '\\' +#else +# define PATH_SEP '/' +#endif + #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE @@ -146,4 +156,9 @@ typedef struct Genesys_Scanner SANE_Int bpp_list[5]; /**< */ } Genesys_Scanner; +#ifdef UNIT_TESTING +SANE_Status genesys_dark_white_shading_calibration (Genesys_Device * dev); +char *calibration_filename(Genesys_Device *currdev); +void add_device(Genesys_Device *dev); +#endif #endif /* not GENESYS_H */ diff --git a/backend/genesys_conv.c b/backend/genesys_conv.c index 61ac782..0346ad6 100644 --- a/backend/genesys_conv.c +++ b/backend/genesys_conv.c @@ -4,42 +4,42 @@ Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ /* @@ -79,9 +79,9 @@ static SANE_Status genesys_reverse_bits( - uint8_t *src_data, - uint8_t *dst_data, - size_t bytes) + uint8_t *src_data, + uint8_t *dst_data, + size_t bytes) { size_t i; for(i = 0; i < bytes; i++) { @@ -105,7 +105,7 @@ binarize_line(Genesys_Device * dev, uint8_t *src, uint8_t *dst, int width) int thresh; int offset, addCol, dropCol; unsigned char mask; - + int x; uint8_t min, max; @@ -186,8 +186,8 @@ binarize_line(Genesys_Device * dev, uint8_t *src, uint8_t *dst, int width) static SANE_Status genesys_gray_lineart( Genesys_Device *dev, - uint8_t *src_data, - uint8_t *dst_data, + uint8_t *src_data, + uint8_t *dst_data, size_t pixels, size_t lines, uint8_t threshold) @@ -211,14 +211,14 @@ genesys_gray_lineart( * or grows it in case it is the opposite like when motor resolution is higher than * sensor's one. */ -static SANE_Status +static SANE_Status genesys_shrink_lines_1 ( - uint8_t *src_data, - uint8_t *dst_data, - unsigned int lines, + uint8_t *src_data, + uint8_t *dst_data, + unsigned int lines, unsigned int src_pixels, - unsigned int dst_pixels, - unsigned int channels) + unsigned int dst_pixels, + unsigned int channels) { unsigned int dst_x, src_x, y, c, cnt; unsigned int avg[3], val; @@ -383,7 +383,7 @@ genesys_deskew(Genesys_Scanner *s) double slope = 0; DBG (DBG_proc, "%s: start\n", __FUNCTION__); - + bg=0; if(s->params.format==SANE_FRAME_GRAY && s->params.depth == 1) { @@ -402,7 +402,7 @@ genesys_deskew(Genesys_Scanner *s) return SANE_STATUS_GOOD; } DBG(DBG_info, "%s: slope=%f => %f\n",__FUNCTION__,slope, (slope/M_PI_2)*90); - /* rotate image slope is in [-PI/2,PI/2] + /* rotate image slope is in [-PI/2,PI/2] * positive values rotate trigonometric direction wise */ status = sanei_magic_rotate (&s->params, dev->img_buffer, diff --git a/backend/genesys_conv_hlp.c b/backend/genesys_conv_hlp.c index cae4116..7663a87 100644 --- a/backend/genesys_conv_hlp.c +++ b/backend/genesys_conv_hlp.c @@ -3,54 +3,54 @@ Copyright (C) 2005 Pierre Willenbrock This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ /* * Conversion filters for genesys backend */ -static SANE_Status +static SANE_Status FUNC_NAME(genesys_reorder_components_cis) ( - uint8_t *src_data, - uint8_t *dst_data, - unsigned int lines, - unsigned int pixels) + uint8_t *src_data, + uint8_t *dst_data, + unsigned int lines, + unsigned int pixels) { unsigned int x, y; uint8_t *src[3]; @@ -97,12 +97,12 @@ FUNC_NAME(genesys_reorder_components_cis) ( return SANE_STATUS_GOOD; } -static SANE_Status +static SANE_Status FUNC_NAME(genesys_reorder_components_cis_bgr) ( - uint8_t *src_data, - uint8_t *dst_data, - unsigned int lines, - unsigned int pixels) + uint8_t *src_data, + uint8_t *dst_data, + unsigned int lines, + unsigned int pixels) { unsigned int x, y; uint8_t *src[3]; @@ -148,12 +148,12 @@ FUNC_NAME(genesys_reorder_components_cis_bgr) ( return SANE_STATUS_GOOD; } -static SANE_Status +static SANE_Status FUNC_NAME(genesys_reorder_components_bgr) ( - uint8_t *src_data, - uint8_t *dst_data, - unsigned int lines, - unsigned int pixels) + uint8_t *src_data, + uint8_t *dst_data, + unsigned int lines, + unsigned int pixels) { unsigned int c; uint8_t *src = src_data; @@ -190,13 +190,13 @@ FUNC_NAME(genesys_reorder_components_bgr) ( } #if defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN) -static SANE_Status +static SANE_Status FUNC_NAME(genesys_reorder_components_endian) ( - uint8_t *src_data, - uint8_t *dst_data, - unsigned int lines, + uint8_t *src_data, + uint8_t *dst_data, + unsigned int lines, unsigned int pixels, - unsigned int channels) + unsigned int channels) { unsigned int c; uint8_t *src = src_data; @@ -212,14 +212,14 @@ return SANE_STATUS_GOOD; #endif /*defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN)*/ -static SANE_Status +static SANE_Status FUNC_NAME(genesys_reverse_ccd) ( - uint8_t *src_data, - uint8_t *dst_data, - unsigned int lines, + uint8_t *src_data, + uint8_t *dst_data, + unsigned int lines, unsigned int components_per_line, unsigned int *ccd_shift, - unsigned int component_count) + unsigned int component_count) { unsigned int x, y, c; COMPONENT_TYPE *src = (COMPONENT_TYPE *)src_data; @@ -229,8 +229,8 @@ FUNC_NAME(genesys_reverse_ccd) ( unsigned int pitch = components_per_line; unsigned int ccd_shift_pitch[12]; unsigned int *csp; - - for (c = 0; c < component_count; c++) + + for (c = 0; c < component_count; c++) ccd_shift_pitch[c] = ccd_shift[c] * pitch; /* @@ -239,7 +239,7 @@ FUNC_NAME(genesys_reverse_ccd) ( into the cpu cache for maximum efficiency. our lines take maximum 252kb(3 channels, 16bit, 2400dpi, full gl841 shading range) * instruction efficiency: - the innermost loop runs long and consists of 3 adds, one compare, + the innermost loop runs long and consists of 3 adds, one compare, 2 derefences. */ /* @@ -258,7 +258,7 @@ FUNC_NAME(genesys_reverse_ccd) ( src += pitch; } */ -/* +/* * cache efficency: here only line_dist_pitch needs to stay in cache. 12*4 = 48 bytes * instruction efficiency: @@ -281,14 +281,14 @@ FUNC_NAME(genesys_reverse_ccd) ( return SANE_STATUS_GOOD; } -static SANE_Status +static SANE_Status FUNC_NAME(genesys_shrink_lines) ( - uint8_t *src_data, - uint8_t *dst_data, - unsigned int lines, + uint8_t *src_data, + uint8_t *dst_data, + unsigned int lines, unsigned int src_pixels, - unsigned int dst_pixels, - unsigned int channels) + unsigned int dst_pixels, + unsigned int channels) { unsigned int dst_x, src_x, y, c, cnt; unsigned int avg[3]; @@ -329,11 +329,11 @@ FUNC_NAME(genesys_shrink_lines) ( for (src_x = 0; src_x < src_pixels; src_x++) { for (c = 0; c < channels; c++) avg[c] = *src++; - while ((cnt < dst_pixels || src_x + 1 == src_pixels) && + while ((cnt < dst_pixels || src_x + 1 == src_pixels) && dst_x < dst_pixels) { cnt += src_pixels; - for (c = 0; c < channels; c++) + for (c = 0; c < channels; c++) *dst++ = avg[c]; dst_x++; } diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c index fb3cd43..213b9c9 100644 --- a/backend/genesys_devices.c +++ b/backend/genesys_devices.c @@ -11,44 +11,44 @@ xerox travelscan device entry Copyright (C) 2010 Chris Berry and Michael Rickmann for Plustek Opticbook 3600 support - + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------ */ @@ -81,7 +81,7 @@ static Genesys_Frontend Wolfson[] = { , /* 2: ST24 */ {DAC_WOLFSON_5345,{0x00, 0x03, 0x05, 0x12} , {0x00, 0x00, 0x00} - , {0xb8, 0xb8, 0xb8} + , {0xb8, 0xb8, 0xb8} , {0x04, 0x04, 0x04} , {0x00, 0x00, 0x00} } @@ -114,10 +114,10 @@ static Genesys_Frontend Wolfson[] = { {0x58, 0x80, 0x00, 0x00} /* reg1=0x80 ? */ , {0x00, 0x00, 0x00} , {0x09, 0x09, 0x09} - , {0x09, 0x09, 0x09} + , {0x09, 0x09, 0x09} , {0x00, 0x00, 0x00} } - , + , {DAC_WOLFSON_XP300,{0x00, 0x35, 0x20, 0x14} /* 7: XP300 */ , {0x00, 0x00, 0x00} , {0xe1, 0xe1, 0xe1} @@ -125,7 +125,7 @@ static Genesys_Frontend Wolfson[] = { , {0x07, 0x00, 0x00} } , /* 8: HP3670 */ - {DAC_WOLFSON_HP3670, + {DAC_WOLFSON_HP3670, /* reg0 reg1 reg2 reg3 */ {0x00, 0x03, 0x05, 0x32} /* reg3=0x32 for 100-300 dpi, 0x12 at 1200 */ , {0x00, 0x00, 0x00} /* sign */ @@ -160,7 +160,7 @@ static Genesys_Frontend Wolfson[] = { {DAC_KVSS080, {0x00, 0x23, 0x24, 0x0f} , {0x00, 0x00, 0x00} - , {0x80, 0x80, 0x80} + , {0x80, 0x80, 0x80} , {0x4b, 0x4b, 0x4b} , {0x00,0x00,0x00} } @@ -211,12 +211,23 @@ static Genesys_Frontend Wolfson[] = { , {0x00, 0x00, 0x00} /* 0x20, 0x21, 0x22 */ , {0x00, 0x00, 0x00} /* 0x28, 0x29, 0x2a */ , {0x00, 0x00, 0x00} - } + }, + {DAC_CANONLIDE80, + /* reg0: control 74 data, 70 no data + * reg3: offset + * reg6: gain + * reg0 , reg3, reg6 */ + {0x70, 0x16, 0x60, 0x00} + , {0x00, 0x00, 0x00} + , {0x00, 0x00, 0x00} + , {0x00, 0x00, 0x00} + , {0x00, 0x00, 0x00} + } }; /** for setting up the sensor-specific settings: - * Optical Resolution, number of black pixels, number of dummy pixels, + * Optical Resolution, number of black pixels, number of dummy pixels, * CCD_start_xoffset, and overall number of sensor pixels * registers 0x08-0x0b, 0x10-0x1d and 0x52-0x5e */ @@ -294,13 +305,14 @@ static Genesys_Sensor Sensor[] = { } , /* CANOLIDE35 */ - {CCD_CANONLIDE35, 1200, - 87, /*(black) */ + {CCD_CANONLIDE35, + 1200, + 87, /* (black) */ 87, /* (dummy) */ 0, /* (startxoffset) */ - 10400, /*sensor_pixels */ - 210, - 200, + 10400, /* sensor_pixels */ + 0, + 0, {0x00, 0x00, 0x00, 0x00}, {0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02 /* TODO(these do no harm, but may be neccessery for CCD) */ @@ -349,7 +361,7 @@ static Genesys_Sensor Sensor[] = { 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, - 0x10, 0x00, 0x20, 0x02 + 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ @@ -372,7 +384,7 @@ static Genesys_Sensor Sensor[] = { 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, - 0x10, 0x00, 0x20, 0x02 + 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ @@ -395,7 +407,7 @@ static Genesys_Sensor Sensor[] = { 200, {0x00, 0x00, 0x00, 0x00}, {0x15, 0x44, 0x15, 0x44, 0x15, 0x44, 0x00, 0x02, 0x04, 0x50, - 0x10, 0x00, 0x20, 0x02 + 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ @@ -418,7 +430,7 @@ static Genesys_Sensor Sensor[] = { 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, - 0x10, 0x00, 0x20, 0x02 + 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ @@ -441,7 +453,7 @@ static Genesys_Sensor Sensor[] = { 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, - 0x10, 0x00, 0x20, 0x02 + 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ @@ -471,9 +483,9 @@ static Genesys_Sensor Sensor[] = { {0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xe1, - 0x55, - 0x00, 0x00, 0x00, - 0x41 + 0x55, + 0x00, 0x00, 0x00, + 0x41 } , {1.7, 1.7, 1.7}, @@ -497,9 +509,9 @@ static Genesys_Sensor Sensor[] = { {0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xe1, - 0x55, - 0x00, 0x00, 0x00, - 0x41 + 0x55, + 0x00, 0x00, 0x00, + 0x41 } , {1.0, 1.0, 1.0}, @@ -524,9 +536,9 @@ static Genesys_Sensor Sensor[] = { {0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xe1, - 0x55, - 0x00, 0x00, 0x00, - 0x41 + 0x55, + 0x00, 0x00, 0x00, + 0x41 } , {1.7, 1.7, 1.7}, @@ -696,8 +708,8 @@ static Genesys_Sensor Sensor[] = { /* Canon Image formula 101 */ {CCD_IMG101, 1200, /* optical resolution */ - 31, - 31, + 31, + 31, 0, 10800, 210, @@ -711,9 +723,9 @@ static Genesys_Sensor Sensor[] = { {0x02, 0x04, 0x06, 0x08, 0x0a, 0x00, 0x59, 0x31, - 0x40, - 0x00, 0x00, 0x00, - 0x1f + 0x40, + 0x00, 0x00, 0x00, + 0x1f } , {1.7, 1.7, 1.7}, @@ -723,8 +735,8 @@ static Genesys_Sensor Sensor[] = { /* Plustek OpticBook 3800 */ {CCD_PLUSTEK3800, 1200, /* optical resolution */ - 31, - 31, + 31, + 31, 0, 10200, 210, @@ -738,14 +750,31 @@ static Genesys_Sensor Sensor[] = { {0x02, 0x04, 0x06, 0x08, 0x0a, 0x00, 0x59, 0x31, - 0x40, - 0x00, 0x00, 0x00, - 0x1f + 0x40, + 0x00, 0x00, 0x00, + 0x1f } , {1.7, 1.7, 1.7}, {NULL, NULL, NULL} - } + }, + /* CANOLIDE80 */ + {CIS_CANONLIDE80, + 1200, /* real hardware limit is 2400 */ + 20, /* black pixels */ + 6, /* expdummy 6 */ + /* tuned to give 3*8 multiple startx coordinate during shading calibration */ + 34, /* CCD_start_xoffset 14=>3, 20=>2 */ + 10240, /* 10400, too wide=>10288 in shading data 10240~, 10208 too short for shading, max shading data = 10240 pixels, endpix-startpix=10208 */ + 150, + 150, + {0x00, 0x05, 0x07, 0x09}, /* in fact ,maps to 0x70-0x73 for GL841 */ + /* [0x10-0x15] values are initial led exposure values */ + /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d*/ + {0x10, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04}, + {0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x29, 0x69, 0x55, 0x00, 0x00, 0x20, 0x41} , + {1.0, 1.0, 1.0}, + {NULL, NULL, NULL}} }; /** for General Purpose Output specific settings: @@ -909,6 +938,12 @@ static Genesys_Gpo Gpo[] = { {GPO_PLUSTEK3800, {0x41, 0xa4}, {0x13, 0xa7} + }, + /* Canon LiDE 80 */ + { + GPO_CANONLIDE80, + {0x28, 0x90}, /* 6c, 6d */ + {0x75, 0x80}, /* 6e, 6f */ } }; @@ -919,7 +954,7 @@ static Genesys_Motor Motor[] = { 2400, /* maximum motor resolution */ 1, /* maximum step mode */ 1, /* number of power modes*/ - {{{ + {{{ 11000, /* maximum start speed */ 3000, /* maximum end speed */ 128, /* step count */ @@ -937,7 +972,7 @@ static Genesys_Motor Motor[] = { 2400, 1, 1, - {{{ + {{{ 2000, 1375, 128, @@ -966,7 +1001,7 @@ static Genesys_Motor Motor[] = { 2100, 128, 0.3, - },},}, + },},}, }, {MOTOR_HP3670, /* HP 3670 */ 1200, @@ -1027,18 +1062,8 @@ static Genesys_Motor Motor[] = { 2400, 1, 1, - {{{ - 3500, - 1300, - 60, - 0.8, - }, - { - 3500, - 1400, - 60, - 0.8, - },},}, + {{{ 3500, 1300, 60, 0.8, }, + { 3500, 1400, 60, 0.8, },},}, }, {MOTOR_XP200, /* Strobe XP200 */ 600, @@ -1263,6 +1288,21 @@ static Genesys_Motor Motor[] = { { 3500, 3250, 60, 0.8 }, }, },}, + {MOTOR_CANONLIDE80, + 2400, /* 2400 ???? */ + 4800, /* 9600 ???? */ + 1, /* max step type */ + 1, /* power mode count */ + { + { /* start speed, max end speed, step number */ + /* maximum speed (second field) is used to compute exposure as seen by motor */ + /* exposure=max speed/ slope dpi * base dpi */ + /* 5144 = max pixels at 600 dpi */ + /* 1288=(5144+8)*ydpi(=300)/base_dpi(=1200) , where 5152 is exposure */ + /* 6440=9660/(1932/1288) */ + { 9560, 1912, 31, 0.8 }, + }, + },}, }; /* here we have the various device settings... @@ -1296,7 +1336,7 @@ static Genesys_Model umax_astra_4500_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ @@ -1323,8 +1363,8 @@ static Genesys_Model canon_lide_50_model = { GENESYS_GL841, NULL, - {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ - {2400, 1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ + { 1200, 600, 400, 300, 240, 200, 150, 75, 0}, /* possible x-resolutions */ + {2400, 1200, 600, 400, 300, 240, 200, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ @@ -1333,7 +1373,7 @@ static Genesys_Model canon_lide_50_model = { SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (6.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -1345,7 +1385,7 @@ static Genesys_Model canon_lide_50_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -1359,8 +1399,8 @@ static Genesys_Model canon_lide_50_model = { GPO_CANONLIDE35, MOTOR_CANONLIDE35, GENESYS_FLAG_LAZY_INIT | /* Which flags are needed for this scanner? */ - GENESYS_FLAG_SKIP_WARMUP | - GENESYS_FLAG_OFFSET_CALIBRATION | + GENESYS_FLAG_SKIP_WARMUP | + GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_WHITE_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_HALF_CCD_MODE, @@ -1401,7 +1441,7 @@ static Genesys_Model panasonic_kvss080_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ @@ -1452,7 +1492,7 @@ static Genesys_Model hp4850c_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ @@ -1467,7 +1507,7 @@ static Genesys_Model hp4850c_model = { DAC_G4050, GPO_G4050, MOTOR_G4050, - GENESYS_FLAG_LAZY_INIT | + GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | @@ -1507,7 +1547,7 @@ static Genesys_Model hpg4010_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ @@ -1522,7 +1562,7 @@ static Genesys_Model hpg4010_model = { DAC_G4050, GPO_G4050, MOTOR_G4050, - GENESYS_FLAG_LAZY_INIT | + GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | @@ -1562,7 +1602,7 @@ static Genesys_Model hpg4050_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ @@ -1577,7 +1617,7 @@ static Genesys_Model hpg4050_model = { DAC_G4050, GPO_G4050, MOTOR_G4050, - GENESYS_FLAG_LAZY_INIT | + GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | @@ -1618,7 +1658,7 @@ static Genesys_Model canon_4400f_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ @@ -1634,7 +1674,7 @@ static Genesys_Model canon_4400f_model = { GPO_CS4400F, MOTOR_G4050, GENESYS_FLAG_NO_CALIBRATION | - GENESYS_FLAG_LAZY_INIT | + GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | @@ -1677,7 +1717,7 @@ static Genesys_Model canon_8400f_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ @@ -1693,7 +1733,7 @@ static Genesys_Model canon_8400f_model = { GPO_CS8400F, MOTOR_CS8400F, GENESYS_FLAG_NO_CALIBRATION | - GENESYS_FLAG_LAZY_INIT | + GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | @@ -1736,7 +1776,7 @@ static Genesys_Model canon_lide_100_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -1748,7 +1788,7 @@ static Genesys_Model canon_lide_100_model = { CIS_CANONLIDE100, DAC_CANONLIDE200, GPO_CANONLIDE200, - MOTOR_CANONLIDE100, + MOTOR_CANONLIDE100, /* Which flags are needed for this scanner? */ GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_SIS_SENSOR @@ -1790,7 +1830,7 @@ static Genesys_Model canon_lide_110_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -1802,7 +1842,7 @@ static Genesys_Model canon_lide_110_model = { CIS_CANONLIDE110, DAC_CANONLIDE110, GPO_CANONLIDE110, - MOTOR_CANONLIDE110, + MOTOR_CANONLIDE110, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION @@ -1844,7 +1884,7 @@ static Genesys_Model canon_lide_210_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -1856,7 +1896,7 @@ static Genesys_Model canon_lide_210_model = { CIS_CANONLIDE210, DAC_CANONLIDE110, GPO_CANONLIDE210, - MOTOR_CANONLIDE210, + MOTOR_CANONLIDE210, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION @@ -1897,7 +1937,7 @@ static Genesys_Model canon_5600f_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -1950,7 +1990,7 @@ static Genesys_Model canon_lide_700f_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2005,7 +2045,7 @@ static Genesys_Model canon_lide_200_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2047,7 +2087,7 @@ static Genesys_Model canon_lide_60_model = { SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (6.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2059,7 +2099,7 @@ static Genesys_Model canon_lide_60_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2076,7 +2116,7 @@ static Genesys_Model canon_lide_60_model = { | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_WHITE_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_HALF_CCD_MODE, GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ @@ -2084,6 +2124,62 @@ static Genesys_Model canon_lide_60_model = { 400 }; /* this is completely untested -- hmg */ +static Genesys_Model canon_lide_80_model = { + "canon-lide-80", /* Name */ + "Canon", /* Device vendor string */ + "LiDE 80", /* Device model name */ + GENESYS_GL841, + NULL, + + { 1200, 600, 400, 300, 240, 150, 100, 75, 0}, /* possible x-resolutions */ + {2400, 1200, 600, 400, 300, 240, 150, 100, 75, 0}, /* possible y-resolutions */ + {16, 8, 0}, /* possible depths in gray mode */ + {16, 8, 0}, /* possible depths in color mode */ + SANE_FIX (0.42), /* Start of scan area in mm (x) 0.42 */ + SANE_FIX (7.90), /* Start of scan area in mm (y) 7.90 */ + SANE_FIX (216.07), /* Size of scan area in mm (x) 218.00 */ + SANE_FIX (299.0), /* Size of scan area in mm (y) */ + + SANE_FIX (4.5), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of black mark in mm (x) */ + + SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ + SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ + SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ + SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ + + SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ + + SANE_FIX (0.0), /* Size of scan area after paper sensor stops + sensing document in mm */ + SANE_FIX (0.0), /* Amount of feeding needed to eject document + after finishing scanning in mm */ + + 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ + + COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ + + SANE_TRUE, /* Is this a CIS scanner? */ + SANE_FALSE, /* Is this a sheetfed scanner? */ + CIS_CANONLIDE80, + DAC_CANONLIDE80, + GPO_CANONLIDE80, + MOTOR_CANONLIDE80, + GENESYS_FLAG_LAZY_INIT | /* Which flags are needed for this scanner? */ + GENESYS_FLAG_SKIP_WARMUP | + GENESYS_FLAG_OFFSET_CALIBRATION | + GENESYS_FLAG_DARK_WHITE_CALIBRATION | + GENESYS_FLAG_CUSTOM_GAMMA | + GENESYS_FLAG_HALF_CCD_MODE, + GENESYS_HAS_SCAN_SW | + GENESYS_HAS_FILE_SW | + GENESYS_HAS_EMAIL_SW | + GENESYS_HAS_COPY_SW, + 160, /* 280 @2400 */ + 400 +}; + + static Genesys_Model hp2300c_model = { "hewlett-packard-scanjet-2300c", /* Name */ "Hewlett Packard", /* Device vendor string */ @@ -2113,7 +2209,7 @@ static Genesys_Model hp2300c_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 16, 8, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2139,7 +2235,7 @@ static Genesys_Model hp2300c_model = { 132 }; -static +static Genesys_Model hp2400c_model = { "hewlett-packard-scanjet-2400c", /* Name */ "Hewlett Packard", /* Device vendor string */ @@ -2169,7 +2265,7 @@ Genesys_Model hp2400c_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ @@ -2194,7 +2290,7 @@ Genesys_Model hp2400c_model = { 132 }; -static +static Genesys_Model visioneer_xp200_model = { "visioneer-strobe-xp200", /* Name */ "Visioneer", /* Device vendor string */ @@ -2224,7 +2320,7 @@ Genesys_Model visioneer_xp200_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2277,7 +2373,7 @@ static Genesys_Model hp3670c_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ @@ -2331,7 +2427,7 @@ static Genesys_Model plustek_st12_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ @@ -2379,7 +2475,7 @@ static Genesys_Model plustek_st24_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ @@ -2395,7 +2491,7 @@ static Genesys_Model plustek_st24_model = { GENESYS_FLAG_UNTESTED | GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_SEARCH_START | GENESYS_FLAG_OFFSET_CALIBRATION, GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ @@ -2432,7 +2528,7 @@ static Genesys_Model medion_md5345_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2475,7 +2571,7 @@ static Genesys_Model visioneer_xp300_model = { SANE_FIX (435.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2487,9 +2583,9 @@ static Genesys_Model visioneer_xp300_model = { SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ - /* this is larger than needed -- accounts for second sensor head, which is a + /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2540,7 +2636,7 @@ static Genesys_Model syscan_docketport_665_model = { SANE_FIX (17.5), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2580,7 +2676,7 @@ static Genesys_Model visioneer_roadwarrior_model = { SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2592,7 +2688,7 @@ static Genesys_Model visioneer_roadwarrior_model = { SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2608,7 +2704,7 @@ static Genesys_Model visioneer_roadwarrior_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -2632,7 +2728,7 @@ static Genesys_Model syscan_docketport_465_model = { SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2644,7 +2740,7 @@ static Genesys_Model syscan_docketport_465_model = { SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2660,7 +2756,7 @@ static Genesys_Model syscan_docketport_465_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_NO_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_UNTESTED, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW, 300, @@ -2684,7 +2780,7 @@ static Genesys_Model visioneer_xp100_r3_model = { SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2696,7 +2792,7 @@ static Genesys_Model visioneer_xp100_r3_model = { SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2712,7 +2808,7 @@ static Genesys_Model visioneer_xp100_r3_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -2736,7 +2832,7 @@ static Genesys_Model pentax_dsmobile_600_model = { SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2748,7 +2844,7 @@ static Genesys_Model pentax_dsmobile_600_model = { SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2764,7 +2860,7 @@ static Genesys_Model pentax_dsmobile_600_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -2788,7 +2884,7 @@ static Genesys_Model syscan_docketport_467_model = { SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2800,7 +2896,7 @@ static Genesys_Model syscan_docketport_467_model = { SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2816,7 +2912,7 @@ static Genesys_Model syscan_docketport_467_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -2840,7 +2936,7 @@ static Genesys_Model syscan_docketport_685_model = { SANE_FIX (212.0), /* Size of scan area in mm (x) */ SANE_FIX (500), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2852,9 +2948,9 @@ static Genesys_Model syscan_docketport_685_model = { SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ - /* this is larger than needed -- accounts for second sensor head, which is a + /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2869,7 +2965,7 @@ static Genesys_Model syscan_docketport_685_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -2893,7 +2989,7 @@ static Genesys_Model syscan_docketport_485_model = { SANE_FIX (435.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2905,9 +3001,9 @@ static Genesys_Model syscan_docketport_485_model = { SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ - /* this is larger than needed -- accounts for second sensor head, which is a + /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2922,7 +3018,7 @@ static Genesys_Model syscan_docketport_485_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -2946,7 +3042,7 @@ static Genesys_Model dct_docketport_487_model = { SANE_FIX (435.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -2958,9 +3054,9 @@ static Genesys_Model dct_docketport_487_model = { SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ - /* this is larger than needed -- accounts for second sensor head, which is a + /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -2976,7 +3072,7 @@ static Genesys_Model dct_docketport_487_model = { | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_UNTESTED, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -3012,7 +3108,7 @@ static Genesys_Model visioneer_7100_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ @@ -3067,7 +3163,7 @@ static Genesys_Model xerox_2400_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ @@ -3111,7 +3207,7 @@ static Genesys_Model xerox_travelscanner_model = { SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ - SANE_FIX (3.0), /* Start of white strip in mm (y) */ + SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ @@ -3123,7 +3219,7 @@ static Genesys_Model xerox_travelscanner_model = { SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ @@ -3139,7 +3235,7 @@ static Genesys_Model xerox_travelscanner_model = { GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION - | GENESYS_FLAG_CUSTOM_GAMMA + | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, @@ -3176,7 +3272,7 @@ static Genesys_Model plustek_3600_model = { sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ - + 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ @@ -3199,7 +3295,7 @@ static Genesys_Model plustek_3600_model = { 7, 200 }; - + static Genesys_Model hpn6310_model = { "hewlett-packard-scanjet-N6310", /* Name */ "Hewlett Packard", /* Device vendor string */ @@ -3288,7 +3384,7 @@ static Genesys_Model plustek_3800_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ @@ -3340,7 +3436,7 @@ static Genesys_Model canon_formula101_model = { SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_FIX (0.0), /* Amount of feeding needed to eject document + SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ @@ -3382,6 +3478,7 @@ static Genesys_USB_Device_Entry genesys_usb_device_list[] = { {0x04a7, 0x04ac, &xerox_travelscanner_model}, {0x04a9, 0x2213, &canon_lide_50_model}, {0x04a9, 0x221c, &canon_lide_60_model}, + {0x04a9, 0x2214, &canon_lide_80_model}, {0x07b3, 0x0900, &plustek_3600_model}, {0x0a17, 0x3210, &pentax_dsmobile_600_model}, {0x04f9, 0x2038, &pentax_dsmobile_600_model}, /* clone, only usb id is different */ @@ -3413,3 +3510,6 @@ static Genesys_USB_Device_Entry genesys_usb_device_list[] = { {0x04a9, 0x190a, &canon_lide_210_model}, {0, 0, NULL} }; + +#define MAX_SCANNERS (sizeof(genesys_usb_device_list) / \ + sizeof(genesys_usb_device_list[0])) diff --git a/backend/genesys_gl124.c b/backend/genesys_gl124.c index 9e2fb8a..86aa4ee 100644 --- a/backend/genesys_gl124.c +++ b/backend/genesys_gl124.c @@ -301,123 +301,6 @@ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi, int half_ccd return &(sensors[idx]); } -/** @brief motor profile - * search for the database of motor profiles and get the best one. Each - * profile is at full step and at a reference exposure. Use LiDE 110 table - * by default. - * @param motor_type motor id - * @param exposure exposure time - * @return a pointer to a Motor_Profile struct - */ -static Motor_Profile *get_motor_profile(int motor_type, int exposure) -{ - unsigned int i; - int idx; - - i=0; - idx=-1; - while(i=exposure - && motors[i].exposure>step_type; - - /* fill result with target speed */ - for(i=0;itable[0]; - - /* loop on profile copying and apply step type */ - while(i=target) - { - slope[i]=current; - sum+=slope[i]; - i++; - current=profile->table[i*factor]>>step_type; - } - if(i<3 && DBG_LEVEL >= DBG_warn) - { - DBG (DBG_warn,"%s: short slope table, failed to reach %d\n",__FUNCTION__,target); - } - - /* ensure minimal slope size */ - while(i<8) - { - sum+=slope[i]; - i++; - } - - /* return used steps and acceleration sum */ - *steps=i; - return sum; -} /* returns the max register bulk size */ static int @@ -732,7 +615,7 @@ gl124_init_registers (Genesys_Device * dev) * @param slope_table pointer to 16 bit values array of the slope table * @param steps number of elemnts in the slope table */ -static SANE_Status +GENESYS_STATIC SANE_Status gl124_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { @@ -922,24 +805,6 @@ static int gl124_compute_exposure(Genesys_Device *dev, int xres, int half_ccd) return sensor->exposure; } -/**@brief compute motor step type to use - * compute the step type (full, half, quarter, ...) to use based - * on target resolution - * @param dev device description - * @param exposure sensor exposure - * @return 0 for full step - * 1 for half step - * 2 for quarter step - * 3 for eighth step - */ -static int gl124_compute_step_type(Genesys_Device *dev, int exposure) -{ -Motor_Profile *profile; - - profile=get_motor_profile(dev->model->motor_type,exposure); - return profile->step_type; -} - static SANE_Status gl124_init_motor_regs_scan (Genesys_Device * dev, @@ -1033,14 +898,15 @@ gl124_init_motor_regs_scan (Genesys_Device * dev, sanei_genesys_set_double(reg,REG_SCANFED,4); /* scan and backtracking slope table */ - gl124_slope_table(scan_table, - &scan_steps, - yres, - scan_exposure_time, - dev->motor.base_ydpi, - scan_step_type, - factor, - dev->model->motor_type); + sanei_genesys_slope_table(scan_table, + &scan_steps, + yres, + scan_exposure_time, + dev->motor.base_ydpi, + scan_step_type, + factor, + dev->model->motor_type, + motors); RIE(gl124_send_slope_table (dev, SCAN_TABLE, scan_table, scan_steps)); RIE(gl124_send_slope_table (dev, BACKTRACK_TABLE, scan_table, scan_steps)); @@ -1049,18 +915,22 @@ gl124_init_motor_regs_scan (Genesys_Device * dev, /* fast table */ fast_dpi=yres; + + /* if (scan_mode != SCAN_MODE_COLOR) { fast_dpi*=3; } - gl124_slope_table(fast_table, - &fast_steps, - fast_dpi, - scan_exposure_time, - dev->motor.base_ydpi, - scan_step_type, - factor, - dev->model->motor_type); + */ + sanei_genesys_slope_table(fast_table, + &fast_steps, + fast_dpi, + scan_exposure_time, + dev->motor.base_ydpi, + scan_step_type, + factor, + dev->model->motor_type, + motors); RIE(gl124_send_slope_table (dev, STOP_TABLE, fast_table, fast_steps)); RIE(gl124_send_slope_table (dev, FAST_TABLE, fast_table, fast_steps)); @@ -1505,10 +1375,8 @@ gl124_init_optical_regs_scan (Genesys_Device * dev, * * this function sets up the scanner to scan in normal or single line mode */ -#ifndef UNIT_TESTING -static -#endif - SANE_Status +GENESYS_STATIC +SANE_Status gl124_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ @@ -1519,6 +1387,8 @@ gl124_init_scan_regs (Genesys_Device * dev, float lines, unsigned int depth, unsigned int channels, + __sane_unused__ int scan_method, + int scan_mode, int color_filter, unsigned int flags) { @@ -1619,7 +1489,7 @@ gl124_init_scan_regs (Genesys_Device * dev, else { exposure_time = gl124_compute_exposure (dev, used_res, half_ccd); - scan_step_type = gl124_compute_step_type(dev, exposure_time); + scan_step_type = sanei_genesys_compute_step_type(motors, dev->model->motor_type, exposure_time); } DBG (DBG_info, "gl124_init_scan_regs : exposure_time=%d pixels\n", exposure_time); @@ -1628,8 +1498,7 @@ gl124_init_scan_regs (Genesys_Device * dev, /*** optical parameters ***/ /* in case of dynamic lineart, we use an internal 8 bit gray scan * to generate 1 lineart data */ - if ((flags & SCAN_FLAG_DYNAMIC_LINEART) - && (dev->settings.scan_mode == SCAN_MODE_LINEART)) + if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (scan_mode == SCAN_MODE_LINEART)) { depth = 8; } @@ -1693,7 +1562,7 @@ gl124_init_scan_regs (Genesys_Device * dev, dev->model->is_cis ? lincnt * channels : lincnt, dummy, move, - dev->settings.scan_mode, + scan_mode, mflags); if (status != SANE_STATUS_GOOD) return status; @@ -2188,7 +2057,6 @@ gl124_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) uint8_t val; float resolution; int loop = 0; - int scan_mode; DBG (DBG_proc, "gl124_slow_back_home (wait_until_home = %d)\n", wait_until_home); @@ -2243,24 +2111,30 @@ gl124_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) memcpy (local_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_dpi(dev); - /* TODO add scan_mode to the API */ - scan_mode= dev->settings.scan_mode; - dev->settings.scan_mode=SCAN_MODE_GRAY; - gl124_init_scan_regs (dev, - local_reg, - resolution, - resolution, - 100, - 30000, - 100, - 100, - 8, - 1, - 0, - SCAN_FLAG_DISABLE_SHADING | - SCAN_FLAG_DISABLE_GAMMA | - SCAN_FLAG_IGNORE_LINE_DISTANCE); - dev->settings.scan_mode=scan_mode; + status = gl124_init_scan_regs (dev, + local_reg, + resolution, + resolution, + 100, + 30000, + 100, + 100, + 8, + 1, + dev->settings.scan_method, + SCAN_MODE_GRAY, + 0, + SCAN_FLAG_DISABLE_SHADING | + SCAN_FLAG_DISABLE_GAMMA | + SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl124_slow_back_home: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); @@ -2348,22 +2222,32 @@ gl124_feed (Genesys_Device * dev, unsigned int steps) memcpy (local_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); - gl124_init_scan_regs (dev, - local_reg, - resolution, - resolution, - 0, - steps, - 100, - 3, - 8, - 3, - dev->settings.color_filter, - SCAN_FLAG_DISABLE_SHADING | - SCAN_FLAG_DISABLE_GAMMA | - SCAN_FLAG_FEEDING | - SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | - SCAN_FLAG_IGNORE_LINE_DISTANCE); + status = gl124_init_scan_regs (dev, + local_reg, + resolution, + resolution, + 0, + steps, + 100, + 3, + 8, + 3, + dev->settings.scan_method, + SCAN_MODE_COLOR, + dev->settings.color_filter, + SCAN_FLAG_DISABLE_SHADING | + SCAN_FLAG_DISABLE_GAMMA | + SCAN_FLAG_FEEDING | + SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | + SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl124_feed: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } /* set exposure to zero */ sanei_genesys_set_triple(local_reg,REG_EXPR,0); @@ -2422,7 +2306,7 @@ gl124_search_start_position (Genesys_Device * dev) int pixels = 600; int dpi = 300; - DBG (DBG_proc, "gl124_search_start_position\n"); + DBGSTART; memcpy (local_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); @@ -2430,8 +2314,19 @@ gl124_search_start_position (Genesys_Device * dev) /* sets for a 200 lines * 600 pixels */ /* normal scan with no shading */ - status = gl124_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, /*we should give a small offset here~60 steps */ - 600, dev->model->search_lines, 8, 1, 1, /*green */ + status = gl124_init_scan_regs (dev, + local_reg, + dpi, + dpi, + 0, + 0, /*we should give a small offset here~60 steps */ + 600, + dev->model->search_lines, + 8, + 1, + dev->settings.scan_method, + SCAN_MODE_GRAY, + 1, /*green */ SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE | @@ -2521,6 +2416,7 @@ gl124_search_start_position (Genesys_Device * dev) } free (data); + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2553,6 +2449,8 @@ gl124_init_regs_for_coarse_calibration (Genesys_Device * dev) 20, 16, channels, + dev->settings.scan_method, + dev->settings.scan_mode, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | @@ -2637,6 +2535,8 @@ gl124_init_regs_for_shading (Genesys_Device * dev) dev->calib_lines, 16, dev->calib_channels, + dev->settings.scan_method, + SCAN_MODE_COLOR, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | @@ -2791,6 +2691,8 @@ gl124_init_regs_for_scan (Genesys_Device * dev) dev->settings.lines, depth, channels, + dev->settings.scan_method, + dev->settings.scan_mode, dev->settings.color_filter, flags); @@ -2964,6 +2866,8 @@ move_to_calibration_area (Genesys_Device * dev) 1, 8, 3, + dev->settings.scan_method, + SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | @@ -3062,6 +2966,8 @@ gl124_led_calibration (Genesys_Device * dev) 1, depth, channels, + dev->settings.scan_method, + SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | @@ -3250,6 +3156,8 @@ gl124_offset_calibration (Genesys_Device * dev) lines, bpp, channels, + dev->settings.scan_method, + SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | @@ -3429,6 +3337,8 @@ gl124_coarse_gain_calibration (Genesys_Device * dev, int dpi) lines, bpp, channels, + dev->settings.scan_method, + SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | @@ -3558,6 +3468,8 @@ gl124_init_regs_for_warmup (Genesys_Device * dev, 1, 8, *channels, + dev->settings.scan_method, + SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | @@ -3878,7 +3790,8 @@ static Genesys_Command_Set gl124_cmd_set = { NULL, gl124_send_shading_data, gl124_calculate_current_setup, - gl124_boot + gl124_boot, + gl124_init_scan_regs }; SANE_Status diff --git a/backend/genesys_gl124.h b/backend/genesys_gl124.h index 1b78af3..8b9998a 100644 --- a/backend/genesys_gl124.h +++ b/backend/genesys_gl124.h @@ -614,10 +614,13 @@ static size_t order_0213[]={0,2,1,3}; * database of sensor profiles */ static Sensor_Profile sensors[]={ - {CIS_CANONLIDE210, 600, 1, 2768, 0x1e, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21}, + /* LiDE 110 */ + {CIS_CANONLIDE110, 600, 1, 2768, 0x1e, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21}, {CIS_CANONLIDE110, 600, 0, 5360, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21}, {CIS_CANONLIDE110, 1200, 0, 10528, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22}, {CIS_CANONLIDE110, 2400, 0, 20864, 0x1e, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24}, + + /* LiDE 210 */ {CIS_CANONLIDE210, 600, 1, 2768, 0x1e, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21}, {CIS_CANONLIDE210, 600, 0, 5360, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21}, {CIS_CANONLIDE210, 1200, 0, 10528, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22}, @@ -628,10 +631,11 @@ static Sensor_Profile sensors[]={ #define MOVE_DPI 200 #define MOVE_EXPOSURE 2304 -static uint32_t lide210_max[] = { 62496, 31296, 0}; -static uint32_t lide210_slow[] = { 62496, 7896, 0}; static uint32_t lide210_fast[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2051, 1432, 1372, 1323, 1280, 1246, 1216, 1188, 1163, 1142, 1121, 1101, 1084, 1068, 1051, 1036, 1020, 1007, 995, 983, 971, 959, 949, 938, 929, 917, 908, 900, 891, 882, 874, 866, 857, 849, 843, 835, 829, 821, 816, 808, 802, 795, 789, 784, 778, 773, 765, 760, 755, 749, 744, 739, 734, 731, 726, 721, 716, 711, 707, 702, 698, 693, 690, 685, 682, 677, 672, 669, 665, 662, 657, 654, 650, 647, 644, 639, 637, 632, 629, 626, 622, 619, 617, 614, 610, 607, 604, 601, 599, 595, 592, 589, 587, 584, 581, 579, 576, 572, 570, 567, 564, 562, 559, 557, 554, 552, 549, 547, 544, 542, 539, 538, 536, 533, 531, 529, 526, 524, 522, 519, 518, 516, 513, 511, 509, 506, 505, 503, 501, 498, 497, 495, 493, 491, 490, 487, 485, 483, 482, 480, 477, 476, 474, 472, 470, 469, 467, 465, 464, 462, 460, 458, 456, 455, 453, 451, 450, 448, 447, 445, 444, 442, 440, 439, 437, 436, 434, 433, 431, 430, 428, 427, 425, 423, 422, 420, 419, 417, 417, 415, 414, 413, 411, 410, 408, 407, 405, 404, 402, 401, 400, 399, 398, 396, 395, 393, 392, 391, 390, 389, 387, 386, 385, 383, 382, 381, 380, 379, 377, 376, 375, 374, 373, 371, 370, 369, 368, 367, 366, 364, 363, 363, 361, 360, 359, 358, 357, 356, 355, 353, 352, 352, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 335, 335, 0}; -static uint32_t lide210_ok[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2051, 1961, 1901, 1852, 1809, 1775, 1745, 1717, 1692, 1671, 1650, 1630, 1613, 1597,1580,1565,1549,1536,1524,1512,1500,1488,1478,1467,1458,1446,1437,1429,1420,1411,1403,1395,1386,1378,1372,1364,1358,1350,1345,1337,1331,1324,1318,1313,1307,1302,1294,1289,1284,1278,1273,1268,1263,1260,1255,1250,1245,1240,1236,1231,1227,1222,1219,1214,1211,1206,1201,1198,1194,1191,1186,1183,1179,1176,1173,1168,1166,1161,1158,1155,1151,1148,1146,1143,1139,1136,1133,1130,1128,1124,1121,1118,1116,1113,1110,1108,1105,1101,1099,1096,1093,1091,1088,1086,1083,1081,1078,1076,1073,1071,1068,1067,1065,1062,1060,1058,1055,1053,1051,1048,1047,1045,1042,1040,1038,1035,1034,1032,1030,1027,1026,1024,1022,1020,1019,1016,1014,1012,1011,1009,1006,1005,1003,1001,999,998,996,994,993,991,989,987,985,984,982,980,979,977,976,974,973,971,969,968,966,965,963,962,960,959,957,956,954,952,951,949,948,946,946,944,943,942,940,939,937,936,934,933,931,930,929,928,927,925,924,922,921,920,919,918,916,915,914,912,911,910,909,908,906,905,904,903,902,900,899,898,897,896,895,893,892,892,890,889,888,887,886,885,884,882,881,881,879,878,877,876,875,874,873,872,871,870,869,868,867,864,864, 0}; +static uint32_t lide110_ok[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2051, 1961, 1901, 1852, 1809, 1775, 1745, 1717, 1692, 1671, 1650, 1630, 1613, 1597,1580,1565,1549,1536,1524,1512,1500,1488,1478,1467,1458,1446,1437,1429,1420,1411,1403,1395,1386,1378,1372,1364,1358,1350,1345,1337,1331,1324,1318,1313,1307,1302,1294,1289,1284,1278,1273,1268,1263,1260,1255,1250,1245,1240,1236,1231,1227,1222,1219,1214,1211,1206,1201,1198,1194,1191,1186,1183,1179,1176,1173,1168,1166,1161,1158,1155,1151,1148,1146,1143,1139,1136,1133,1130,1128,1124,1121,1118,1116,1113,1110,1108,1105,1101,1099,1096,1093,1091,1088,1086,1083,1081,1078,1076,1073,1071,1068,1067,1065,1062,1060,1058,1055,1053,1051,1048,1047,1045,1042,1040,1038,1035,1034,1032,1030,1027,1026,1024,1022,1020,1019,1016,1014,1012,1011,1009,1006,1005,1003,1001,999,998,996,994,993,991,989,987,985,984,982,980,979,977,976,974,973,971,969,968,966,965,963,962,960,959,957,956,954,952,951,949,948,946,946,944,943,942,940,939,937,936,934,933,931,930,929,928,927,925,924,922,921,920,919,918,916,915,914,912,911,910,909,908,906,905,904,903,902,900,899,898,897,896,895,893,892,892,890,889,888,887,886,885,884,882,881,881,879,878,877,876,875,874,873,872,871,870,869,868,867,864,857, 849, 843, 835, 829, 821, 816, 808, 802, 795, 789, 784, 778, 773, 765, 760, 755, 749, 744, 739, 734, 731, 726, 721, 716, 711, 707, 702, 698, 693, 690, 685, 682, 677, 672, 669, 665, 662, 657, 654, 650, 647, 644, 639, 637, 632, 629, 626, 622, 619, 617, 614, 610, 607, 604, 601, 599, 595, 592, 589, 587, 584, 581, 579, 576, 572, 570, 567, 564, 562, 559, 557, 554, 552, 549, 547, 544, 542, 539, 538, 536, 533, 531, 529, 526, 524, 522, 519, 518, 516, 513, 511, 509, 506, 505, 503, 501, 498, 497, 495, 493, 491, 490, 487, 485, 483, 482, 480, 477, 476, 474, 472, 470, 469, 467, 465, 464, 462, 460, 458, 456, 455, 453, 451, 450, 448, 447, 445, 444, 442, 440, 439, 437, 436, 434, 433, 431, 430, 428, 427, 425, 423, 422, 420, 419, 417, 417, 415, 414, 413, 411, 410, 408, 407, 405, 404, 402, 401, 400, 399, 398, 396, 395, 393, 392, 391, 390, 389, 387, 386, 385, 383, 382, 381, 380, 379, 377, 376, 375, 374, 373, 371, 370, 369, 368, 367, 366, 364, 363, 363, 361, 360, 359, 358, 357, 356, 355, 353, 352, 352, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 335, 335, 0}; +static uint32_t lide110_slow[] = { 62496, 7896, 2632, 0}; +static uint32_t lide110_max[] = { 62496, 31296, 10432, 0}; +static uint32_t lide210_max[] = { 62496, 31296, 20864, 10432, 0}; /** * database of motor profiles @@ -641,31 +645,31 @@ static uint32_t lide210_ok[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 23 /* NEXT LPERIOD=PREVIOUS*2-192 */ static Motor_Profile motors[]={ {MOTOR_CANONLIDE110, 2768, 0, lide210_fast}, - {MOTOR_CANONLIDE110, 5360, 0, lide210_ok}, - {MOTOR_CANONLIDE110, 10528, 1, lide210_slow}, - {MOTOR_CANONLIDE110, 20864, 2, lide210_max}, + {MOTOR_CANONLIDE110, 5360, 0, lide110_ok}, + {MOTOR_CANONLIDE110, 10528, 1, lide110_slow}, + {MOTOR_CANONLIDE110, 20864, 2, lide110_max}, {MOTOR_CANONLIDE210, 2768, 0, lide210_fast}, - {MOTOR_CANONLIDE210, 5360, 0, lide210_ok}, - {MOTOR_CANONLIDE210, 10528, 1, lide210_slow}, + {MOTOR_CANONLIDE210, 5360, 0, lide110_ok}, + {MOTOR_CANONLIDE210, 10528, 1, lide110_slow}, {MOTOR_CANONLIDE210, 20864, 2, lide210_max}, {0, 0, 0, NULL}, }; /* *INDENT-ON* */ - -#ifndef UNIT_TESTING -static -#endif - SANE_Status gl124_init_scan_regs (Genesys_Device * dev, - Genesys_Register_Set * reg, - float xres, /*dpi */ - float yres, /*dpi */ - float startx, /*optical_res, from dummy_pixel+1 */ - float starty, /*base_ydpi, from home! */ - float pixels, - float lines, - unsigned int depth, - unsigned int channels, - int color_filter, unsigned int flags); +GENESYS_STATIC +SANE_Status gl124_init_scan_regs (Genesys_Device * dev, + Genesys_Register_Set * reg, + float xres, /*dpi */ + float yres, /*dpi */ + float startx, /*optical_res, from dummy_pixel+1 */ + float starty, /*base_ydpi, from home! */ + float pixels, + float lines, + unsigned int depth, + unsigned int channels, + int scan_method, + int scan_mode, + int color_filter, + unsigned int flags); #ifndef UNIT_TESTING static @@ -702,10 +706,11 @@ static #endif SANE_Status gl124_feed (Genesys_Device * dev, unsigned int steps); -#ifndef UNIT_TESTING -static -#endif -SANE_Status +GENESYS_STATIC SANE_Status gl124_stop_action (Genesys_Device * dev); +GENESYS_STATIC SANE_Status +gl124_send_slope_table (Genesys_Device * dev, int table_nr, + uint16_t * slope_table, int steps); + /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ diff --git a/backend/genesys_gl646.c b/backend/genesys_gl646.c index c7fa175..19b4585 100644 --- a/backend/genesys_gl646.c +++ b/backend/genesys_gl646.c @@ -8,44 +8,44 @@ Copyright (C) 2007 Luke Copyright (C) 2011 Alexey Osipov for HP2400 description and tuning - + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME @@ -682,7 +682,7 @@ get_cksel (int sensor, int required, SANE_Bool color) * the device. * @param dev pointer to a struct describing the device * @param regs register set to fill - * @param scan_settings scan's settings + * @param scan_settings scan's settings * @param slope_table1 first motor table to fill * @param slope_table2 second motor table to fill * @param resolution dpi of the scan @@ -985,10 +985,8 @@ gl646_setup_registers (Genesys_Device * dev, /* gamma enable for scans */ if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) regs[reg_0x05].value |= REG05_GMM14BIT; - if (depth < 16) - regs[reg_0x05].value |= REG05_GMMENB; - else - regs[reg_0x05].value &= ~REG05_GMMENB; + + regs[reg_0x05].value &= ~REG05_GMMENB; /* true CIS gray if needed */ if (dev->model->is_cis == SANE_TRUE && color == SANE_FALSE @@ -1120,7 +1118,7 @@ gl646_setup_registers (Genesys_Device * dev, /* we assume all scans are done with 2 tables */ /* - feedl = feed_steps - fast_slope_steps*2 - + feedl = feed_steps - fast_slope_steps*2 - (slow_slope_steps >> scan_step_type); */ /* but head has moved due to shading calibration => dev->scanhead_position_in_steps */ if (feedl > 0) @@ -1299,7 +1297,7 @@ gl646_setup_registers (Genesys_Device * dev, dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; - /* total_bytes_to_read is the number of byte to send to frontend + /* total_bytes_to_read is the number of byte to send to frontend * total_bytes_read is the number of bytes sent to frontend * read_bytes_left is the number of bytes to read from the scanner */ @@ -1354,7 +1352,7 @@ gl646_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs) } -/** Test if the ASIC works +/** Test if the ASIC works */ static SANE_Status gl646_asic_test (Genesys_Device * dev) @@ -1415,7 +1413,7 @@ gl646_asic_test (Genesys_Device * dev) size = 0x40000; verify_size = size + 0x80; /* todo: looks like the read size must be a multiple of 128? - otherwise the read doesn't succeed the second time after the scanner has + otherwise the read doesn't succeed the second time after the scanner has been plugged in. Very strange. */ data = (uint8_t *) malloc (size); @@ -1699,7 +1697,7 @@ gl646_init_regs (Genesys_Device * dev) } -/* Send slope table for motor movement +/* Send slope table for motor movement slope_table in machine byte order */ static SANE_Status @@ -1834,7 +1832,7 @@ gl646_set_ad_fe (Genesys_Device * dev, uint8_t set) } } } - /* + /* if (set == AFE_POWER_SAVE) { status = @@ -1864,7 +1862,7 @@ gl646_wm_hp3670 (Genesys_Device * dev, uint8_t set, int dpi) SANE_Status status = SANE_STATUS_GOOD; int i; - DBG (DBG_proc, "gl646_wm_hp3670: start \n"); + DBGSTART; switch (set) { case AFE_INIT: @@ -1971,7 +1969,7 @@ gl646_wm_hp3670 (Genesys_Device * dev, uint8_t set, int dpi) } } - DBG (DBG_proc, "gl646_wm_hp3670: success \n"); + DBGCOMPLETED; return status; } @@ -2169,8 +2167,8 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set, int dpi) return SANE_STATUS_GOOD; } -/** Set values of analog frontend - * this this the public interface, the gl646 as to use one more +/** Set values of analog frontend + * this this the public interface, the gl646 as to use one more * parameter to work effectively, hence the redirection * @param dev device to set * @param set action to execute @@ -2229,16 +2227,14 @@ gl646_set_lamp_power (Genesys_Device * dev, * limited to AFE for now. * @param dev scanner's device * @param enable SANE_TRUE to enable power saving, SANE_FALSE to leave it - * @return allways SANE_STATUS_GOOD + * @return allways SANE_STATUS_GOOD */ -#ifndef UNIT_TESTING -static -#endif - SANE_Status +GENESYS_STATIC +SANE_Status gl646_save_power (Genesys_Device * dev, SANE_Bool enable) { - DBG (DBG_proc, "gl646_save_power: start\n"); + DBGSTART; DBG (DBG_info, "gl646_save_power: enable = %d\n", enable); if (enable) @@ -2250,7 +2246,7 @@ gl646_save_power (Genesys_Device * dev, SANE_Bool enable) gl646_set_fe (dev, AFE_INIT, 0); } - DBG (DBG_proc, "gl646_save_power: end\n"); + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2558,8 +2554,8 @@ gl646_detect_document_end (Genesys_Device * dev) DBG (DBG_info, "gl646_detect_document_end: no more document\n"); dev->document = SANE_FALSE; - /* adjust number of bytes to read: - * total_bytes_to_read is the number of byte to send to frontend + /* adjust number of bytes to read: + * total_bytes_to_read is the number of byte to send to frontend * total_bytes_read is the number of bytes sent to frontend * read_bytes_left is the number of bytes to read from the scanner */ @@ -2972,10 +2968,8 @@ gl646_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, * @param dev scanner's device * @param wait_until_home true if the function waits until head parked */ -#ifndef UNIT_TESTING -static -#endif - SANE_Status +GENESYS_STATIC +SANE_Status gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { SANE_Status status; @@ -3068,11 +3062,11 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; - status = setup_for_scan (dev, settings, SANE_TRUE, SANE_TRUE, SANE_TRUE); + status = setup_for_scan (dev, dev->reg, settings, SANE_TRUE, SANE_TRUE, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "%s: failed to setup for scan: %s\n", __FUNCTION__, + "%s: failed to setup for scan: %s\n", __FUNCTION__, sane_strstatus (status)); DBGCOMPLETED; return status; @@ -3088,7 +3082,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "%s: failed to set frontend: %s\n", __FUNCTION__, + "%s: failed to set frontend: %s\n", __FUNCTION__, sane_strstatus (status)); DBGCOMPLETED; return status; @@ -3153,7 +3147,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) DBG (DBG_info, "gl646_slow_back_home: scanhead is still moving\n"); - DBG (DBG_proc, "gl646_slow_back_home: end\n"); + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -3331,7 +3325,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev) /* we don't want top offset, but we need right margin to be the same * than the one for the final scan */ - status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); + status = setup_for_scan (dev, dev->reg, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); /* used when sending shading calibration data */ dev->calib_pixels = settings.pixels; @@ -3377,7 +3371,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev) /** - * set up registers for the actual scan. The scan's parameters are given + * set up registers for the actual scan. The scan's parameters are given * through the device settings. It allocates the scan buffers. */ static SANE_Status @@ -3385,36 +3379,44 @@ gl646_init_regs_for_scan (Genesys_Device * dev) { SANE_Status status; + DBGSTART; + /* park head after calibration if needed */ if (dev->scanhead_position_in_steps > 0 && dev->settings.scan_method == SCAN_METHOD_FLATBED) { - status = gl646_slow_back_home (dev, SANE_TRUE); - if (status != SANE_STATUS_GOOD) - { - return status; - - } + RIE(gl646_slow_back_home (dev, SANE_TRUE)); dev->scanhead_position_in_steps = 0; } - return setup_for_scan (dev, dev->settings, SANE_FALSE, SANE_TRUE, - SANE_TRUE); + RIE(setup_for_scan (dev, dev->reg, dev->settings, SANE_FALSE, SANE_TRUE, SANE_TRUE)); + + /* gamma is only enabled at final scan time */ + if (dev->settings.depth < 16) + dev->reg[reg_0x05].value |= REG05_GMMENB; + + DBGCOMPLETED; + return status; } /** - * set up registers for the actual scan. The scan's parameters are given + * set up registers for the actual scan. The scan's parameters are given * through the device settings. It allocates the scan buffers. * @param dev scanner's device + * @param regs registers to set up * @param settings settings of scan * @param split SANE_TRUE if move to scan area is split from scan, SANE_FALSE is * scan first moves to area * @param xcorrection take x geometry correction into account (fixed and detected offsets) * @param ycorrection take y geometry correction into account */ -static SANE_Status -setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, - SANE_Bool split, SANE_Bool xcorrection, SANE_Bool ycorrection) +GENESYS_STATIC SANE_Status +setup_for_scan (Genesys_Device * dev, + Genesys_Register_Set *regs, + Genesys_Settings settings, + SANE_Bool split, + SANE_Bool xcorrection, + SANE_Bool ycorrection) { SANE_Status status = SANE_STATUS_GOOD; SANE_Bool color; @@ -3423,10 +3425,11 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, uint16_t startx = 0, endx, pixels; int move = 0; - DBG (DBG_proc, "setup_for_scan: start\n"); + DBGSTART; DBG (DBG_info, - "setup_for_scan settings:\nResolution: %ux%uDPI\n" + "%s settings:\nResolution: %ux%uDPI\n" "Lines : %u\nPixels : %u\nStartpos : %.3f/%.3f\nScan mode : %d\nScan method: %s\n\n", + __FUNCTION__, settings.xres, settings.yres, settings.lines, settings.pixels, settings.tl_x, settings.tl_y, settings.scan_mode, settings.scan_method == SCAN_METHOD_FLATBED ? "flatbed" : "XPA"); @@ -3441,7 +3444,7 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, channels = 1; color = SANE_FALSE; } - + depth=settings.depth; if (settings.scan_mode == SCAN_MODE_LINEART) { @@ -3479,17 +3482,16 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, move += (settings.tl_y * dev->motor.optical_ydpi) / MM_PER_INCH; } - DBG (DBG_info, "setup_for_scan: move=%d steps\n", move); + DBG (DBG_info, "%s: move=%d steps\n", __FUNCTION__, move); /* security check */ if (move < 0) { - DBG (DBG_error, - "setup_for_scan: overriding negative move value %d\n", move); + DBG (DBG_error, "%s: overriding negative move value %d\n", __FUNCTION__, move); move = 0; } } - DBG (DBG_info, "setup_for_scan: move=%d steps\n", move); + DBG (DBG_info, "%s: move=%d steps\n", __FUNCTION__, move); /* pixels are allways given at full CCD optical resolution */ /* use detected left margin and fixed value */ @@ -3537,7 +3539,7 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, /* set up correct values for scan (gamma and shading enabled) */ status = gl646_setup_registers (dev, - dev->reg, + regs, settings, dev->slope_table0, dev->slope_table1, @@ -3548,31 +3550,29 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, depth); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "setup_for_scan: failed setup registers: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed setup registers: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } /* now post-process values for register and options fine tuning */ /* select color filter based on settings */ - dev->reg[reg_0x04].value &= ~REG04_FILTER; + regs[reg_0x04].value &= ~REG04_FILTER; if (channels == 1) { switch (settings.color_filter) { /* red */ case 0: - dev->reg[reg_0x04].value |= 0x04; + regs[reg_0x04].value |= 0x04; break; /* green */ case 1: - dev->reg[reg_0x04].value |= 0x08; + regs[reg_0x04].value |= 0x08; break; /* blue */ case 2: - dev->reg[reg_0x04].value |= 0x0c; + regs[reg_0x04].value |= 0x0c; break; default: break; @@ -3582,27 +3582,23 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, /* send computed slope tables */ status = gl646_send_slope_table (dev, 0, dev->slope_table0, - sanei_genesys_read_reg_from_set (dev->reg, 0x21)); + sanei_genesys_read_reg_from_set (regs, 0x21)); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "setup_for_scan: failed to send slope table 0: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed to send slope table 0: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } status = gl646_send_slope_table (dev, 1, dev->slope_table1, - sanei_genesys_read_reg_from_set (dev->reg, 0x6b)); + sanei_genesys_read_reg_from_set (regs, 0x6b)); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "setup_for_scan: failed to send slope table 1: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed to send slope table 1: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } - DBG (DBG_proc, "setup_for_scan: end\n"); + DBGCOMPLETED; return status; } @@ -4234,7 +4230,7 @@ ad_fe_coarse_gain_calibration (Genesys_Device * dev, int dpi) Genesys_Settings settings; char title[32]; - DBG (DBG_proc, "ad_fe_coarse_gain_calibration: start\n"); + DBGSTART; /* setup for a RGB scan, one full sensor's width line */ /* resolution is the one from the final scan */ @@ -4317,12 +4313,12 @@ ad_fe_coarse_gain_calibration (Genesys_Device * dev, int dpi) DBG (DBG_info, "ad_fe_coarse_gain_calibration: gains=(%d,%d,%d)\n", dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2]); - DBG (DBG_proc, "ad_fe_coarse_gain_calibration: end\n"); + DBGCOMPLETED; return status; } /** - * Alternative coarse gain calibration + * Alternative coarse gain calibration * this on uses the settings from offset_calibration. First scan moves so * we can go to calibration area for XPA. * @param dev device for scan @@ -4343,7 +4339,7 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) { return ad_fe_coarse_gain_calibration (dev, dev->sensor.optical_res); } - DBG (DBG_proc, "gl646_coarse_gain_calibration: start\n"); + DBGSTART; /* setup for a RGB scan, one full sensor's width line */ /* resolution is the one from the final scan */ @@ -4352,9 +4348,7 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) /* we are searching a sensor resolution */ if (dpi > dev->sensor.optical_res) { - resolution = - get_closest_resolution (dev->model->ccd_type, dev->sensor.optical_res, - SANE_TRUE); + resolution = dev->sensor.optical_res; } else { @@ -4371,14 +4365,12 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) if (settings.scan_method == SCAN_METHOD_FLATBED) { settings.tl_x = 0; - settings.pixels = - (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; + settings.pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; } else { settings.tl_x = SANE_UNFIX (dev->model->x_offset_ta); - settings.pixels = - (SANE_UNFIX (dev->model->x_size_ta) * resolution) / MM_PER_INCH; + settings.pixels = (SANE_UNFIX (dev->model->x_size_ta) * resolution) / MM_PER_INCH; } settings.lines = CALIBRATION_LINES; settings.depth = 8; @@ -4422,8 +4414,7 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) if (status != SANE_STATUS_GOOD) { free(line); - DBG (DBG_error, - "gl646_coarse_gain_calibration: failed to scan first line\n"); + DBG (DBG_error, "%s: failed to scan first line\n", __FUNCTION__); return status; } @@ -4438,7 +4429,7 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) pass++; /* average high level for each channel and compute gain - to reach the target code + to reach the target code we only use the central half of the CCD data */ for (k = idx; k < idx + channels; k++) { @@ -4481,7 +4472,7 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) dev->frontend.gain[k]++; DBG (DBG_proc, - "gl646_coarse_gain_calibration: channel %d, average = %.2f, gain = %d\n", + "%s: channel %d, average = %.2f, gain = %d\n", __FUNCTION__, k, average[k], dev->frontend.gain[k]); } free (line); @@ -4493,9 +4484,9 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) dev->frontend.gain[2] = dev->frontend.gain[0]; } - DBG (DBG_info, "gl646_coarse_gain_calibration: gains=(%d,%d,%d)\n", + DBG (DBG_info, "%s: gains=(%d,%d,%d)\n", __FUNCTION__, dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2]); - DBG (DBG_proc, "gl646_coarse_gain_calibration: end\n"); + DBGCOMPLETED; return status; } @@ -4537,7 +4528,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev, settings.dynamic_lineart = SANE_FALSE; /* setup for scan */ - status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); + status = setup_for_scan (dev, dev->reg, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, @@ -4551,9 +4542,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev, /* don't enable any correction for this scan */ dev->reg[reg_0x01].value &= ~REG01_DVDSET; - /* XXX STEF XXX - dev->reg[reg_0x05].value &= ~REG05_GMMENB; */ - + /* copy to local_reg */ memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); @@ -4569,7 +4558,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev, RIE (gl646_set_fe (dev, AFE_SET, settings.xres)); RIE (gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS)); - DBG (DBG_proc, "gl646_init_regs_for_warmup: end\n"); + DBGCOMPLETED; return status; } @@ -4605,7 +4594,7 @@ gl646_repark_head (Genesys_Device * dev) settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; - status = setup_for_scan (dev, settings, SANE_FALSE, SANE_FALSE, SANE_FALSE); + status = setup_for_scan (dev, dev->reg, settings, SANE_FALSE, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, @@ -4702,7 +4691,7 @@ gl646_init (Genesys_Device * dev) switch (dev->model->motor_type) { - /* set to 11111 to spot bugs, sanei_genesys_exposure_time should + /* set to 11111 to spot bugs, sanei_genesys_exposure_time should have obsoleted this field */ case MOTOR_5345: dev->settings.exposure_time = 11111; @@ -4924,15 +4913,13 @@ gl646_init (Genesys_Device * dev) return SANE_STATUS_GOOD; } -#ifndef UNIT_TESTING -static -#endif +GENESYS_STATIC SANE_Status gl646_move_to_ta (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; - DBG (DBG_proc, "gl646_move_to_ta: starting\n"); + DBGSTART; if (simple_move (dev, SANE_UNFIX (dev->model->y_offset_calib_ta)) != SANE_STATUS_GOOD) { @@ -4940,8 +4927,7 @@ gl646_move_to_ta (Genesys_Device * dev) "gl646_move_to_ta: failed to move to calibration area\n"); return status; } - DBG (DBG_proc, "gl646_move_to_ta: end\n"); - + DBGCOMPLETED; return status; } @@ -4957,10 +4943,7 @@ gl646_move_to_ta (Genesys_Device * dev) * @param shading SANE_TRUE to enable shading correction * @param data pointer for the data */ -#ifndef UNIT_TESTING -static -#endif - SANE_Status +GENESYS_STATIC SANE_Status simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, SANE_Bool forward, SANE_Bool shading, unsigned char **data) { @@ -4990,7 +4973,7 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, { split = SANE_TRUE; } - status = setup_for_scan (dev, settings, split, SANE_FALSE, SANE_FALSE); + status = setup_for_scan (dev, dev->reg, settings, split, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_scan: setup_for_scan failed (%s)\n", @@ -5046,6 +5029,9 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, dev->reg[reg_0x01].value |= REG01_DVDSET; } + /* enable gamma table for the scan */ + dev->reg[reg_0x05].value |= REG05_GMMENB; + /* one table movement for simple scan */ dev->reg[reg_0x02].value &= ~REG02_FASTFED; @@ -5522,7 +5508,7 @@ gl646_is_compatible_calibration (Genesys_Device * dev, dev->current_setup.channels, dev->current_setup.xres, cache->used_setup.channels, cache->used_setup.xres); - /* a calibration cache is compatible if color mode and x dpi match the user + /* a calibration cache is compatible if color mode and x dpi match the user * requested scan. In the case of CIS scanners, dpi isn't a criteria */ if (dev->model->is_cis == SANE_FALSE) { @@ -5798,6 +5784,7 @@ static Genesys_Command_Set gl646_cmd_set = { gl646_move_to_ta, NULL, NULL, + NULL, NULL }; diff --git a/backend/genesys_gl646.h b/backend/genesys_gl646.h index e9124fd..9e328c5 100644 --- a/backend/genesys_gl646.h +++ b/backend/genesys_gl646.h @@ -6,42 +6,42 @@ Copyright (C) 2005-2009 Pierre Willenbrock This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #include "genesys.h" @@ -261,20 +261,36 @@ static #endif SANE_Status gl646_public_set_fe (Genesys_Device * dev, uint8_t set); +GENESYS_STATIC +SANE_Status +gl646_save_power (Genesys_Device * dev, SANE_Bool enable); + +GENESYS_STATIC +SANE_Status +gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); + +GENESYS_STATIC +SANE_Status +gl646_move_to_ta (Genesys_Device * dev); + /** * sets up the scanner for a scan, registers, gamma tables, shading tables * and slope tables, based on the parameter struct. * @param device device to set up + * @param regs registers to set up * @param settings settings of the scan * @param split true if move before scan has to be done - * @param xcorrection true if scanner's X geometry must be taken into account to - * compute X, ie add left margins - * @param ycorrection true if scanner's Y geometry must be taken into account to - * compute Y, ie add top margins + * @param xcorrection true if scanner's X geometry must be taken into account to + * compute X, ie add left margins + * @param ycorrection true if scanner's Y geometry must be taken into account to + * compute Y, ie add top margins */ -static SANE_Status -setup_for_scan (Genesys_Device * device, Genesys_Settings settings, - SANE_Bool split, SANE_Bool xcorrection, +GENESYS_STATIC SANE_Status +setup_for_scan (Genesys_Device *device, + Genesys_Register_Set *regs, + Genesys_Settings settings, + SANE_Bool split, + SANE_Bool xcorrection, SANE_Bool ycorrection); /** @@ -305,7 +321,7 @@ gl646_setup_registers (Genesys_Device * dev, static #endif SANE_Status -simple_move (Genesys_Device * dev, SANE_Int distance); +simple_move (Genesys_Device * dev, SANE_Int distance); /** * Does a simple scan of the area given by the settings. Scanned data @@ -320,7 +336,7 @@ simple_move (Genesys_Device * dev, SANE_Int distance); * @param data pointer that will point to the scanned data */ #ifndef UNIT_TESTING -static +static #endif SANE_Status simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, SANE_Bool forward, @@ -344,7 +360,7 @@ static SANE_Status write_control (Genesys_Device * dev, int resolution); static void gl646_init_regs (Genesys_Device * dev); #ifndef UNIT_TESTING -static +static #endif SANE_Status gl646_load_document (Genesys_Device * dev); @@ -576,7 +592,7 @@ static Motor_Master motor_master[] = { {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 2175, 1087, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 600, SANE_FALSE, 600, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300,1200, SANE_FALSE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 17400, 8700, 120, 4905, 337, 0.3, 0.4, 16}, - /* non half ccd settings for 300 dpi + /* non half ccd settings for 300 dpi {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, */ diff --git a/backend/genesys_gl841.c b/backend/genesys_gl841.c index 2b22d2c..318def8 100644 --- a/backend/genesys_gl841.c +++ b/backend/genesys_gl841.c @@ -9,45 +9,45 @@ Copyright (C) 2006 Laurent Charpentier Copyright (C) 2010 Chris Berry and Michael Rickmann for Plustek Opticbook 3600 support - - + + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME @@ -64,7 +64,7 @@ /* ------------------------------------------------------------------------ */ /* Write to many registers */ -/* Note: There is no known bulk register write, +/* Note: There is no known bulk register write, this function is sending single registers instead */ static SANE_Status gl841_bulk_write_register (Genesys_Device * dev, @@ -88,7 +88,7 @@ gl841_bulk_write_register (Genesys_Device * dev, buffer[i * 2 + 0] = reg[i].address; buffer[i * 2 + 1] = reg[i].value; - + DBG (DBG_io2, "reg[0x%02x] = 0x%02x\n", buffer[i * 2 + 0], buffer[i * 2 + 1]); } @@ -214,13 +214,13 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; - size_t size; - uint8_t outdata[8]; + size_t size, target; + uint8_t outdata[8], *buffer; DBG (DBG_io, "gl841_bulk_read_data: requesting %lu bytes\n", (u_long) len); - if (len == 0) + if (len == 0) return SANE_STATUS_GOOD; status = @@ -254,12 +254,14 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr, return status; } - while (len) + target = len; + buffer = data; + while (target) { - if (len > BULKIN_MAXSIZE) + if (target > BULKIN_MAXSIZE) size = BULKIN_MAXSIZE; else - size = len; + size = target; DBG (DBG_io2, "gl841_bulk_read_data: trying to read %lu bytes of data\n", @@ -277,14 +279,18 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr, DBG (DBG_io2, "gl841_bulk_read_data read %lu bytes, %lu remaining\n", - (u_long) size, (u_long) (len - size)); + (u_long) size, (u_long) (target - size)); - len -= size; + target -= size; data += size; } - DBG (DBG_io, "gl841_bulk_read_data: completed\n"); + if (DBG_LEVEL >= DBG_data && dev->binary!=NULL) + { + fwrite(buffer, len, 1, dev->binary); + } + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -324,7 +330,7 @@ gl841_set_buffer_address_gamma (Genesys_Device * dev, uint32_t addr) } /* Write bulk data (e.g. gamma) */ -static SANE_Status +GENESYS_STATIC SANE_Status gl841_bulk_write_data_gamma (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { @@ -398,7 +404,7 @@ gl841_bulk_write_data_gamma (Genesys_Device * dev, uint8_t addr, /**************************************************************************** - Mid level functions + Mid level functions ****************************************************************************/ static SANE_Bool @@ -515,6 +521,7 @@ sanei_gl841_setup_sensor (Genesys_Device * dev, DBG (DBG_proc, "gl841_setup_sensor\n"); + /* that one is tricky at least ....*/ r = sanei_genesys_get_address (regs, 0x70); for (i = 0; i < 4; i++, r++) r->value = dev->sensor.regs_0x08_0x0b[i]; @@ -604,7 +611,7 @@ sanei_gl841_setup_sensor (Genesys_Device * dev, } } -/** Test if the ASIC works +/** Test if the ASIC works */ /*TODO: make this functional*/ static SANE_Status @@ -670,7 +677,7 @@ sanei_gl841_asic_test (Genesys_Device * dev) size = 0x40000; verify_size = size + 0x80; /* todo: looks like the read size must be a multiple of 128? - otherwise the read doesn't succeed the second time after the scanner has + otherwise the read doesn't succeed the second time after the scanner has been plugged in. Very strange. */ data = (uint8_t *) malloc (size); @@ -745,15 +752,15 @@ sanei_gl841_asic_test (Genesys_Device * dev) if (verify_data[i] != data[i]) { DBG (DBG_error, "sanei_gl841_asic_test: data verification error\n"); - DBG (DBG_info, "0x%.8x: got %.2x %.2x %.2x %.2x, expected %.2x %.2x %.2x %.2x\n", - i, - verify_data[i], - verify_data[i+1], - verify_data[i+2], - verify_data[i+3], - data[i], - data[i+1], - data[i+2], + DBG (DBG_info, "0x%.8x: got %.2x %.2x %.2x %.2x, expected %.2x %.2x %.2x %.2x\n", + i, + verify_data[i], + verify_data[i+1], + verify_data[i+2], + verify_data[i+3], + data[i], + data[i+1], + data[i+2], data[i+3]); free (data); free (verify_data); @@ -777,7 +784,168 @@ gl841_bulk_full_size (void) } /* - * Set all registers to default values + * Set all registers LiDE 80 to default values + * (function called only once at the beginning) + * we are doing a special case to ease development + */ +static void +gl841_init_lide80 (Genesys_Device * dev) +{ + uint8_t val; + int index=0; + + INITREG (0x01, 0x82); /* 0x02 = SHDAREA and no CISSET ! */ + INITREG (0x02, 0x10); + INITREG (0x03, 0x50); + INITREG (0x04, 0x02); + INITREG (0x05, 0x4c); /* 1200 DPI */ + INITREG (0x06, 0x38); /* 0x38 scanmod=1, pwrbit, GAIN4 */ + INITREG (0x07, 0x00); + INITREG (0x08, 0x00); + INITREG (0x09, 0x11); + INITREG (0x0a, 0x00); + + INITREG (0x10, 0x40); + INITREG (0x11, 0x00); + INITREG (0x12, 0x40); + INITREG (0x13, 0x00); + INITREG (0x14, 0x40); + INITREG (0x15, 0x00); + INITREG (0x16, 0x00); + INITREG (0x17, 0x01); + INITREG (0x18, 0x00); + INITREG (0x19, 0x06); + INITREG (0x1a, 0x00); + INITREG (0x1b, 0x00); + INITREG (0x1c, 0x00); + INITREG (0x1d, 0x04); + INITREG (0x1e, 0x10); + INITREG (0x1f, 0x04); + INITREG (0x20, 0x02); + INITREG (0x21, 0x10); + INITREG (0x22, 0x20); + INITREG (0x23, 0x20); + INITREG (0x24, 0x10); + INITREG (0x25, 0x00); + INITREG (0x26, 0x00); + INITREG (0x27, 0x00); + + INITREG (0x29, 0xff); + + INITREG (0x2c, dev->sensor.optical_res>>8); + INITREG (0x2d, dev->sensor.optical_res & 0xff); + INITREG (0x2e, 0x80); + INITREG (0x2f, 0x80); + INITREG (0x30, 0x00); + INITREG (0x31, 0x10); + INITREG (0x32, 0x15); + INITREG (0x33, 0x0e); + INITREG (0x34, 0x40); + INITREG (0x35, 0x00); + INITREG (0x36, 0x2a); + INITREG (0x37, 0x30); + INITREG (0x38, 0x2a); + INITREG (0x39, 0xf8); + + INITREG (0x3d, 0x00); + INITREG (0x3e, 0x00); + INITREG (0x3f, 0x00); + + INITREG (0x52, 0x03); + INITREG (0x53, 0x07); + INITREG (0x54, 0x00); + INITREG (0x55, 0x00); + INITREG (0x56, 0x00); + INITREG (0x57, 0x00); + INITREG (0x58, 0x29); + INITREG (0x59, 0x69); + INITREG (0x5a, 0x55); + + INITREG (0x5d, 0x20); + INITREG (0x5e, 0x41); + INITREG (0x5f, 0x40); + INITREG (0x60, 0x00); + INITREG (0x61, 0x00); + INITREG (0x62, 0x00); + INITREG (0x63, 0x00); + INITREG (0x64, 0x00); + INITREG (0x65, 0x00); + INITREG (0x66, 0x00); + INITREG (0x67, 0x40); + INITREG (0x68, 0x40); + INITREG (0x69, 0x20); + INITREG (0x6a, 0x20); + INITREG (0x6c, dev->gpo.value[0]); + INITREG (0x6d, dev->gpo.value[1]); + INITREG (0x6e, dev->gpo.enable[0]); + INITREG (0x6f, dev->gpo.enable[1]); + INITREG (0x70, 0x00); + INITREG (0x71, 0x05); + INITREG (0x72, 0x07); + INITREG (0x73, 0x09); + INITREG (0x74, 0x00); + INITREG (0x75, 0x01); + INITREG (0x76, 0xff); + INITREG (0x77, 0x00); + INITREG (0x78, 0x0f); + INITREG (0x79, 0xf0); + INITREG (0x7a, 0xf0); + INITREG (0x7b, 0x00); + INITREG (0x7c, 0x1e); + INITREG (0x7d, 0x11); + INITREG (0x7e, 0x00); + INITREG (0x7f, 0x50); + INITREG (0x80, 0x00); + INITREG (0x81, 0x00); + INITREG (0x82, 0x0f); + INITREG (0x83, 0x00); + INITREG (0x84, 0x0e); + INITREG (0x85, 0x00); + INITREG (0x86, 0x0d); + INITREG (0x87, 0x02); + INITREG (0x88, 0x00); + INITREG (0x89, 0x00); + + /* specific scanner settings, clock and gpio first */ + sanei_genesys_read_register (dev, REG6B, &val); + sanei_genesys_write_register (dev, REG6B, 0x0c); + sanei_genesys_write_register (dev, 0x06, 0x10); + sanei_genesys_write_register (dev, REG6E, 0x6d); + sanei_genesys_write_register (dev, REG6F, 0x80); + sanei_genesys_write_register (dev, REG6B, 0x0e); + sanei_genesys_read_register (dev, REG6C, &val); + sanei_genesys_write_register (dev, REG6C, 0x00); + sanei_genesys_read_register (dev, REG6D, &val); + sanei_genesys_write_register (dev, REG6D, 0x8f); + sanei_genesys_read_register (dev, REG6B, &val); + sanei_genesys_write_register (dev, REG6B, 0x0e); + sanei_genesys_read_register (dev, REG6B, &val); + sanei_genesys_write_register (dev, REG6B, 0x0e); + sanei_genesys_read_register (dev, REG6B, &val); + sanei_genesys_write_register (dev, REG6B, 0x0a); + sanei_genesys_read_register (dev, REG6B, &val); + sanei_genesys_write_register (dev, REG6B, 0x02); + sanei_genesys_read_register (dev, REG6B, &val); + sanei_genesys_write_register (dev, REG6B, 0x06); + + sanei_genesys_write_0x8c (dev, 0x10, 0x94); + sanei_genesys_write_register (dev, 0x09, 0x10); + + /* set up GPIO : no address, so no bulk write, doesn't written directly either ? */ + /* + dev->reg[reg_0x6c].value = dev->gpo.value[0]; + dev->reg[reg_0x6d].value = dev->gpo.value[1]; + dev->reg[reg_0x6e].value = dev->gpo.enable[0]; + dev->reg[reg_0x6f].value = dev->gpo.enable[1]; */ + + dev->reg[reg_0x6b].value |= REG6B_GPO18; + dev->reg[reg_0x6b].value &= ~REG6B_GPO17; + + sanei_gl841_setup_sensor (dev, dev->reg, 0, 0); +} + +/* + * Set all registers to default values * (function called only once at the beginning) */ static void @@ -789,6 +957,11 @@ gl841_init_registers (Genesys_Device * dev) nr = 0; memset (dev->reg, 0, GENESYS_MAX_REGS * sizeof (Genesys_Register_Set)); + if (strcmp (dev->model->name, "canon-lide-80") == 0) + { + gl841_init_lide80(dev); + return ; + } for (addr = 1; addr <= 0x0a; addr++) dev->reg[nr++].address = addr; @@ -814,12 +987,12 @@ gl841_init_registers (Genesys_Device * dev) { dev->reg[reg_0x01].value &= ~REG01_CISSET; } - + dev->reg[reg_0x02].value = 0x30 /*0x38 */ ; /* auto home, one-table-move, full step */ dev->reg[reg_0x02].value |= REG02_AGOHOME; dev->reg[reg_0x02].value |= REG02_MTRPWR; dev->reg[reg_0x02].value |= REG02_FASTFED; - + dev->reg[reg_0x03].value = 0x1f /*0x17 */ ; /* lamp on */ dev->reg[reg_0x03].value |= REG03_AVEENB; @@ -842,7 +1015,7 @@ gl841_init_registers (Genesys_Device * dev) else { dev->reg[reg_0x05].value |= REG05_DPIHW_2400; - DBG (DBG_warn, + DBG (DBG_warn, "gl841_init_registers: Cannot handle sensor pixel count %d\n", dev->sensor.sensor_pixels); } @@ -861,9 +1034,9 @@ gl841_init_registers (Genesys_Device * dev) else { dev->reg[reg_0x06].value |= 0x05 << REG06S_SCANMOD; /* 15 clocks/pixel */ - dev->reg[reg_0x09].value = 0; /* 24 MHz CLKSET */ + dev->reg[reg_0x09].value = 0; /* 24 MHz CLKSET */ } - + dev->reg[reg_0x1e].value = 0xf0; /* watch-dog time */ dev->reg[reg_0x17].value |= 1 << REG17S_TGW; @@ -879,7 +1052,7 @@ gl841_init_registers (Genesys_Device * dev) /*BUFSEL*/ dev->reg[reg_0x20].value = 0x20; - + /*LAMPPWM*/ dev->reg[reg_0x29].value = 0xff; @@ -905,7 +1078,7 @@ gl841_init_registers (Genesys_Device * dev) /*STOPTIM*/ dev->reg[reg_0x5e].value |= 0x2 << REG5ES_STOPTIM; - sanei_gl841_setup_sensor (dev, dev->reg, 0, 0); + sanei_gl841_setup_sensor (dev, dev->reg, 0, 0); /* set up GPIO */ dev->reg[reg_0x6c].value = dev->gpo.value[0]; @@ -913,18 +1086,24 @@ gl841_init_registers (Genesys_Device * dev) dev->reg[reg_0x6e].value = dev->gpo.enable[0]; dev->reg[reg_0x6f].value = dev->gpo.enable[1]; - if (dev->model->gpo_type == GPO_CANONLIDE35) + /* TODO there is a switch calling to be written here */ + if (dev->model->gpo_type == GPO_CANONLIDE35) + { + dev->reg[reg_0x6b].value |= REG6B_GPO18; + dev->reg[reg_0x6b].value &= ~REG6B_GPO17; + } + if (dev->model->gpo_type == GPO_CANONLIDE80) { dev->reg[reg_0x6b].value |= REG6B_GPO18; dev->reg[reg_0x6b].value &= ~REG6B_GPO17; } - if (dev->model->gpo_type == GPO_XP300) + if (dev->model->gpo_type == GPO_XP300) { dev->reg[reg_0x6b].value |= REG6B_GPO17; } - if (dev->model->gpo_type == GPO_DP685) + if (dev->model->gpo_type == GPO_DP685) { /* REG6B_GPO18 lights on green led */ dev->reg[reg_0x6b].value |= REG6B_GPO17|REG6B_GPO18; @@ -933,10 +1112,10 @@ gl841_init_registers (Genesys_Device * dev) DBG (DBG_proc, "gl841_init_registers complete\n"); } -/* Send slope table for motor movement +/* Send slope table for motor movement slope_table in machine byte order */ -static SANE_Status +GENESYS_STATIC SANE_Status gl841_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { @@ -944,6 +1123,7 @@ gl841_send_slope_table (Genesys_Device * dev, int table_nr, int start_address; SANE_Status status; uint8_t *table; + char msg[4000]; /*#ifdef WORDS_BIGENDIAN*/ int i; /*#endif*/ @@ -971,6 +1151,15 @@ gl841_send_slope_table (Genesys_Device * dev, int table_nr, /*#else table = (uint8_t*)slope_table; #endif*/ + if (DBG_LEVEL >= DBG_io) + { + sprintf (msg, "write slope %d (%d)=", table_nr, steps); + for (i = 0; i < steps; i++) + { + sprintf (msg+strlen(msg), ",%d", slope_table[i]); + } + DBG (DBG_io, "%s: %s\n", __FUNCTION__, msg); + } status = sanei_genesys_set_buffer_address (dev, start_address + table_nr * 0x200); @@ -1005,13 +1194,88 @@ gl841_send_slope_table (Genesys_Device * dev, int table_nr, DBG (DBG_proc, "gl841_send_slope_table: completed\n"); return status; } - + +static SANE_Status +gl841_set_lide80_fe (Genesys_Device * dev, uint8_t set) +{ + SANE_Status status = SANE_STATUS_GOOD; + + DBGSTART; + + if (set == AFE_INIT) + { + DBG (DBG_proc, "%s(): setting DAC %u\n", __FUNCTION__, + dev->model->dac_type); + + /* sets to default values */ + sanei_genesys_init_fe (dev); + + /* write them to analog frontend */ + status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: writing reg 0x00 failed: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.reg[1]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: writing reg 0x03 failed: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + status = sanei_genesys_fe_write_data (dev, 0x06, dev->frontend.reg[2]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: writing reg 0x06 failed: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + } + + if (set == AFE_SET) + { + status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: writing reg 0x00 failed: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + status = sanei_genesys_fe_write_data (dev, 0x06, dev->frontend.offset[0]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: writing offset failed: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.gain[0]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: writing gain failed: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + } + + return status; + DBGCOMPLETED; +} + /* Set values of Analog Device type frontend */ static SANE_Status gl841_set_ad_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status = SANE_STATUS_GOOD; int i; + + /* special case for LiDE 80 analog frontend */ + if(dev->model->dac_type==DAC_CANONLIDE80) + { + return gl841_set_lide80_fe(dev, set); + } + DBG (DBG_proc, "gl841_set_ad_fe(): start\n"); if (set == AFE_INIT) { @@ -1309,7 +1573,7 @@ gl841_set_fe (Genesys_Device * dev, uint8_t set) */ static SANE_Status gl841_init_motor_regs_off(Genesys_Register_Set * reg, - unsigned int scan_lines) + unsigned int scan_lines) { unsigned int feedl; Genesys_Register_Set * r; @@ -1318,21 +1582,21 @@ gl841_init_motor_regs_off(Genesys_Register_Set * reg, scan_lines); feedl = 2; - + r = sanei_genesys_get_address (reg, 0x3d); r->value = (feedl >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x3e); r->value = (feedl >> 8) & 0xff; - r = sanei_genesys_get_address (reg, 0x3f); + r = sanei_genesys_get_address (reg, 0x3f); r->value = feedl & 0xff; - r = sanei_genesys_get_address (reg, 0x5e); + r = sanei_genesys_get_address (reg, 0x5e); r->value &= ~0xe0; r = sanei_genesys_get_address (reg, 0x25); r->value = (scan_lines >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x26); r->value = (scan_lines >> 8) & 0xff; - r = sanei_genesys_get_address (reg, 0x27); + r = sanei_genesys_get_address (reg, 0x27); r->value = scan_lines & 0xff; r = sanei_genesys_get_address (reg, 0x02); @@ -1349,43 +1613,95 @@ gl841_init_motor_regs_off(Genesys_Register_Set * reg, r->value &= ~0x40; - r = sanei_genesys_get_address (reg, 0x67); + r = sanei_genesys_get_address (reg, 0x67); r->value = 0x3f; r = sanei_genesys_get_address (reg, 0x68); r->value = 0x3f; - r = sanei_genesys_get_address (reg, 0x21); + r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = 0; - - r = sanei_genesys_get_address (reg, 0x24); + + r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = 0; - + r = sanei_genesys_get_address (reg, 0x69); r->value = 0; - + r = sanei_genesys_get_address (reg, 0x6a); r->value = 0; - + r = sanei_genesys_get_address (reg, 0x5f); r->value = 0; - DBG (DBG_proc, "gl841_init_motor_regs_off : completed. \n"); + DBGCOMPLETED; + return SANE_STATUS_GOOD; +} + +/** @brief write motor table frequency + * Write motor frequency data table. + * @param dev device to set up motor + * @param ydpi motor target resolution + * @return SANE_STATUS_GOOD on success + */ +GENESYS_STATIC SANE_Status gl841_write_freq(Genesys_Device *dev, unsigned int ydpi) +{ +SANE_Status status; +/**< fast table */ +uint8_t tdefault[] = {0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76}; +uint8_t t1200[] = {0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20}; +uint8_t t300[] = {0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60}; +uint8_t t150[] = {0x0c,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0x40,0x14,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x0c,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0x11,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x0c,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0x40,0xd4,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x0c,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0x11,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60}; + +uint8_t *table; - return SANE_STATUS_GOOD; + DBGSTART; + if(dev->model->motor_type == MOTOR_CANONLIDE80) + { + switch(ydpi) + { + case 3600: + case 1200: + table=t1200; + break; + case 900: + case 300: + table=t300; + break; + case 450: + case 150: + table=t150; + break; + default: + table=tdefault; + } + RIE(sanei_genesys_write_register(dev, 0x66, 0x00)); + RIE(sanei_genesys_write_register(dev, 0x5b, 0x0c)); + RIE(sanei_genesys_write_register(dev, 0x5c, 0x00)); + RIE(gl841_bulk_write_data_gamma (dev, 0x28, table, 128)); + RIE(sanei_genesys_write_register(dev, 0x5b, 0x00)); + RIE(sanei_genesys_write_register(dev, 0x5c, 0x00)); + } + DBGCOMPLETED; + return SANE_STATUS_GOOD; } -static SANE_Status + +#ifndef UNIT_TESTING +static +#endif +SANE_Status gl841_init_motor_regs(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int feed_steps,/*1/base_ydpi*/ /*maybe float for half/quarter step resolution?*/ unsigned int action, - unsigned int flags) + unsigned int flags) { SANE_Status status; unsigned int fast_exposure; + int scan_power_mode; int use_fast_fed = 0; uint16_t fast_slope_table[256]; unsigned int fast_slope_steps = 0; @@ -1399,49 +1715,48 @@ gl841_init_motor_regs(Genesys_Device * dev, flags); memset(fast_slope_table,0xff,512); - + gl841_send_slope_table (dev, 0, fast_slope_table, 256); gl841_send_slope_table (dev, 1, fast_slope_table, 256); gl841_send_slope_table (dev, 2, fast_slope_table, 256); gl841_send_slope_table (dev, 3, fast_slope_table, 256); gl841_send_slope_table (dev, 4, fast_slope_table, 256); + gl841_write_freq(dev, dev->motor.base_ydpi / 4); - if (action == MOTOR_ACTION_FEED || action == MOTOR_ACTION_GO_HOME) { -/* FEED and GO_HOME can use fastest slopes available */ - fast_slope_steps = 256; - fast_exposure = sanei_genesys_exposure_time2( - dev, - dev->motor.base_ydpi / 4, - 0,/*step_type*/ - 0,/*last used pixel*/ - 0, - 0); - - DBG (DBG_info, "gl841_init_motor_regs : fast_exposure=%d pixels\n", - fast_exposure); - } + fast_slope_steps = 256; + if (action == MOTOR_ACTION_FEED || action == MOTOR_ACTION_GO_HOME) + { + /* FEED and GO_HOME can use fastest slopes available */ + fast_exposure = gl841_exposure_time(dev, + dev->motor.base_ydpi / 4, + 0, + 0, + 0, + &scan_power_mode); + DBG (DBG_info, "%s : fast_exposure=%d pixels\n", __FUNCTION__, fast_exposure); + } if (action == MOTOR_ACTION_HOME_FREE) { /* HOME_FREE must be able to stop in one step, so do not try to get faster */ - fast_slope_steps = 256; fast_exposure = dev->motor.slopes[0][0].maximum_start_speed; } sanei_genesys_create_slope_table3 ( dev, - fast_slope_table, 256, + fast_slope_table, + 256, fast_slope_steps, - 0, + 0, fast_exposure, dev->motor.base_ydpi / 4, &fast_slope_steps, &fast_exposure, 0); - + feedl = feed_steps - fast_slope_steps*2; use_fast_fed = 1; - -/* all needed slopes available. we did even decide which mode to use. + +/* all needed slopes available. we did even decide which mode to use. what next? - transfer slopes SCAN: @@ -1475,16 +1790,16 @@ HOME_FREE: 3 r->value = (feedl >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x3e); r->value = (feedl >> 8) & 0xff; - r = sanei_genesys_get_address (reg, 0x3f); + r = sanei_genesys_get_address (reg, 0x3f); r->value = feedl & 0xff; - r = sanei_genesys_get_address (reg, 0x5e); + r = sanei_genesys_get_address (reg, 0x5e); r->value &= ~0xe0; r = sanei_genesys_get_address (reg, 0x25); r->value = 0; r = sanei_genesys_get_address (reg, 0x26); r->value = 0; - r = sanei_genesys_get_address (reg, 0x27); + r = sanei_genesys_get_address (reg, 0x27); r->value = 0; r = sanei_genesys_get_address (reg, 0x02); @@ -1493,7 +1808,7 @@ HOME_FREE: 3 r->value |= 0x10; - if (action == MOTOR_ACTION_GO_HOME) + if (action == MOTOR_ACTION_GO_HOME) r->value |= 0x06; else r->value &= ~0x06; @@ -1511,38 +1826,40 @@ HOME_FREE: 3 r->value &= ~0x40; status = gl841_send_slope_table (dev, 3, fast_slope_table, 256); - + if (status != SANE_STATUS_GOOD) return status; - - r = sanei_genesys_get_address (reg, 0x67); + + r = sanei_genesys_get_address (reg, 0x67); r->value = 0x3f; r = sanei_genesys_get_address (reg, 0x68); r->value = 0x3f; - r = sanei_genesys_get_address (reg, 0x21); + r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = 0; - - r = sanei_genesys_get_address (reg, 0x24); + + r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = 0; - + r = sanei_genesys_get_address (reg, 0x69); r->value = 0; - + r = sanei_genesys_get_address (reg, 0x6a); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); - + r = sanei_genesys_get_address (reg, 0x5f); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); - DBG (DBG_proc, "gl841_init_motor_regs : completed. \n"); - - return SANE_STATUS_GOOD; + DBGCOMPLETED; + return SANE_STATUS_GOOD; } -static SANE_Status +#ifndef UNIT_TESTING +static +#endif +SANE_Status gl841_init_motor_regs_scan(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int scan_exposure_time,/*pixel*/ @@ -1554,11 +1871,12 @@ gl841_init_motor_regs_scan(Genesys_Device * dev, unsigned int feed_steps,/*1/base_ydpi*/ /*maybe float for half/quarter step resolution?*/ int scan_power_mode, - unsigned int flags) + unsigned int flags) { SANE_Status status; unsigned int fast_exposure; int use_fast_fed = 0; + int dummy_power_mode; unsigned int fast_time; unsigned int slow_time; uint16_t slow_slope_table[256]; @@ -1586,26 +1904,25 @@ gl841_init_motor_regs_scan(Genesys_Device * dev, scan_power_mode, flags); - fast_exposure = sanei_genesys_exposure_time2( - dev, - dev->motor.base_ydpi / 4, - 0,/*step_type*/ - 0,/*last used pixel*/ - 0, - scan_power_mode); - - DBG (DBG_info, "gl841_init_motor_regs_scan : fast_exposure=%d pixels\n", - fast_exposure); + fast_exposure = gl841_exposure_time(dev, + dev->motor.base_ydpi / 4, + 0, + 0, + 0, + &dummy_power_mode); + DBG (DBG_info, "%s : fast_exposure=%d pixels\n", __FUNCTION__, fast_exposure); memset(slow_slope_table,0xff,512); - + gl841_send_slope_table (dev, 0, slow_slope_table, 256); gl841_send_slope_table (dev, 1, slow_slope_table, 256); gl841_send_slope_table (dev, 2, slow_slope_table, 256); gl841_send_slope_table (dev, 3, slow_slope_table, 256); gl841_send_slope_table (dev, 4, slow_slope_table, 256); + /* motor frequency table */ + gl841_write_freq(dev, scan_yres); /* we calculate both tables for SCAN. the fast slope step count depends on @@ -1616,53 +1933,55 @@ gl841_init_motor_regs_scan(Genesys_Device * dev, dev, slow_slope_table, 256, 256, - scan_step_type, + scan_step_type, scan_exposure_time, scan_yres, &slow_slope_steps, NULL, scan_power_mode); - + sanei_genesys_create_slope_table3 ( dev, back_slope_table, 256, 256, - scan_step_type, + scan_step_type, 0, scan_yres, &back_slope_steps, NULL, scan_power_mode); - + if (feed_steps < (slow_slope_steps >> scan_step_type)) { /*TODO: what should we do here?? go back to exposure calculation?*/ feed_steps = slow_slope_steps >> scan_step_type; } - - if (feed_steps > fast_slope_steps*2 - - (slow_slope_steps >> scan_step_type)) + + if (feed_steps > fast_slope_steps*2 - + (slow_slope_steps >> scan_step_type)) fast_slope_steps = 256; - else + else /* we need to shorten fast_slope_steps here. */ - fast_slope_steps = (feed_steps - + fast_slope_steps = (feed_steps - (slow_slope_steps >> scan_step_type))/2; - + DBG(DBG_info,"gl841_init_motor_regs_scan: Maximum allowed slope steps for fast slope: %d\n",fast_slope_steps); - + fast_slope_time = sanei_genesys_create_slope_table3 ( dev, fast_slope_table, 256, fast_slope_steps, - 0, + 0, fast_exposure, dev->motor.base_ydpi / 4, &fast_slope_steps, &fast_exposure, scan_power_mode); - - if (dev->model->gpo_type == GPO_XP300 || dev->model->gpo_type == GPO_DP685) + + /* fast fed special cases handling */ + if (dev->model->gpo_type == GPO_XP300 + || dev->model->gpo_type == GPO_DP685) { - /* quirk: looks like at least this scanner is unable to use + /* quirk: looks like at least this scanner is unable to use 2-feed mode */ use_fast_fed = 0; } @@ -1670,36 +1989,36 @@ gl841_init_motor_regs_scan(Genesys_Device * dev, use_fast_fed = 0; DBG(DBG_info,"gl841_init_motor_regs_scan: feed too short, slow move forced.\n"); } else { -/* for deciding whether we should use fast mode we need to check how long we - need for (fast)accelerating, moving, decelerating, (TODO: stopping?) - (slow)accelerating again versus (slow)accelerating and moving. we need +/* for deciding whether we should use fast mode we need to check how long we + need for (fast)accelerating, moving, decelerating, (TODO: stopping?) + (slow)accelerating again versus (slow)accelerating and moving. we need fast and slow tables here. */ /*NOTE: scan_exposure_time is per scan_yres*/ /*NOTE: fast_exposure is per base_ydpi/4*/ /*we use full steps as base unit here*/ - fast_time = + fast_time = fast_exposure / 4 * - (feed_steps - fast_slope_steps*2 - - (slow_slope_steps >> scan_step_type)) + (feed_steps - fast_slope_steps*2 - + (slow_slope_steps >> scan_step_type)) + fast_slope_time*2 + slow_slope_time; - slow_time = + slow_time = (scan_exposure_time * scan_yres) / dev->motor.base_ydpi * - (feed_steps - (slow_slope_steps >> scan_step_type)) + (feed_steps - (slow_slope_steps >> scan_step_type)) + slow_slope_time; DBG(DBG_info,"gl841_init_motor_regs_scan: Time for slow move: %d\n", slow_time); DBG(DBG_info,"gl841_init_motor_regs_scan: Time for fast move: %d\n", fast_time); - + use_fast_fed = fast_time < slow_time; } - - if (use_fast_fed) - feedl = feed_steps - fast_slope_steps*2 - + + if (use_fast_fed) + feedl = feed_steps - fast_slope_steps*2 - (slow_slope_steps >> scan_step_type); - else + else if ((feed_steps << scan_step_type) < slow_slope_steps) feedl = 0; else @@ -1707,7 +2026,7 @@ gl841_init_motor_regs_scan(Genesys_Device * dev, DBG(DBG_info,"gl841_init_motor_regs_scan: Decided to use %s mode\n", use_fast_fed?"fast feed":"slow feed"); -/* all needed slopes available. we did even decide which mode to use. +/* all needed slopes available. we did even decide which mode to use. what next? - transfer slopes SCAN: @@ -1741,16 +2060,16 @@ HOME_FREE: 3 r->value = (feedl >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x3e); r->value = (feedl >> 8) & 0xff; - r = sanei_genesys_get_address (reg, 0x3f); + r = sanei_genesys_get_address (reg, 0x3f); r->value = feedl & 0xff; - r = sanei_genesys_get_address (reg, 0x5e); + r = sanei_genesys_get_address (reg, 0x5e); r->value &= ~0xe0; r = sanei_genesys_get_address (reg, 0x25); r->value = (scan_lines >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x26); r->value = (scan_lines >> 8) & 0xff; - r = sanei_genesys_get_address (reg, 0x27); + r = sanei_genesys_get_address (reg, 0x27); r->value = scan_lines & 0xff; r = sanei_genesys_get_address (reg, 0x02); @@ -1776,35 +2095,35 @@ HOME_FREE: 3 r->value &= ~0x40; status = gl841_send_slope_table (dev, 0, slow_slope_table, 256); - + if (status != SANE_STATUS_GOOD) return status; - + status = gl841_send_slope_table (dev, 1, back_slope_table, 256); - + if (status != SANE_STATUS_GOOD) return status; - + status = gl841_send_slope_table (dev, 2, slow_slope_table, 256); - + if (status != SANE_STATUS_GOOD) return status; - + if (use_fast_fed) { status = gl841_send_slope_table (dev, 3, fast_slope_table, 256); - + if (status != SANE_STATUS_GOOD) return status; } - + if (flags & MOTOR_FLAG_AUTO_GO_HOME){ status = gl841_send_slope_table (dev, 4, fast_slope_table, 256); - + if (status != SANE_STATUS_GOOD) return status; } - - + + /* now reg 0x21 and 0x24 are available, we can calculate reg 0x22 and 0x23, reg 0x60-0x62 and reg 0x63-0x65 rule: @@ -1814,15 +2133,15 @@ HOME_FREE: 3 if (min_restep < slow_slope_steps*2+2) min_restep = slow_slope_steps*2+2; /* steps of table 1*/ - if (min_restep < back_slope_steps*2+2) + if (min_restep < back_slope_steps*2+2) min_restep = back_slope_steps*2+2; /* steps of table 0*/ - r = sanei_genesys_get_address (reg, 0x22); + r = sanei_genesys_get_address (reg, REG_FWDSTEP); r->value = min_restep - slow_slope_steps*2; /* steps of table 1*/ - r = sanei_genesys_get_address (reg, 0x23); + r = sanei_genesys_get_address (reg, REG_BWDSTEP); r->value = min_restep - back_slope_steps*2; - + /* for z1/z2: in dokumentation mentioned variables a-d: @@ -1830,16 +2149,16 @@ HOME_FREE: 3 b = time needed for reg 0x1f... wouldn't that be reg0x1f*exposure_time? c = time needed for acceleration, table 1 d = time needed for reg 0x22... wouldn't that be reg0x22*exposure_time? - z1 = (c+d-1) % exposure_time + z1 = (c+d-1) % exposure_time z2 = (a+b-1) % exposure_time */ -/* i don't see any effect of this. i can only guess that this will enhance +/* i don't see any effect of this. i can only guess that this will enhance sub-pixel accuracy z1 = (slope_0_time-1) % exposure_time; z2 = (slope_0_time-1) % exposure_time; */ z1 = z2 = 0; - + DBG (DBG_info, "gl841_init_motor_regs_scan: z1 = %d\n", z1); DBG (DBG_info, "gl841_init_motor_regs_scan: z2 = %d\n", z2); r = sanei_genesys_get_address (reg, 0x60); @@ -1854,40 +2173,39 @@ HOME_FREE: 3 r->value = ((z2 >> 8) & 0xff); r = sanei_genesys_get_address (reg, 0x65); r->value = (z2 & 0xff); - - r = sanei_genesys_get_address (reg, 0x1e); - r->value &= 0xf0; /* 0 dummy lines */ - r->value |= scan_dummy; /* dummy lines */ - r = sanei_genesys_get_address (reg, 0x67); + r = sanei_genesys_get_address (reg, REG1E); + r->value &= REG1E_WDTIME; + r->value |= scan_dummy; + + r = sanei_genesys_get_address (reg, 0x67); r->value = 0x3f | (scan_step_type << 6); r = sanei_genesys_get_address (reg, 0x68); r->value = 0x3f; - r = sanei_genesys_get_address (reg, 0x21); + r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = (slow_slope_steps >> 1) + (slow_slope_steps & 1); - - r = sanei_genesys_get_address (reg, 0x24); + + r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = (back_slope_steps >> 1) + (back_slope_steps & 1); - + r = sanei_genesys_get_address (reg, 0x69); r->value = (slow_slope_steps >> 1) + (slow_slope_steps & 1); - + r = sanei_genesys_get_address (reg, 0x6a); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); - + r = sanei_genesys_get_address (reg, 0x5f); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); - DBG (DBG_proc, "gl841_init_motor_regs_scan : completed. \n"); - - return SANE_STATUS_GOOD; + DBGCOMPLETED; + return SANE_STATUS_GOOD; } static int -gl841_get_dpihw(Genesys_Device * dev) +gl841_get_dpihw(Genesys_Device * dev) { Genesys_Register_Set * r; r = sanei_genesys_get_address (dev->reg, 0x05); @@ -1911,7 +2229,7 @@ gl841_init_optical_regs_off(Genesys_Register_Set * reg) r->value &= ~REG01_SCAN; DBGCOMPLETED; - return SANE_STATUS_GOOD; + return SANE_STATUS_GOOD; } static SANE_Status @@ -1919,7 +2237,7 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int exposure_time, unsigned int used_res, - unsigned int start, + unsigned int start, unsigned int pixels, int channels, int depth, @@ -1934,13 +2252,14 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, unsigned int i; Genesys_Register_Set * r; SANE_Status status; + uint16_t expavg, expr, expb, expg; DBG (DBG_proc, "gl841_init_optical_regs_scan : exposure_time=%d, " "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, " "half_ccd=%d, flags=%x\n", exposure_time, used_res, - start, + start, pixels, channels, depth, @@ -1948,7 +2267,7 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, flags); end = start + pixels; - + status = gl841_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { @@ -1957,31 +2276,45 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, sane_strstatus (status)); return status; } - + /* adjust used_res for chosen dpihw */ used_res = used_res * gl841_get_dpihw(dev) / dev->sensor.optical_res; /* - with half_ccd the optical resolution of the ccd is halfed. We don't apply this + with half_ccd the optical resolution of the ccd is halved. We don't apply this to dpihw, so we need to double dpiset. - + For the scanner only the ratio of dpiset and dpihw is of relevance to scale down properly. */ - if (half_ccd) + if (half_ccd) dpiset = used_res * 2; else dpiset = used_res; - - if (dev->model->gpo_type == GPO_CANONLIDE35) + + /* gpio part.*/ + if (dev->model->gpo_type == GPO_CANONLIDE35) { -/* gpio part.*/ r = sanei_genesys_get_address (reg, REG6C); if (half_ccd) r->value &= ~0x80; else r->value |= 0x80; } + if (dev->model->gpo_type == GPO_CANONLIDE80) + { + r = sanei_genesys_get_address (reg, REG6C); + if (half_ccd) + { + r->value &= ~0x40; + r->value |= 0x20; + } + else + { + r->value &= ~0x20; + r->value |= 0x40; + } + } /* enable shading */ r = sanei_genesys_get_address (reg, 0x01); @@ -1991,8 +2324,8 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, r->value &= ~REG01_DVDSET; else r->value |= REG01_DVDSET; - - /* average looks better than deletion, and we are already set up to + + /* average looks better than deletion, and we are already set up to use one of the average enabled resolutions */ r = sanei_genesys_get_address (reg, 0x03); @@ -2001,7 +2334,7 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, r->value &= ~REG03_LAMPPWR; else r->value |= REG03_LAMPPWR; - + /* exposure times */ r = sanei_genesys_get_address (reg, 0x10); for (i = 0; i < 6; i++, r++) { @@ -2044,23 +2377,28 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, r->value |= REG04_BITSET; break; } - + + /* AFEMOD should depend on FESET, and we should set these + * bits separately */ r->value &= ~(REG04_FILTER | REG04_AFEMOD); - if (channels == 1) + 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 |= 0x18; /* green filter */ + r->value |= 0x10; /* no filter */ break; } - } + } else { if (dev->model->ccd_type == CCD_PLUSTEK_3600) @@ -2072,56 +2410,57 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, r->value |= 0x10; /* color pixel by pixel */ } } - + /* CIS scanners can do true gray by setting LEDADD */ - if (dev->model->is_cis == SANE_TRUE) + r = sanei_genesys_get_address (reg, 0x87); + r->value &= ~REG87_LEDADD; + if (flags & OPTICAL_FLAG_ENABLE_LEDADD) { - r = sanei_genesys_get_address (reg, 0x87); - r->value &= ~REG87_LEDADD; - /* we set up LEDADD only when asked */ - if (channels==1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) - { - r->value |= REG87_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(exprreg,REG_EXPR,expavg); + sanei_genesys_set_double(dev->reg,REG_EXPG,expavg); + sanei_genesys_set_double(dev->reg,REG_EXPB,expavg); } - + /* enable gamma tables */ r = sanei_genesys_get_address (reg, 0x05); if (flags & OPTICAL_FLAG_DISABLE_GAMMA) r->value &= ~REG05_GMMENB; else r->value |= REG05_GMMENB; - + /* sensor parameters */ sanei_gl841_setup_sensor (dev, dev->reg, 1, half_ccd); - + r = sanei_genesys_get_address (reg, 0x29); r->value = 255; /*<<<"magic" number, only suitable for cis*/ - - r = sanei_genesys_get_address (reg, 0x2c); - r->value = HIBYTE (dpiset); - r = sanei_genesys_get_address (reg, 0x2d); - r->value = LOBYTE (dpiset); - - r = sanei_genesys_get_address (reg, 0x30); - r->value = HIBYTE (start); - r = sanei_genesys_get_address (reg, 0x31); - r->value = LOBYTE (start); - r = sanei_genesys_get_address (reg, 0x32); - r->value = HIBYTE (end); - r = sanei_genesys_get_address (reg, 0x33); - r->value = LOBYTE (end); - + + sanei_genesys_set_double(reg, REG_DPISET, dpiset); + sanei_genesys_set_double(reg, REG_STRPIXEL, start); + sanei_genesys_set_double(reg, REG_ENDPIXEL, end); + DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d\n",__FUNCTION__,start,end); + /* words(16bit) before gamma, conversion to 8 bit or lineart*/ - words_per_line = (pixels * dpiset) / gl841_get_dpihw(dev); - + words_per_line = (pixels * dpiset) / gl841_get_dpihw(dev); + words_per_line *= channels; if (depth == 1) words_per_line = (words_per_line >> 3) + ((words_per_line & 7)?1:0); else words_per_line *= depth / 8; - + dev->wpl = words_per_line; dev->bpl = words_per_line; @@ -2131,22 +2470,18 @@ gl841_init_optical_regs_scan(Genesys_Device * dev, r->value = HIBYTE (LOWORD (words_per_line)); r = sanei_genesys_get_address (reg, 0x37); r->value = LOBYTE (LOWORD (words_per_line)); - - r = sanei_genesys_get_address (reg, 0x38); - r->value = HIBYTE (exposure_time); - r = sanei_genesys_get_address (reg, 0x39); - r->value = LOBYTE (exposure_time); + + sanei_genesys_set_double(reg, REG_LPERIOD, exposure_time); r = sanei_genesys_get_address (reg, 0x34); r->value = dev->sensor.dummy_pixel; - DBG (DBG_proc, "gl841_init_optical_regs_scan : completed. \n"); - return SANE_STATUS_GOOD; + DBGCOMPLETED; + return SANE_STATUS_GOOD; } - -static int -gl841_get_led_exposure(Genesys_Device * dev) +static int +gl841_get_led_exposure(Genesys_Device * dev) { int d,r,g,b,m; if (!dev->model->is_cis) @@ -2161,20 +2496,97 @@ gl841_get_led_exposure(Genesys_Device * dev) m = g; if (m < b) m = b; - + return m + d; } -/* set up registers for an actual scan - * - * this function sets up the scanner to scan in normal or single line mode +/** @brief compute exposure time + * Compute exposure time for the device and the given scan resolution, + * also compute scan_power_mode */ -#ifndef UNIT_TESTING -static -#endif -SANE_Status -gl841_init_scan_regs (Genesys_Device * dev, - Genesys_Register_Set * reg, +GENESYS_STATIC int +gl841_exposure_time(Genesys_Device *dev, + float slope_dpi, + int scan_step_type, + int start, + int used_pixels, + int *scan_power_mode) +{ +int exposure_time = 0; +int exposure_time2 = 0; +int led_exposure; + + *scan_power_mode=0; + led_exposure=gl841_get_led_exposure(dev); + exposure_time = sanei_genesys_exposure_time2( + dev, + slope_dpi, + scan_step_type, + start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ + led_exposure, + *scan_power_mode); + + while(*scan_power_mode + 1 < dev->motor.power_mode_count) { + exposure_time2 = sanei_genesys_exposure_time2( + dev, + slope_dpi, + scan_step_type, + start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ + led_exposure, + *scan_power_mode + 1); + if (exposure_time < exposure_time2) + break; + exposure_time = exposure_time2; + (*scan_power_mode)++; + } + + return exposure_time; +} + +/**@brief compute scan_step_type + * Try to do at least 4 steps per line. if that is impossible we will have to + * live with that. + * @param dev device + * @param yres motor resolution + */ +GENESYS_STATIC int +gl841_scan_step_type(Genesys_Device *dev, int yres) +{ +int scan_step_type=0; + + /* TODO : check if there is a bug around the use of max_step_type */ + /* should be <=1, need to chek all devices entry in genesys_devices */ + if (yres*4 < dev->motor.base_ydpi || dev->motor.max_step_type <= 0) + { + scan_step_type = 0; + } + else if (yres*4 < dev->motor.base_ydpi*2 || dev->motor.max_step_type <= 1) + { + scan_step_type = 1; + } + else + { + scan_step_type = 2; + } + + /* this motor behaves differently */ + if (dev->model->motor_type==MOTOR_CANONLIDE80) + { + /* driven by 'frequency' tables ? */ + scan_step_type = 0; + } + + return scan_step_type; +} + +/* set up registers for an actual scan + * + * this function sets up the scanner to scan in normal or single line mode + */ +GENESYS_STATIC +SANE_Status +gl841_init_scan_regs (Genesys_Device * dev, + Genesys_Register_Set * reg, float xres,/*dpi*/ float yres,/*dpi*/ float startx,/*optical_res, from dummy_pixel+1*/ @@ -2192,20 +2604,22 @@ gl841_init_scan_regs (Genesys_Device * dev, int bytes_per_line; int move; unsigned int lincnt; - int exposure_time, exposure_time2, led_exposure; + int exposure_time; + int scan_power_mode; int i; int stagger; + int avg; int slope_dpi = 0; int dummy = 0; int scan_step_type = 1; - int scan_power_mode = 0; int max_shift; size_t requested_buffer_size, read_buffer_size; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; SANE_Status status; + unsigned int oflags; /**> optical flags */ DBG (DBG_info, "gl841_init_scan_regs settings:\n" @@ -2281,34 +2695,32 @@ independent of our calculated values: if (i < 2 || (flags & SCAN_FLAG_USE_OPTICAL_RES)) /* optical_res >= xres > optical_res/2 */ used_res = optical_res; else if (i < 3) /* optical_res/2 >= xres > optical_res/3 */ - used_res = optical_res/2; + used_res = optical_res/2; else if (i < 4) /* optical_res/3 >= xres > optical_res/4 */ - used_res = optical_res/3; + used_res = optical_res/3; else if (i < 5) /* optical_res/4 >= xres > optical_res/5 */ - used_res = optical_res/4; + used_res = optical_res/4; else if (i < 6) /* optical_res/5 >= xres > optical_res/6 */ - used_res = optical_res/5; + used_res = optical_res/5; else if (i < 8) /* optical_res/6 >= xres > optical_res/8 */ - used_res = optical_res/6; + used_res = optical_res/6; else if (i < 10) /* optical_res/8 >= xres > optical_res/10 */ - used_res = optical_res/8; + used_res = optical_res/8; else if (i < 12) /* optical_res/10 >= xres > optical_res/12 */ - used_res = optical_res/10; + used_res = optical_res/10; else if (i < 15) /* optical_res/12 >= xres > optical_res/15 */ - used_res = optical_res/12; + used_res = optical_res/12; else used_res = optical_res/15; /* compute scan parameters values */ /* pixels are allways given at half or full CCD optical resolution */ /* use detected left margin and fixed value */ -/* start */ + /* start */ /* add x coordinates */ - start = - ((dev->sensor.CCD_start_xoffset + startx) * used_res) / - dev->sensor.optical_res; + start = ((dev->sensor.CCD_start_xoffset + startx) * used_res) / dev->sensor.optical_res; -/* needs to be aligned for used_res */ + /* needs to be aligned for used_res */ start = (start * optical_res) / used_res; start += dev->sensor.dummy_pixel + 1; @@ -2316,10 +2728,19 @@ independent of our calculated values: if (stagger > 0) start |= 1; + /* in case of SHDAREA, we need to align start + * on pixel average factor, startx is different of + * 0 only when calling for function to setup for + * scan, where shading data needs to be align */ + if((dev->reg[reg_0x01].value & REG01_SHDAREA) != 0) + { + avg=optical_res/used_res; + start=(start/avg)*avg; + } + /* compute correct pixels number */ -/* pixels */ - used_pixels = - (pixels * optical_res) / xres; + /* pixels */ + used_pixels = (pixels * optical_res) / xres; /* round up pixels number if needed */ if (used_pixels * xres < pixels * optical_res) @@ -2327,8 +2748,8 @@ independent of our calculated values: /* dummy */ /* dummy lines: may not be usefull, for instance 250 dpi works with 0 or 1 - dummy line. Maybe the dummy line adds correctness since the motor runs - slower (higher dpi) + dummy line. Maybe the dummy line adds correctness since the motor runs + slower (higher dpi) */ /* for cis this creates better aligned color lines: dummy \ scanned lines @@ -2355,86 +2776,64 @@ dummy \ scanned lines /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ - if (dev->model->is_cis) + if (dev->model->is_cis) slope_dpi = yres*channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); -/* scan_step_type */ -/* Try to do at least 4 steps per line. if that is impossible we will have to - live with that - */ - if (yres*4 < dev->motor.base_ydpi - || dev->motor.max_step_type <= 0) - scan_step_type = 0; - else if (yres*4 < dev->motor.base_ydpi*2 - || dev->motor.max_step_type <= 1) - scan_step_type = 1; - else - scan_step_type = 2; - -/* exposure_time */ - led_exposure = gl841_get_led_exposure(dev); - - exposure_time = sanei_genesys_exposure_time2( - dev, - slope_dpi, - scan_step_type, - start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ - led_exposure, - scan_power_mode); - - while(scan_power_mode + 1 < dev->motor.power_mode_count) { - exposure_time2 = sanei_genesys_exposure_time2( - dev, - slope_dpi, - scan_step_type, - start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ - led_exposure, - scan_power_mode + 1); - if (exposure_time < exposure_time2) - break; - exposure_time = exposure_time2; - scan_power_mode++; - } - - - DBG (DBG_info, "gl841_init_scan_regs : exposure_time=%d pixels\n", - exposure_time); + scan_step_type = gl841_scan_step_type(dev, yres); + exposure_time = gl841_exposure_time(dev, + slope_dpi, + scan_step_type, + start, + used_pixels, + &scan_power_mode); + DBG (DBG_info, "%s : exposure_time=%d pixels\n", __FUNCTION__, exposure_time); -/*** optical parameters ***/ + /*** optical parameters ***/ /* in case of dynamic lineart, we use an internal 8 bit gray scan * to generate 1 lineart data */ if(flags & SCAN_FLAG_DYNAMIC_LINEART) { depth=8; } - if (depth == 16) - flags |= SCAN_FLAG_DISABLE_GAMMA; - status = gl841_init_optical_regs_scan(dev, - reg, + oflags=0; + if (flags & SCAN_FLAG_DISABLE_SHADING) + { + oflags |= OPTICAL_FLAG_DISABLE_SHADING; + } + if ((flags & SCAN_FLAG_DISABLE_GAMMA) || (depth==16)) + { + oflags |= OPTICAL_FLAG_DISABLE_GAMMA; + } + if (flags & SCAN_FLAG_DISABLE_LAMP) + { + oflags |= OPTICAL_FLAG_DISABLE_LAMP; + } + if (flags & SCAN_FLAG_ENABLE_LEDADD) + { + oflags |= OPTICAL_FLAG_ENABLE_LEDADD; + } + + status = gl841_init_optical_regs_scan(dev, + reg, exposure_time, used_res, - start, + start, used_pixels, channels, depth, half_ccd, color_filter, - ((flags & SCAN_FLAG_DISABLE_SHADING)? - OPTICAL_FLAG_DISABLE_SHADING:0) | - ((flags & SCAN_FLAG_DISABLE_GAMMA)? - OPTICAL_FLAG_DISABLE_GAMMA:0) | - ((flags & SCAN_FLAG_DISABLE_LAMP)? - OPTICAL_FLAG_DISABLE_LAMP:0) - ); - + oflags); if (status != SANE_STATUS_GOOD) + { return status; - + } + /*** motor parameters ***/ /* scanned area must be enlarged by max color shift needed */ @@ -2482,7 +2881,7 @@ dummy \ scanned lines /*** prepares data reordering ***/ /* words_per_line */ - bytes_per_line = (used_pixels * used_res) / optical_res; + bytes_per_line = (used_pixels * used_res) / optical_res; bytes_per_line = (bytes_per_line * channels * depth) / 8; requested_buffer_size = 8 * bytes_per_line; @@ -2500,13 +2899,13 @@ dummy \ scanned lines RIE(sanei_genesys_buffer_free(&(dev->lines_buffer))); RIE(sanei_genesys_buffer_alloc(&(dev->lines_buffer), read_buffer_size)); - + RIE(sanei_genesys_buffer_free(&(dev->shrink_buffer))); - RIE(sanei_genesys_buffer_alloc(&(dev->shrink_buffer), + RIE(sanei_genesys_buffer_alloc(&(dev->shrink_buffer), requested_buffer_size)); - + RIE(sanei_genesys_buffer_free(&(dev->out_buffer))); - RIE(sanei_genesys_buffer_alloc(&(dev->out_buffer), + RIE(sanei_genesys_buffer_alloc(&(dev->out_buffer), (8 * dev->settings.pixels * channels * depth) / 8)); @@ -2534,12 +2933,12 @@ dummy \ scanned lines /* theory : target_size = (dev->settings.pixels * dev->settings.lines * channels * depth) / 8; - but it suffers from integer overflow so we do the following: + but it suffers from integer overflow so we do the following: - 1 bit color images store color data byte-wise, eg byte 0 contains - 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains + 1 bit color images store color data byte-wise, eg byte 0 contains + 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 8 bits of blue. - This does not fix the overflow, though. + This does not fix the overflow, though. 644mp*16 = 10gp, leading to an overflow -- pierre */ @@ -2578,14 +2977,14 @@ gl841_calculate_current_setup (Genesys_Device * dev) int used_res; int used_pixels; unsigned int lincnt; - int exposure_time, exposure_time2, led_exposure; + int exposure_time; + int scan_power_mode; int i; int stagger; int slope_dpi = 0; int dummy = 0; int scan_step_type = 1; - int scan_power_mode = 0; int max_shift; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ @@ -2669,21 +3068,21 @@ gl841_calculate_current_setup (Genesys_Device * dev) if (i < 2) /* optical_res >= xres > optical_res/2 */ used_res = optical_res; else if (i < 3) /* optical_res/2 >= xres > optical_res/3 */ - used_res = optical_res/2; + used_res = optical_res/2; else if (i < 4) /* optical_res/3 >= xres > optical_res/4 */ - used_res = optical_res/3; + used_res = optical_res/3; else if (i < 5) /* optical_res/4 >= xres > optical_res/5 */ - used_res = optical_res/4; + used_res = optical_res/4; else if (i < 6) /* optical_res/5 >= xres > optical_res/6 */ - used_res = optical_res/5; + used_res = optical_res/5; else if (i < 8) /* optical_res/6 >= xres > optical_res/8 */ - used_res = optical_res/6; + used_res = optical_res/6; else if (i < 10) /* optical_res/8 >= xres > optical_res/10 */ - used_res = optical_res/8; + used_res = optical_res/8; else if (i < 12) /* optical_res/10 >= xres > optical_res/12 */ - used_res = optical_res/10; + used_res = optical_res/10; else if (i < 15) /* optical_res/12 >= xres > optical_res/15 */ - used_res = optical_res/12; + used_res = optical_res/12; else used_res = optical_res/15; @@ -2692,7 +3091,7 @@ gl841_calculate_current_setup (Genesys_Device * dev) /* use detected left margin and fixed value */ /* start */ /* add x coordinates */ - start = + start = ((dev->sensor.CCD_start_xoffset + startx) * used_res) / dev->sensor.optical_res; @@ -2715,8 +3114,8 @@ gl841_calculate_current_setup (Genesys_Device * dev) /* dummy */ /* dummy lines: may not be usefull, for instance 250 dpi works with 0 or 1 - dummy line. Maybe the dummy line adds correctness since the motor runs - slower (higher dpi) + dummy line. Maybe the dummy line adds correctness since the motor runs + slower (higher dpi) */ /* for cis this creates better aligned color lines: dummy \ scanned lines @@ -2743,53 +3142,21 @@ dummy \ scanned lines /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ - if (dev->model->is_cis) + if (dev->model->is_cis) slope_dpi = yres*channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); -/* scan_step_type */ -/* Try to do at least 4 steps per line. if that is impossible we will have to - live with that - */ - if (yres*4 < dev->motor.base_ydpi - || dev->motor.max_step_type <= 0) - scan_step_type = 0; - else if (yres*4 < dev->motor.base_ydpi*2 - || dev->motor.max_step_type <= 1) - scan_step_type = 1; - else - scan_step_type = 2; - - led_exposure = gl841_get_led_exposure(dev); - -/* exposure_time */ - exposure_time = sanei_genesys_exposure_time2( - dev, - slope_dpi, - scan_step_type, - start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ - led_exposure, - scan_power_mode); - - while(scan_power_mode + 1 < dev->motor.power_mode_count) { - exposure_time2 = sanei_genesys_exposure_time2( - dev, - slope_dpi, - scan_step_type, - start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ - led_exposure, - scan_power_mode + 1); - if (exposure_time < exposure_time2) - break; - exposure_time = exposure_time2; - scan_power_mode++; - } - - DBG (DBG_info, "gl841_calculate_current_setup : exposure_time=%d pixels\n", - exposure_time); + scan_step_type = gl841_scan_step_type(dev, yres); + exposure_time = gl841_exposure_time(dev, + slope_dpi, + scan_step_type, + start, + used_pixels, + &scan_power_mode); + DBG (DBG_info, "%s : exposure_time=%d pixels\n", __FUNCTION__, exposure_time); /* scanned area must be enlarged by max color shift needed */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0); @@ -2808,7 +3175,7 @@ dummy \ scanned lines dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; - DBG (DBG_proc, "gl841_calculate_current_setup: completed\n"); + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2835,7 +3202,7 @@ gl841_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set) } static void -gl841_set_lamp_power (Genesys_Device * dev, +gl841_set_lamp_power (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool set) { Genesys_Register_Set * r; @@ -2878,16 +3245,16 @@ gl841_set_lamp_power (Genesys_Device * dev, static SANE_Status gl841_save_power(Genesys_Device * dev, SANE_Bool enable) { uint8_t val; - + DBG(DBG_proc, "gl841_save_power: enable = %d\n", enable); if (enable) { - if (dev->model->gpo_type == GPO_CANONLIDE35) + if (dev->model->gpo_type == GPO_CANONLIDE35) { -/* expect GPIO17 to be enabled, and GPIO9 to be disabled, +/* expect GPIO17 to be enabled, and GPIO9 to be disabled, while GPIO8 is disabled*/ -/* final state: GPIO8 disabled, GPIO9 enabled, GPIO17 disabled, +/* final state: GPIO8 disabled, GPIO9 enabled, GPIO17 disabled, GPIO18 disabled*/ sanei_genesys_read_register(dev, REG6D, &val); @@ -2898,7 +3265,7 @@ gl841_save_power(Genesys_Device * dev, SANE_Bool enable) { /*enable GPIO9*/ sanei_genesys_read_register(dev, REG6C, &val); sanei_genesys_write_register(dev, REG6C, val | 0x01); - + /*disable GPO17*/ sanei_genesys_read_register(dev, REG6B, &val); sanei_genesys_write_register(dev, REG6B, val & ~REG6B_GPO17); @@ -2923,14 +3290,14 @@ gl841_save_power(Genesys_Device * dev, SANE_Bool enable) { gl841_set_fe (dev, AFE_POWER_SAVE); - } - else + } + else { - if (dev->model->gpo_type == GPO_CANONLIDE35) + if (dev->model->gpo_type == GPO_CANONLIDE35) { -/* expect GPIO17 to be enabled, and GPIO9 to be disabled, +/* expect GPIO17 to be enabled, and GPIO9 to be disabled, while GPIO8 is disabled*/ -/* final state: GPIO8 enabled, GPIO9 disabled, GPIO17 enabled, +/* final state: GPIO8 enabled, GPIO9 disabled, GPIO17 enabled, GPIO18 enabled*/ sanei_genesys_read_register(dev, REG6D, &val); @@ -2959,7 +3326,7 @@ gl841_save_power(Genesys_Device * dev, SANE_Bool enable) { dev->calib_reg[reg_0x6b].value |= REG6B_GPO18; } - if (dev->model->gpo_type == GPO_DP665 + if (dev->model->gpo_type == GPO_DP665 || dev->model->gpo_type == GPO_DP685) { sanei_genesys_read_register(dev, REG6B, &val); @@ -3049,7 +3416,7 @@ gl841_set_powersaving (Genesys_Device * dev, local_reg[5].value = exposure_time & 255; /* lowbyte */ status = - gl841_bulk_write_register (dev, local_reg, + gl841_bulk_write_register (dev, local_reg, sizeof (local_reg)/sizeof (local_reg[0])); if (status != SANE_STATUS_GOOD) DBG (DBG_error, @@ -3060,13 +3427,19 @@ gl841_set_powersaving (Genesys_Device * dev, return status; } -static SANE_Status +#ifndef UNIT_TESTING +static +#endif +SANE_Status gl841_start_action (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x01); } -static SANE_Status +#ifndef UNIT_TESTING +static +#endif +SANE_Status gl841_stop_action (Genesys_Device * dev) { Genesys_Register_Set local_reg[GENESYS_GL841_MAX_REGS+1]; @@ -3113,12 +3486,12 @@ gl841_stop_action (Genesys_Device * dev) return status; } - /* looks like writing the right registers to zero is enough to get the chip - out of scan mode into command mode, actually triggering(writing to + /* looks like writing the right registers to zero is enough to get the chip + out of scan mode into command mode, actually triggering(writing to register 0x0f) seems to be unnecessary */ loop = 10; - while (loop > 0) + while (loop > 0) { status = sanei_genesys_read_register(dev, 0x40, &val40); if (DBG_LEVEL >= DBG_io) @@ -3133,7 +3506,7 @@ gl841_stop_action (Genesys_Device * dev) DBGCOMPLETED; return status; } - + /* if scanner is in command mode, we are done */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)) { @@ -3154,7 +3527,7 @@ gl841_get_paper_sensor(Genesys_Device * dev, SANE_Bool * paper_loaded) { SANE_Status status; uint8_t val; - + status = sanei_genesys_read_register(dev, REG6D, &val); if (status != SANE_STATUS_GOOD) { @@ -3186,7 +3559,7 @@ gl841_eject_document (Genesys_Device * dev) DBG (DBG_proc, "gl841_eject_document: finished\n"); return SANE_STATUS_GOOD; } - + memset (local_reg, 0, sizeof (local_reg)); val = 0; @@ -3275,7 +3648,7 @@ gl841_eject_document (Genesys_Device * dev) } feed_mm = SANE_UNFIX(dev->model->eject_feed); - if (dev->document) + if (dev->document) { feed_mm += SANE_UNFIX(dev->model->post_scan); } @@ -3288,13 +3661,13 @@ gl841_eject_document (Genesys_Device * dev) sane_strstatus (status)); return status; } - + /* now feed for extra steps */ loop = 0; while (loop < 300) /* do not wait longer then 30 seconds */ { unsigned int steps; - + status = sanei_genesys_read_feed_steps(dev, &steps); if (status != SANE_STATUS_GOOD) { @@ -3341,9 +3714,9 @@ gl841_load_document (Genesys_Device * dev) DBG (DBG_proc, "gl841_load_document\n"); while (loop > 0) /* do not wait longer then 30 seconds */ { - + RIE(gl841_get_paper_sensor(dev, &paper_loaded)); - + if (paper_loaded) { DBG (DBG_info, @@ -3426,7 +3799,7 @@ gl841_detect_document_end (Genesys_Device * dev) /* the current scancnt is also the final one, so we use it to * compute total bytes to read. We also add the line count to eject document */ total_bytes_to_read=(scancnt+postcnt)*dev->wpl; - + DBG (DBG_io, "%s: old total_bytes_to_read=%u\n",__FUNCTION__,(unsigned int)dev->total_bytes_to_read); DBG (DBG_io, "%s: new total_bytes_to_read=%u\n",__FUNCTION__,(unsigned int)total_bytes_to_read); @@ -3453,9 +3826,17 @@ gl841_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, { SANE_Status status; Genesys_Register_Set local_reg[4]; + uint8_t val; DBG (DBG_proc, "gl841_begin_scan\n"); + if (dev->model->gpo_type == GPO_CANONLIDE80) + { + RIE (sanei_genesys_read_register (dev, REG6B, &val)); + val = REG6B_GPO18; + RIE (sanei_genesys_write_register (dev, REG6B, val)); + } + local_reg[0].address = 0x03; if (dev->model->ccd_type != CCD_PLUSTEK_3600) { @@ -3479,7 +3860,7 @@ gl841_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, local_reg[3].value = 0x00; /* do not start motor yet */ status = - gl841_bulk_write_register (dev, local_reg, + gl841_bulk_write_register (dev, local_reg, sizeof (local_reg)/sizeof (local_reg[0])); if (status != SANE_STATUS_GOOD) { @@ -3522,7 +3903,7 @@ gl841_end_scan (Genesys_Device * dev, Genesys_Register_Set __sane_unused__ * reg return status; } } - + DBG (DBG_proc, "gl841_end_scan: completed\n"); return status; @@ -3530,7 +3911,7 @@ gl841_end_scan (Genesys_Device * dev, Genesys_Register_Set __sane_unused__ * reg /* Moves the slider to steps */ #ifndef UNIT_TESTING -static +static #endif SANE_Status gl841_feed (Genesys_Device * dev, int steps) @@ -3540,15 +3921,12 @@ gl841_feed (Genesys_Device * dev, int steps) uint8_t val; int loop; - DBG (DBG_proc, "gl841_feed (steps = %d)\n", - steps); + DBG (DBG_proc, "gl841_feed (steps = %d)\n", steps); - status = - gl841_stop_action (dev); + status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "gl841_feed: failed to stop action: %s\n", + DBG (DBG_error, "gl841_feed: failed to stop action: %s\n", sane_strstatus (status)); return status; } @@ -3557,12 +3935,9 @@ gl841_feed (Genesys_Device * dev, int steps) gl841_init_optical_regs_off(local_reg); - gl841_init_motor_regs(dev,local_reg, - steps,MOTOR_ACTION_FEED,0); + gl841_init_motor_regs(dev,local_reg, steps,MOTOR_ACTION_FEED,0); - status = - gl841_bulk_write_register (dev, local_reg, - GENESYS_GL841_MAX_REGS); + status = gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, @@ -3579,8 +3954,7 @@ gl841_feed (Genesys_Device * dev, int steps) sane_strstatus (status)); gl841_stop_action (dev); /* send original registers */ - gl841_bulk_write_register (dev, dev->reg, - GENESYS_GL841_MAX_REGS); + gl841_bulk_write_register (dev, dev->reg, GENESYS_GL841_MAX_REGS); return status; } @@ -3595,7 +3969,7 @@ gl841_feed (Genesys_Device * dev, int steps) sane_strstatus (status)); return status; } - + if (!(val & REG41_MOTORENB)) /* motor enabled */ { DBG (DBG_proc, "gl841_feed: finished\n"); @@ -3636,14 +4010,20 @@ gl841_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) DBG (DBG_proc, "gl841_slow_back_home: finished\n"); return SANE_STATUS_GOOD; } - - /* reset gpio pin */ + + /* reset gpio pin */ if (dev->model->gpo_type == GPO_CANONLIDE35) { RIE (sanei_genesys_read_register (dev, REG6C, &val)); val = dev->gpo.value[0]; RIE (sanei_genesys_write_register (dev, REG6C, val)); } + if (dev->model->gpo_type == GPO_CANONLIDE80) + { + RIE (sanei_genesys_read_register (dev, REG6B, &val)); + val = REG6B_GPO18 | REG6B_GPO17; + RIE (sanei_genesys_write_register (dev, REG6B, val)); + } gl841_save_power(dev, SANE_FALSE); /* first read gives HOME_SENSOR true */ @@ -3706,7 +4086,7 @@ gl841_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS+1) * sizeof (Genesys_Register_Set)); gl841_init_motor_regs(dev,local_reg, 65536,MOTOR_ACTION_GO_HOME,0); - + /* set up for reverse and no scan */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; @@ -3800,7 +4180,7 @@ gl841_search_start_position (Genesys_Device * dev) SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE); if(status!=SANE_STATUS_GOOD) { - DBG (DBG_error, "%s: failed to init scan registers: %s\n", __FUNCTION__, + DBG (DBG_error, "%s: failed to init scan registers: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -3810,7 +4190,7 @@ gl841_search_start_position (Genesys_Device * dev) gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__, + DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -3868,7 +4248,7 @@ gl841_search_start_position (Genesys_Device * dev) /* update regs to copy ASIC internal state */ memcpy (dev->reg, local_reg, (GENESYS_GL841_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); -/*TODO: find out where sanei_genesys_search_reference_point +/*TODO: find out where sanei_genesys_search_reference_point stores information, and use that correctly*/ status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, @@ -3886,7 +4266,7 @@ gl841_search_start_position (Genesys_Device * dev) return SANE_STATUS_GOOD; } -/* +/* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status @@ -3896,8 +4276,7 @@ gl841_init_regs_for_coarse_calibration (Genesys_Device * dev) uint8_t channels; uint8_t cksel; - DBG (DBG_proc, "gl841_init_regs_for_coarse_calibration\n"); - + DBGSTART; cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */ @@ -3913,7 +4292,7 @@ gl841_init_regs_for_coarse_calibration (Genesys_Device * dev) dev->settings.yres, 0, 0, - dev->sensor.optical_res / cksel, + dev->sensor.optical_res / cksel, /* XXX STEF XXX !!! */ 20, 16, channels, @@ -3945,13 +4324,11 @@ gl841_init_regs_for_coarse_calibration (Genesys_Device * dev) return status; } - DBG (DBG_proc, - "gl841_init_register_for_coarse_calibration: completed\n"); /* if (DBG_LEVEL >= DBG_info) sanei_gl841_print_registers (dev->calib_reg);*/ - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -3962,14 +4339,25 @@ gl841_init_regs_for_shading (Genesys_Device * dev) { SANE_Status status; SANE_Int ydpi; + float starty=0; - DBG (DBG_proc, "gl841_init_regs_for_shading: lines = %d\n", (int)dev->calib_lines); + DBGSTART; + DBG (DBG_proc, "%s: lines = %d\n", __FUNCTION__, (int)(dev->calib_lines)); + + /* initial calibration reg values */ + memcpy (dev->calib_reg, dev->reg, GENESYS_GL841_MAX_REGS * sizeof (Genesys_Register_Set)); ydpi = dev->motor.base_ydpi; - if (dev->motor.motor_id == MOTOR_PLUSTEK_3600) /* TODO PLUSTEK_3600: 1200dpi not yet working, produces dark bar */ + if (dev->model->motor_type == MOTOR_PLUSTEK_3600) /* TODO PLUSTEK_3600: 1200dpi not yet working, produces dark bar */ { ydpi = 600; } + if (dev->model->motor_type == MOTOR_CANONLIDE80) + { + ydpi = gl841_get_dpihw(dev); + /* get over extra dark area for this model */ + starty = 140; + } dev->calib_channels = 3; dev->calib_lines = dev->model->shading_lines; @@ -3978,7 +4366,7 @@ gl841_init_regs_for_shading (Genesys_Device * dev) dev->settings.xres, ydpi, 0, - 0, + starty, (dev->sensor.sensor_pixels * dev->settings.xres) / dev->sensor.optical_res, dev->calib_lines, 16, @@ -3986,36 +4374,27 @@ gl841_init_regs_for_shading (Genesys_Device * dev) dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | -/* we don't handle differing shading areas very well */ -/* SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |*/ - SCAN_FLAG_IGNORE_LINE_DISTANCE | - SCAN_FLAG_USE_OPTICAL_RES - ); - - dev->calib_pixels = dev->current_setup.pixels; - + SCAN_FLAG_USE_OPTICAL_RES | + /*SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |*/ + SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "gl841_init_registers_for_shading: failed to setup scan: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } - dev->scanhead_position_in_steps += dev->calib_lines; + dev->calib_pixels = dev->current_setup.pixels; + dev->scanhead_position_in_steps += dev->calib_lines + starty; - status = - gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS); + status = gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "gl841_init_registers_for_shading: failed to bulk write registers: %s\n", + DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } - DBG (DBG_proc, "gl841_init_regs_for_shading: completed\n"); - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -4063,9 +4442,9 @@ gl841_init_regs_for_scan (Genesys_Device * dev) assumption: steps are expressed at maximum motor resolution - we need: - SANE_Fixed y_offset; - SANE_Fixed y_size; + we need: + SANE_Fixed y_offset; + SANE_Fixed y_size; SANE_Fixed y_offset_calib; mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */ @@ -4076,7 +4455,9 @@ gl841_init_regs_for_scan (Genesys_Device * dev) move = 0; if (dev->model->flags & GENESYS_FLAG_SEARCH_START) - move += SANE_UNFIX (dev->model->y_offset_calib); + { + move += SANE_UNFIX (dev->model->y_offset_calib); + } DBG (DBG_info, "gl841_init_regs_for_scan: move=%f steps\n", move); @@ -4097,18 +4478,20 @@ gl841_init_regs_for_scan (Genesys_Device * dev) flags=0; - /* we enable true gray for cis scanners only, and just when doing + /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ flags = 0; - + + /* true gray (led add for cis scanners) */ if(dev->model->is_cis && dev->settings.true_gray - &&dev->model->ccd_type != CCD_CANONLIDE35) + && dev->settings.scan_mode != SCAN_MODE_COLOR) { - flags |= OPTICAL_FLAG_ENABLE_LEDADD; + flags |= SCAN_FLAG_ENABLE_LEDADD; } + /* enable emulated lineart from gray data */ - if(dev->settings.scan_mode == SCAN_MODE_LINEART + if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; @@ -4126,7 +4509,7 @@ gl841_init_regs_for_scan (Genesys_Device * dev) channels, dev->settings.color_filter, flags); - + if (status != SANE_STATUS_GOOD) return status; @@ -4192,7 +4575,7 @@ gl841_send_gamma_table (Genesys_Device * dev) -needs working coarse/gain */ -static SANE_Status +GENESYS_STATIC SANE_Status gl841_led_calibration (Genesys_Device * dev) { int num_pixels; @@ -4205,8 +4588,9 @@ gl841_led_calibration (Genesys_Device * dev) int avg[3], avga, avge; int turn; char fn[20]; - uint16_t expr, expg, expb; + uint16_t exp[3], target; Genesys_Register_Set *r; + int move; SANE_Bool acceptable = SANE_FALSE; @@ -4214,21 +4598,22 @@ gl841_led_calibration (Genesys_Device * dev) uint16_t min_exposure=500; uint16_t max_exposure; - DBG (DBG_proc, "gl841_led_calibration\n"); - + DBGSTART; - if (dev->model->gpo_type == GPO_CANONLIDE35) + /* feed to white strip if needed */ + if (dev->model->y_offset_calib>0) { - status = gl841_feed(dev, 280);/*feed to white strip. canon lide 35 only.*/ - + move = SANE_UNFIX (dev->model->y_offset_calib); + move = (move * (dev->motor.base_ydpi)) / MM_PER_INCH; + DBG (DBG_io, "%s: move=%d lines\n", __FUNCTION__, move); + status = gl841_feed(dev, move); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "gl841_led_calibration: failed to feed: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed to feed: %s\n", __FUNCTION__, + sane_strstatus (status)); return status; } - } + } /* offset calibration is always done in color mode */ channels = 3; @@ -4254,7 +4639,7 @@ gl841_led_calibration (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl841_led_calibration: failed to setup scan: %s\n", + "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -4269,7 +4654,7 @@ gl841_led_calibration (Genesys_Device * dev) if (!line) return SANE_STATUS_NO_MEM; -/* +/* we try to get equal bright leds here: loop: @@ -4277,23 +4662,24 @@ gl841_led_calibration (Genesys_Device * dev) adjust exposure times */ - expr = (dev->sensor.regs_0x10_0x1d[0] << 8) | dev->sensor.regs_0x10_0x1d[1]; - expg = (dev->sensor.regs_0x10_0x1d[2] << 8) | dev->sensor.regs_0x10_0x1d[3]; - expb = (dev->sensor.regs_0x10_0x1d[4] << 8) | dev->sensor.regs_0x10_0x1d[5]; + exp[0] = (dev->sensor.regs_0x10_0x1d[0] << 8) | dev->sensor.regs_0x10_0x1d[1]; + exp[1] = (dev->sensor.regs_0x10_0x1d[2] << 8) | dev->sensor.regs_0x10_0x1d[3]; + exp[2] = (dev->sensor.regs_0x10_0x1d[4] << 8) | dev->sensor.regs_0x10_0x1d[5]; turn = 0; /* max exposure is set to ~2 time initial average * exposure, or 2 time last calibration exposure */ - max_exposure=((expr+expg+expb)/3)*2; + max_exposure=((exp[0]+exp[1]+exp[2])/3)*2; + target=dev->sensor.gain_white_ref*256; do { - dev->sensor.regs_0x10_0x1d[0] = (expr >> 8) & 0xff; - dev->sensor.regs_0x10_0x1d[1] = expr & 0xff; - dev->sensor.regs_0x10_0x1d[2] = (expg >> 8) & 0xff; - dev->sensor.regs_0x10_0x1d[3] = expg & 0xff; - dev->sensor.regs_0x10_0x1d[4] = (expb >> 8) & 0xff; - dev->sensor.regs_0x10_0x1d[5] = expb & 0xff; + dev->sensor.regs_0x10_0x1d[0] = (exp[0] >> 8) & 0xff; + dev->sensor.regs_0x10_0x1d[1] = exp[0] & 0xff; + dev->sensor.regs_0x10_0x1d[2] = (exp[1] >> 8) & 0xff; + dev->sensor.regs_0x10_0x1d[3] = exp[1] & 0xff; + dev->sensor.regs_0x10_0x1d[4] = (exp[2] >> 8) & 0xff; + dev->sensor.regs_0x10_0x1d[5] = exp[2] & 0xff; r = &(dev->calib_reg[reg_0x10]); for (i = 0; i < 6; i++, r++) { @@ -4301,14 +4687,12 @@ gl841_led_calibration (Genesys_Device * dev) RIE (sanei_genesys_write_register (dev, 0x10+i, dev->sensor.regs_0x10_0x1d[i])); } - RIE (gl841_bulk_write_register - (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); + RIE (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); - DBG (DBG_info, - "gl841_led_calibration: starting first line reading\n"); + DBG (DBG_info, "%s: starting line reading\n", __FUNCTION__); RIE (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE)); RIE (sanei_genesys_read_data_from_scanner (dev, line, total_size)); - + if (DBG_LEVEL >= DBG_data) { snprintf(fn,20,"led_%d.pnm",turn); sanei_genesys_write_pnm_file (fn, @@ -4317,15 +4701,14 @@ gl841_led_calibration (Genesys_Device * dev) channels, num_pixels, 1); } - - acceptable = SANE_TRUE; - + + /* compute average */ for (j = 0; j < channels; j++) { avg[j] = 0; for (i = 0; i < num_pixels; i++) { - if (dev->model->is_cis) + if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; @@ -4339,82 +4722,212 @@ gl841_led_calibration (Genesys_Device * dev) avg[j] /= num_pixels; } - DBG(DBG_info,"gl841_led_calibration: average: " - "%d,%d,%d\n", - avg[0],avg[1],avg[2]); + DBG(DBG_info,"%s: average: %d,%d,%d\n", __FUNCTION__, avg[0], avg[1], avg[2]); acceptable = SANE_TRUE; - + + /* exposure is acceptable if each color is in the %5 range + * of other color channels */ if (avg[0] < avg[1] * 0.95 || avg[1] < avg[0] * 0.95 || avg[0] < avg[2] * 0.95 || avg[2] < avg[0] * 0.95 || avg[1] < avg[2] * 0.95 || avg[2] < avg[1] * 0.95) + { + acceptable = SANE_FALSE; + } + + /* led exposure is not acceptable if white level is too low + * ~80 hardcoded value for white level */ + if(avg[0]<20000 || avg[1]<20000 || avg[2]<20000) + { acceptable = SANE_FALSE; + } - if (!acceptable) { - avga = (avg[0]+avg[1]+avg[2])/3; - expr = (expr * avga) / avg[0]; - expg = (expg * avga) / avg[1]; - expb = (expb * avga) / avg[2]; -/* - keep the resulting exposures below this value. - too long exposure drives the ccd into saturation. - we may fix this by relying on the fact that - we get a striped scan without shading, by means of - statistical calculation -*/ - avge = (expr + expg + expb) / 3; + /* for scanners using target value */ + if(target>0) + { + acceptable = SANE_TRUE; + for(i=0;i<3;i++) + { + /* we accept +- 2% delta from target */ + if(abs(avg[i]-target)>target/50) + { + exp[i]=(exp[i]*target)/avg[i]; + acceptable = SANE_FALSE; + } + } + } + else + { + if (!acceptable) + { + avga = (avg[0]+avg[1]+avg[2])/3; + exp[0] = (exp[0] * avga) / avg[0]; + exp[1] = (exp[1] * avga) / avg[1]; + exp[2] = (exp[2] * avga) / avg[2]; + /* + keep the resulting exposures below this value. + too long exposure drives the ccd into saturation. + we may fix this by relying on the fact that + we get a striped scan without shading, by means of + statistical calculation + */ + avge = (exp[0] + exp[1] + exp[2]) / 3; + + if (avge > max_exposure) { + exp[0] = (exp[0] * max_exposure) / avge; + exp[1] = (exp[1] * max_exposure) / avge; + exp[2] = (exp[2] * max_exposure) / avge; + } + if (avge < min_exposure) { + exp[0] = (exp[0] * min_exposure) / avge; + exp[1] = (exp[1] * min_exposure) / avge; + exp[2] = (exp[2] * min_exposure) / avge; + } - if (avge > max_exposure) { - expr = (expr * max_exposure) / avge; - expg = (expg * max_exposure) / avge; - expb = (expb * max_exposure) / avge; - } - if (avge < min_exposure) { - expr = (expr * min_exposure) / avge; - expg = (expg * min_exposure) / avge; - expb = (expb * min_exposure) / avge; - } - - } + } + } RIE (gl841_stop_action (dev)); turn++; } while (!acceptable && turn < 100); - - DBG(DBG_info,"gl841_led_calibration: acceptable exposure: %d,%d,%d\n", - expr,expg,expb); + + DBG(DBG_info,"%s: acceptable exposure: %d,%d,%d\n", __FUNCTION__, exp[0],exp[1],exp[2]); /* cleanup before return */ free (line); gl841_slow_back_home(dev, SANE_TRUE); - DBG (DBG_proc, "gl841_led_calibration: completed\n"); + DBGCOMPLETED; return status; } /** @brief calibration for AD frontend devices - * experiments show that modifying offset is of little (if no) influence - * so we just return - * CHRIS: This was added from gl646.c as again offset seems to make no - * difference - * - * TODO PLUSTEK_3600 Michael Rickmann: - * offset calibration makes a lot of a difference but currently - * makes everything to dark + * offset calibration assumes that the scanning head is on a black area + * For LiDE80 analog frontend + * 0x0003 : is gain and belongs to [0..63] + * 0x0006 : is offset + * We scan a line with no gain until average offset reaches the target */ static SANE_Status ad_fe_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; + int num_pixels; + int total_size; + uint8_t *line; + int i; + int average; + int turn; + char fn[20]; + int top; + int bottom; + int target; + + DBGSTART; + + /* don't impact 3600 behavior since we can't test it */ + if (dev->model->ccd_type == CCD_PLUSTEK_3600) + { + DBGCOMPLETED; + return status; + } + + status = gl841_init_scan_regs (dev, + dev->calib_reg, + dev->settings.xres, + dev->settings.yres, + 0, + 0, + (dev->sensor.sensor_pixels*dev->settings.xres) / dev->sensor.optical_res, + 1, + 8, + 3, + dev->settings.color_filter, + SCAN_FLAG_DISABLE_SHADING | + SCAN_FLAG_DISABLE_GAMMA | + SCAN_FLAG_SINGLE_LINE | + SCAN_FLAG_IGNORE_LINE_DISTANCE | + SCAN_FLAG_USE_OPTICAL_RES); + + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl841_offset_calibration: failed to setup scan: %s\n", + sane_strstatus (status)); + return status; + } + + num_pixels = dev->current_setup.pixels; + total_size = num_pixels * 3 * 2 * 1; + + line = malloc (total_size); + if (line==NULL) + { + DBGCOMPLETED; + return SANE_STATUS_NO_MEM; + } + + dev->frontend.gain[0] = 0x00; + dev->frontend.gain[1] = 0x00; + dev->frontend.gain[2] = 0x00; - DBG (DBG_proc, "ad_fe_offset_calibration: start\n"); - DBG (DBG_info, "ad_fe_offset_calibration: offset=(%d,%d,%d)\n", - dev->frontend.offset[0], dev->frontend.offset[1], - dev->frontend.offset[2]); - DBG (DBG_proc, "ad_fe_offset_calibration: end\n"); + /* loop on scan until target offset is reached */ + turn=0; + target=24; + bottom=0; + top=255; + do { + /* set up offset mid range */ + dev->frontend.offset[0] = (top+bottom)/2; + dev->frontend.offset[1] = (top+bottom)/2; + dev->frontend.offset[2] = (top+bottom)/2; + + /* scan line */ + DBG (DBG_info, "%s: starting line reading\n",__FUNCTION__); + gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS); + gl841_set_fe(dev, AFE_SET); + gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE); + sanei_genesys_read_data_from_scanner (dev, line, total_size); + gl841_stop_action (dev); + if (DBG_LEVEL >= DBG_data) { + snprintf(fn,20,"offset_%02d.pnm",turn); + sanei_genesys_write_pnm_file (fn, line, 8, 3, num_pixels, 1); + } + + /* search for minimal value */ + average=0; + for(i=0;itarget) + { + top=(top+bottom)/2; + } + else + { + bottom=(top+bottom)/2; + } + turn++; + } while ((top-bottom)>1 && turn < 100); + + dev->frontend.offset[0]=0; + dev->frontend.offset[1]=0; + dev->frontend.offset[2]=0; + free(line); + DBG (DBG_info, "%s: offset=(%d,%d,%d)\n", __FUNCTION__, + dev->frontend.offset[0], + dev->frontend.offset[1], + dev->frontend.offset[2]); + DBGCOMPLETED; return status; } @@ -4425,7 +4938,7 @@ ad_fe_offset_calibration (Genesys_Device * dev) this function expects the slider to be where? */ -static SANE_Status +GENESYS_STATIC SANE_Status gl841_offset_calibration (Genesys_Device * dev) { int num_pixels; @@ -4443,14 +4956,14 @@ gl841_offset_calibration (Genesys_Device * dev) SANE_Bool acceptable = SANE_FALSE; int mintgt = 0x400; + DBG (DBG_proc, "gl841_offset_calibration\n"); + /* Analog Device fronted have a different calibration */ - if (dev->model->dac_type == DAC_PLUSTEK_3600) + if ((dev->reg[reg_0x04].value & REG04_FESET) == 0x02) { return ad_fe_offset_calibration (dev); } - DBG (DBG_proc, "gl841_offset_calibration\n"); - /* offset calibration is always done in color mode */ channels = 3; @@ -4501,15 +5014,15 @@ gl841_offset_calibration (Genesys_Device * dev) /*okay. the sensor black level is now at -260mV. we only get 0 from AFE...*/ /* we should probably do real calibration here: * -detect acceptable offset with binary search - * -calculate offset from this last version + * -calculate offset from this last version * - * acceptable offset means + * acceptable offset means * - few completely black pixels(<10%?) * - few completely white pixels(<10%?) * - * final offset should map the minimum not completely black + * final offset should map the minimum not completely black * pixel to 0(16 bits) - * + * * this does account for dummy pixels at the end of ccd * this assumes slider is at black strip(which is not quite as black as "no * signal"). @@ -4534,8 +5047,8 @@ gl841_offset_calibration (Genesys_Device * dev) for (j=0; j < channels; j++) { off[j] = (offh[j]+offl[j])/2; dev->frontend.offset[j] = off[j]; - } - + } + status = gl841_set_fe(dev, AFE_SET); if (status != SANE_STATUS_GOOD) @@ -4551,7 +5064,7 @@ gl841_offset_calibration (Genesys_Device * dev) RIEF2 (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line); - + if (DBG_LEVEL >= DBG_data) { snprintf(fn,20,"offset1_%02d.pnm",turn); sanei_genesys_write_pnm_file (fn, @@ -4560,9 +5073,9 @@ gl841_offset_calibration (Genesys_Device * dev) channels, num_pixels, 1); } - + acceptable = SANE_TRUE; - + for (j = 0; j < channels; j++) { cmin[j] = 0; @@ -4570,7 +5083,7 @@ gl841_offset_calibration (Genesys_Device * dev) for (i = 0; i < num_pixels; i++) { - if (dev->model->is_cis) + if (dev->model->is_cis) val = first_line[i * 2 + j * 2 * num_pixels + 1] * 256 + first_line[i * 2 + j * 2 * num_pixels]; @@ -4595,7 +5108,7 @@ gl841_offset_calibration (Genesys_Device * dev) offl[0] = off[0]; else offl[j] = off[j]; - } + } if (cmax[j] > num_pixels/100) { acceptable = SANE_FALSE; if (dev->model->is_cis) @@ -4618,7 +5131,7 @@ gl841_offset_calibration (Genesys_Device * dev) turn++; } while (!acceptable && turn < 100); - + DBG(DBG_info,"gl841_offset_calibration: acceptable offsets: %d,%d,%d\n", off[0],off[1],off[2]); @@ -4626,12 +5139,12 @@ gl841_offset_calibration (Genesys_Device * dev) for (j = 0; j < channels; j++) { off1[j] = off[j]; - + min1[j] = 65536; - - for (i = 0; i < num_pixels; i++) + + for (i = 0; i < num_pixels; i++) { - if (dev->model->is_cis) + if (dev->model->is_cis) val = first_line[i * 2 + j * 2 * num_pixels + 1] * 256 + first_line[i * 2 + j * 2 * num_pixels]; @@ -4643,20 +5156,20 @@ gl841_offset_calibration (Genesys_Device * dev) min1[j] = val; } } - + offl[0] = off[0]; offl[1] = off[0]; offl[2] = off[0]; turn = 0; - + do { - + for (j=0; j < channels; j++) { off[j] = (offh[j]+offl[j])/2; dev->frontend.offset[j] = off[j]; - } - + } + status = gl841_set_fe(dev, AFE_SET); if (status != SANE_STATUS_GOOD) @@ -4668,25 +5181,25 @@ gl841_offset_calibration (Genesys_Device * dev) sane_strstatus (status)); return status; } - + DBG (DBG_info, "gl841_offset_calibration: starting second line reading\n"); RIEF2 (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS), first_line, second_line); RIEF2 (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); - + if (DBG_LEVEL >= DBG_data) { - snprintf(fn,20,"offset2_%d.pnm",turn); + snprintf(fn,20,"offset2_%02d.pnm",turn); sanei_genesys_write_pnm_file (fn, second_line, 16, channels, num_pixels, 1); } - + acceptable = SANE_TRUE; - + for (j = 0; j < channels; j++) { cmin[j] = 0; @@ -4694,7 +5207,7 @@ gl841_offset_calibration (Genesys_Device * dev) for (i = 0; i < num_pixels; i++) { - if (dev->model->is_cis) + if (dev->model->is_cis) val = second_line[i * 2 + j * 2 * num_pixels + 1] * 256 + second_line[i * 2 + j * 2 * num_pixels]; @@ -4714,7 +5227,7 @@ gl841_offset_calibration (Genesys_Device * dev) offl[0] = off[0]; else offl[j] = off[j]; - } + } if (cmax[j] > num_pixels/100) { acceptable = SANE_FALSE; if (dev->model->is_cis) @@ -4738,7 +5251,7 @@ gl841_offset_calibration (Genesys_Device * dev) turn++; } while (!acceptable && turn < 100); - + DBG(DBG_info,"gl841_offset_calibration: acceptable offsets: %d,%d,%d\n", off[0],off[1],off[2]); @@ -4746,12 +5259,12 @@ gl841_offset_calibration (Genesys_Device * dev) for (j = 0; j < channels; j++) { off2[j] = off[j]; - + min2[j] = 65536; - for (i = 0; i < num_pixels; i++) + for (i = 0; i < num_pixels; i++) { - if (dev->model->is_cis) + if (dev->model->is_cis) val = second_line[i * 2 + j * 2 * num_pixels + 1] * 256 + second_line[i * 2 + j * 2 * num_pixels]; @@ -4770,11 +5283,11 @@ gl841_offset_calibration (Genesys_Device * dev) DBG(DBG_info,"gl841_offset_calibration: second set: %d/%d,%d/%d,%d/%d\n", off2[0],min2[0],off2[1],min2[1],off2[2],min2[2]); -/* +/* calculate offset for each channel based on minimal pixel value min1 at offset off1 and minimal pixel value min2 at offset off2 - + to get min at off, values are linearly interpolated: min=real+off*fact min1=real+off1*fact @@ -4833,16 +5346,16 @@ gl841_offset_calibration (Genesys_Device * dev) } -/* alternative coarse gain calibration +/* alternative coarse gain calibration this on uses the settings from offset_calibration and uses only one scanline */ /* with offset and coarse calibration we only want to get our input range into - a reasonable shape. the fine calibration of the upper and lower bounds will + a reasonable shape. the fine calibration of the upper and lower bounds will be done with shading. */ -static SANE_Status +GENESYS_STATIC SANE_Status gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) { int num_pixels; @@ -4853,18 +5366,22 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) int max[3]; float gain[3]; int val; + int lines=1; + int move; - DBG (DBG_proc, "gl841_coarse_gain_calibration dpi=%d\n", dpi); + DBG (DBG_proc, "%s: dpi=%d\n", __FUNCTION__, dpi); - if (dev->model->gpo_type == GPO_CANONLIDE35) + /* feed to white strip if needed */ + if (dev->model->y_offset_calib>0) { - status = gl841_feed(dev, 280);/*feed to white strip. canon lide 35 only.*/ - + move = SANE_UNFIX (dev->model->y_offset_calib); + move = (move * (dev->motor.base_ydpi)) / MM_PER_INCH; + DBG (DBG_io, "%s: move=%d lines\n", __FUNCTION__, move); + status = gl841_feed(dev, move); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "gl841_coarse_gain_calibration: failed to feed: %s\n", - sane_strstatus (status)); + DBG (DBG_error, "%s: failed to feed: %s\n", __FUNCTION__, + sane_strstatus (status)); return status; } } @@ -4879,7 +5396,7 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) 0, 0, (dev->sensor.sensor_pixels*dev->settings.xres) / dev->sensor.optical_res, - 1, + lines, 16, channels, dev->settings.color_filter, @@ -4892,18 +5409,16 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "gl841_coarse_calibration: failed to setup scan: %s\n", + DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } - RIE (gl841_bulk_write_register - (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); + RIE (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); num_pixels = dev->current_setup.pixels; - total_size = num_pixels * channels * 2 * 1; /* colors * bytes_per_color * scan lines */ + total_size = num_pixels * channels * 2 * lines; /* colors * bytes_per_color * scan lines */ line = malloc (total_size); if (!line) @@ -4913,18 +5428,17 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); if (DBG_LEVEL >= DBG_data) - sanei_genesys_write_pnm_file ("coarse.pnm", line, 16, - channels, num_pixels, 1); + sanei_genesys_write_pnm_file ("coarse.pnm", line, 16, channels, num_pixels, lines); /* average high level for each channel and compute gain - to reach the target code + to reach the target code we only use the central half of the CCD data */ for (j = 0; j < channels; j++) { max[j] = 0; for (i = 0; i < num_pixels; i++) { - if (dev->model->is_cis) + if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; @@ -4941,24 +5455,28 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) if (dev->model->dac_type == DAC_CANONLIDE35 || dev->model->dac_type == DAC_WOLFSON_XP300 || - dev->model->dac_type == DAC_WOLFSON_DSM600) { + dev->model->dac_type == DAC_WOLFSON_DSM600) + { gain[j] *= 0.69;/*seems we don't get the real maximum. empirically derived*/ - if (283 - 208/gain[j] > 255) + if (283 - 208/gain[j] > 255) dev->frontend.gain[j] = 255; else if (283 - 208/gain[j] < 0) dev->frontend.gain[j] = 0; else dev->frontend.gain[j] = 283 - 208/gain[j]; - } + } + else if (dev->model->dac_type == DAC_CANONLIDE80) + { + dev->frontend.gain[j] = gain[j]*12; + } - DBG (DBG_proc, - "gl841_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n", + DBG (DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __FUNCTION__, j, max[j], gain[j],dev->frontend.gain[j]); } for (j = 0; j < channels; j++) { - if(gain[j] > 10) + if(gain[j] > 10) { DBG (DBG_error0, "**********************************************\n"); DBG (DBG_error0, "**********************************************\n"); @@ -4975,7 +5493,7 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) return SANE_STATUS_JAMMED; #endif } - + } if (dev->model->is_cis) { @@ -4986,19 +5504,23 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0]; } - if (channels == 1) + if (channels == 1) { dev->frontend.gain[0] = dev->frontend.gain[1]; dev->frontend.gain[2] = dev->frontend.gain[1]; } - + free (line); + DBG (DBG_info, "%s: gain=(%d,%d,%d)\n", __FUNCTION__, + dev->frontend.gain[0], + dev->frontend.gain[1], + dev->frontend.gain[2]); RIE (gl841_stop_action (dev)); gl841_slow_back_home(dev, SANE_TRUE); - DBG (DBG_proc, "gl841_coarse_gain_calibration: completed\n"); + DBGCOMPLETED; return status; } @@ -5069,7 +5591,7 @@ gl841_init_regs_for_warmup (Genesys_Device * dev, * as a by-product, also check for lock */ #ifndef UNIT_TESTING -static +static #endif SANE_Status sanei_gl841_repark_head (Genesys_Device * dev) @@ -5077,7 +5599,7 @@ sanei_gl841_repark_head (Genesys_Device * dev) SANE_Status status; DBG (DBG_proc, "sanei_gl841_repark_head\n"); - + status = gl841_feed(dev,232); if (status != SANE_STATUS_GOOD) @@ -5095,7 +5617,7 @@ sanei_gl841_repark_head (Genesys_Device * dev) } static SANE_Status -gl841_is_compatible_calibration (Genesys_Device * dev, +gl841_is_compatible_calibration (Genesys_Device * dev, Genesys_Calibration_Cache *cache, int for_overwrite) { @@ -5146,7 +5668,7 @@ gl841_is_compatible_calibration (Genesys_Device * dev, return SANE_STATUS_GOOD; } -/* +/* * initialize ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home */ @@ -5181,16 +5703,15 @@ gl841_init (Genesys_Device * dev) dev->settings.color_filter = 0; - /* Set default values for registers */ - gl841_init_registers (dev); - /* ASIC reset */ RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); + /* Set default values for registers */ + gl841_init_registers (dev); + /* Write initial registers */ - RIE (gl841_bulk_write_register - (dev, dev->reg, GENESYS_GL841_MAX_REGS)); + RIE (gl841_bulk_write_register (dev, dev->reg, GENESYS_GL841_MAX_REGS)); /* Test ASIC and RAM */ if (!(dev->model->flags & GENESYS_FLAG_LAZY_INIT)) @@ -5246,7 +5767,7 @@ gl841_init (Genesys_Device * dev) dev->sensor.gamma[i]); } } - + /* send gamma tables */ status = gl841_send_gamma_table (dev); if (status != SANE_STATUS_GOOD) @@ -5320,8 +5841,9 @@ gl841_update_hardware_sensors (Genesys_Scanner * s) */ SANE_Status status = SANE_STATUS_GOOD; uint8_t val; - - if (s->dev->model->gpo_type == GPO_CANONLIDE35) + + if (s->dev->model->gpo_type == GPO_CANONLIDE35 + || s->dev->model->gpo_type == GPO_CANONLIDE80) { RIE(sanei_genesys_read_register(s->dev, REG6D, &val)); @@ -5352,7 +5874,7 @@ gl841_update_hardware_sensors (Genesys_Scanner * s) /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. - * When searching backward, the searched area must completely be of the desired + * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward @@ -5665,6 +6187,127 @@ gl841_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black) return status; } +/** + * Send shading calibration data. The buffer is considered to always hold values + * for all the channels. + */ +GENESYS_STATIC +SANE_Status +gl841_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) +{ + SANE_Status status = SANE_STATUS_GOOD; + uint32_t length, x, factor, pixels, i; + uint32_t half; + uint32_t lines, channels; + uint16_t dpiset, dpihw, strpixel ,endpixel, beginpixel; + uint8_t *buffer,*ptr,*src; + + DBGSTART; + DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__FUNCTION__,size); + + /* old method if no SHDAREA */ + if((dev->reg[reg_0x01].value & REG01_SHDAREA) == 0) + { + /* start address */ + status = sanei_genesys_set_buffer_address (dev, 0x0000); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: failed to set buffer address: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + + /* shading data whole line */ + status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "%s: failed to send shading table: %s\n", __FUNCTION__, + sane_strstatus (status)); + return status; + } + DBGCOMPLETED; + return status; + } + + /* data is whole line, we extract only the part for the scanned area */ + length = (uint32_t) (size / 3); + sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&strpixel); + sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&endpixel); + DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d\n",__FUNCTION__,strpixel,endpixel,endpixel-strpixel); + + /* compute deletion/average factor */ + sanei_genesys_get_double(dev->reg,REG_DPISET,&dpiset); + dpihw = gl841_get_dpihw(dev); + half=dev->current_setup.half_ccd+1; + factor=dpihw/dpiset; + DBG( DBG_io2, "%s: dpihw=%d, dpiset=%d, half_ccd=%d, factor=%d\n",__FUNCTION__,dpihw,dpiset,half-1,factor); + + /* binary data logging */ + if(DBG_LEVEL>=DBG_data) + { + dev->binary=fopen("binary.pnm","wb"); + sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines); + channels=dev->current_setup.channels; + if(dev->binary!=NULL) + { + fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255); + } + } + + /* turn pixel value into bytes 2x16 bits words */ + strpixel*=2*2; /* 2 words of 2 bytes */ + endpixel*=2*2; + pixels=endpixel-strpixel; + + /* shading pixel begin is start pixel minus start pixel during shading + * calibration. Currently only cases handled are full and half ccd resolution. + */ + beginpixel = dev->sensor.CCD_start_xoffset / half; + beginpixel += dev->sensor.dummy_pixel + 1; + DBG(DBG_io2, "%s: ORIGIN PIXEL=%d\n", __FUNCTION__, beginpixel); + beginpixel = (strpixel-beginpixel*2*2)/factor; + DBG(DBG_io2, "%s: BEGIN PIXEL=%d\n",__FUNCTION__,beginpixel/4); + + DBG(DBG_io2, "%s: using chunks of %d bytes (%d shading data pixels)\n",__FUNCTION__,length, length/4); + buffer=(uint8_t *)malloc(pixels); + memset(buffer,0,pixels); + + /* write actual shading data contigously + * channel by channel, starting at addr 0x0000 + * */ + for(i=0;i<3;i++) + { + /* copy data to work buffer and process it */ + /* coefficent destination */ + ptr=buffer; + + /* iterate on both sensor segment, data has been averaged, + * so is in the right order and we only have to copy it */ + for(x=0;xmodel->cmd_set->bulk_write_data (dev, 0x3c, buffer, pixels), buffer); + } + + free(buffer); + DBGCOMPLETED; + + return status; +} + + /** the gl841 command set */ static Genesys_Command_Set gl841_cmd_set = { "gl841-generic", /* the name of this set */ @@ -5718,8 +6361,9 @@ static Genesys_Command_Set gl841_cmd_set = { gl841_is_compatible_calibration, NULL, - NULL, + gl841_send_shading_data, gl841_calculate_current_setup, + NULL, NULL }; diff --git a/backend/genesys_gl841.h b/backend/genesys_gl841.h index bbf2ee1..bbb79f1 100644 --- a/backend/genesys_gl841.h +++ b/backend/genesys_gl841.h @@ -3,42 +3,42 @@ Copyright (C) 2011-2013 Stéphane Voltz This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #include "genesys.h" @@ -157,11 +157,25 @@ #define REG1DS_TGSHLD 0 +#define REG1E 0x1e #define REG1E_WDTIME 0xf0 #define REG1ES_WDTIME 4 #define REG1E_LINESEL 0x0f #define REG1ES_LINESEL 0 +#define REG_EXPR 0x10 +#define REG_EXPG 0x12 +#define REG_EXPB 0x14 +#define REG_STEPNO 0x21 +#define REG_FWDSTEP 0x22 +#define REG_BWDSTEP 0x23 +#define REG_FASTNO 0x24 +#define REG_LINCNT 0x25 +#define REG_DPISET 0x2c +#define REG_STRPIXEL 0x30 +#define REG_ENDPIXEL 0x32 +#define REG_LPERIOD 0x38 + #define REG40_HISPDFLG 0x04 #define REG40_MOTMFLG 0x02 #define REG40_DATAENB 0x01 @@ -231,8 +245,8 @@ #define REG6C_GPIOL 0xff #define REG6D 0x6d - #define REG6E 0x6e +#define REG6F 0x6f #define REG87_LEDADD 0x04 @@ -348,8 +362,13 @@ enum reg_0x85, reg_0x86, reg_0x87, + reg_0x88, + reg_0x89, GENESYS_GL841_MAX_REGS }; + +#define INITREG(adr,val) {dev->reg[index].address=adr;dev->reg[index].value=val;index++;} + /** * prototypes declaration in case of unit testing */ @@ -387,4 +406,51 @@ sanei_gl841_repark_head (Genesys_Device * dev); SANE_Status gl841_feed (Genesys_Device * dev, int steps); +SANE_Status +gl841_init_motor_regs_scan(Genesys_Device * dev, + Genesys_Register_Set * reg, + unsigned int scan_exposure_time, + float scan_yres, + int scan_step_type, + unsigned int scan_lines, + unsigned int scan_dummy, + unsigned int feed_steps, + int scan_power_mode, + unsigned int flags) ; + +SANE_Status +gl841_stop_action (Genesys_Device * dev); + +SANE_Status +gl841_start_action (Genesys_Device * dev); + +SANE_Status +gl841_init_motor_regs(Genesys_Device * dev, + Genesys_Register_Set * reg, + unsigned int feed_steps, + unsigned int action, + unsigned int flags); + +SANE_Status gl841_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps); + +SANE_Status gl841_bulk_write_data_gamma (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len); + +SANE_Status gl841_offset_calibration (Genesys_Device * dev); + +SANE_Status gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi); + +SANE_Status gl841_led_calibration (Genesys_Device * dev); + +SANE_Status gl841_send_shading_data (Genesys_Device * dev, uint8_t * data, int size); + +int gl841_scan_step_type(Genesys_Device *dev, int yres); +SANE_Status gl841_write_freq(Genesys_Device *dev, unsigned int ydpi); #endif + +GENESYS_STATIC +int gl841_exposure_time(Genesys_Device *dev, + float slope_dpi, + int scan_step_type, + int start, + int used_pixels, + int *scan_power_mode); diff --git a/backend/genesys_gl843.c b/backend/genesys_gl843.c index 3648d09..2b0d8fa 100644 --- a/backend/genesys_gl843.c +++ b/backend/genesys_gl843.c @@ -1,45 +1,45 @@ /* sane - Scanner Access Now Easy. Copyright (C) 2010-2013 Stéphane Voltz - - + + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME @@ -294,7 +294,7 @@ gl843_bulk_read_data (Genesys_Device * dev, uint8_t addr, } /**************************************************************************** - Mid level functions + Mid level functions ****************************************************************************/ static SANE_Bool @@ -439,7 +439,7 @@ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi, int flags) } else { - if(sp[i].dpi>=dpi + if(sp[i].dpi>=dpi && sp[i].dpivalue = sensor->regs_0x52_0x5e[i]; } - + /* specific registers */ r = sanei_genesys_get_address (regs, 0x0c); if (r) @@ -664,7 +664,7 @@ gl843_init_registers (Genesys_Device * dev) SETREG (0x94, 0xff); SETREG (0xab, 0x50); } - + /* so many time burnt for this register ....*/ if (strcmp (dev->model->name, "canon-canoscan-4400f") != 0 &&strcmp (dev->model->name, "canon-canoscan-8400f") != 0) @@ -683,7 +683,7 @@ gl843_init_registers (Genesys_Device * dev) SETREG (0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */ SETREG (0x0a, 0x18); SETREG (0x0b, 0x69); - + /* CIS exposure is used for XPA lamp movement */ SETREG (0x10, 0x2c); SETREG (0x11, 0x09); @@ -698,7 +698,7 @@ gl843_init_registers (Genesys_Device * dev) SETREG (0x71, 0x02); SETREG (0x72, 0x00); SETREG (0x73, 0x00); - + SETREG (0x80, 0x50); SETREG (0x9d, 0x08); SETREG (0xab, 0x40); @@ -710,7 +710,7 @@ gl843_init_registers (Genesys_Device * dev) SETREG (0x9b, 0x80); SETREG (0xac, 0x00); } - + if (strcmp (dev->model->name, "canon-canoscan-4400f") == 0) { SETREG (0x06, 0xf0); /* SCANMOD=111, PWRBIT and no GAIN4 */ @@ -732,7 +732,7 @@ gl843_init_registers (Genesys_Device * dev) sanei_genesys_set_double(dev->reg,REG_EXPG,0x9c40); sanei_genesys_set_double(dev->reg,REG_EXPB,0x9c40); } - + if (strcmp (dev->model->name, "canon-canoscan-8400f") == 0) { SETREG (0x03, 0x1c); @@ -775,7 +775,7 @@ gl843_init_registers (Genesys_Device * dev) DBGCOMPLETED; } -/* Send slope table for motor movement +/* Send slope table for motor movement slope_table in machine byte order */ #ifndef UNIT_TESTING @@ -1032,7 +1032,7 @@ gl843_init_motor_regs_scan (Genesys_Device * dev, feedl<<=scan_step_type; dist = scan_steps; - if (use_fast_fed) + if (use_fast_fed) { dist += fast_steps*2; } @@ -1089,7 +1089,7 @@ gl843_init_motor_regs_scan (Genesys_Device * dev, { r->value = 0x50; coeff=dev->sensor.optical_res/sanei_genesys_compute_dpihw(dev, scan_yres); - if (dev->model->motor_type == MOTOR_KVSS080) + if (dev->model->motor_type == MOTOR_KVSS080) { if(coeff>=1) { @@ -1130,7 +1130,7 @@ static int gl843_compute_exposure(Genesys_Device *dev, int xres, int flags) /** @brief setup optical related registers * start and pixels are expressed in optical sensor resolution coordinate - * space. + * space. * @param dev device to use * @param reg registers to set up * @param exposure exposure time to use @@ -1190,7 +1190,7 @@ gl843_init_optical_regs_scan (Genesys_Device * dev, /* sensor parameters */ gl843_setup_sensor (dev, reg, dpihw, flags); - /* resolution is divided according to CKSEL which is known once sensor is set up */ + /* resolution is divided according to CKSEL which is known once sensor is set up */ r = sanei_genesys_get_address (reg, REG18); cksel= (r->value & REG18_CKSEL)+1; DBG (DBG_io2, "%s: cksel=%d\n", __FUNCTION__, cksel); @@ -1208,8 +1208,8 @@ gl843_init_optical_regs_scan (Genesys_Device * dev, used_pixels=endx-startx; /* in case of stagger we have to start at an odd coordinate */ - if ((flags & OPTICAL_FLAG_STAGGER) - &&((startx & 1)==0)) + if ((flags & OPTICAL_FLAG_STAGGER) + &&((startx & 1)==0)) { startx++; endx++; @@ -1218,7 +1218,7 @@ gl843_init_optical_regs_scan (Genesys_Device * dev, status = gl843_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, "%s: failed to set frontend: %s\n", __FUNCTION__, + DBG (DBG_error, "%s: failed to set frontend: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -1450,7 +1450,7 @@ gl843_init_scan_regs (Genesys_Device * dev, /* stagger starting at 2400, and not applied for calibration */ stagger = 0; - if ( (yres>1200) + if ( (yres>1200) && ((flags & SCAN_FLAG_IGNORE_LINE_DISTANCE)==0) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) { @@ -1458,7 +1458,7 @@ gl843_init_scan_regs (Genesys_Device * dev, } DBG (DBG_info, "%s : stagger=%d lines\n", __FUNCTION__, stagger); - /* we enable true gray for cis scanners only, and just when doing + /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ oflags = 0; @@ -1495,7 +1495,7 @@ gl843_init_scan_regs (Genesys_Device * dev, /* use detected left margin and fixed value */ /* start */ start = startx; - + /* compute correct pixels number */ used_pixels = (pixels * optical_res) / xres; DBG (DBG_info, "%s: used_pixels=%d\n", __FUNCTION__, used_pixels); @@ -1566,7 +1566,7 @@ gl843_init_scan_regs (Genesys_Device * dev, /*** motor parameters ***/ /* it seems base_dpi of the G4050 motor is changed above 600 dpi*/ - if (dev->model->motor_type == MOTOR_G4050 && yres>600) + if (dev->model->motor_type == MOTOR_G4050 && yres>600) { dev->ld_shift_r = (dev->model->ld_shift_r*3800)/dev->motor.base_ydpi; dev->ld_shift_g = (dev->model->ld_shift_g*3800)/dev->motor.base_ydpi; @@ -1797,7 +1797,7 @@ gl843_calculate_current_setup (Genesys_Device * dev) DBG (DBG_info, "%s : exposure=%d pixels\n", __FUNCTION__, exposure); /* it seems base_dpi of the G4050 motor is changed above 600 dpi*/ - if (dev->model->motor_type == MOTOR_G4050 && yres>600) + if (dev->model->motor_type == MOTOR_G4050 && yres>600) { dev->ld_shift_r = (dev->model->ld_shift_r*3800)/dev->motor.base_ydpi; dev->ld_shift_g = (dev->model->ld_shift_g*3800)/dev->motor.base_ydpi; @@ -1901,7 +1901,7 @@ gl843_save_power (Genesys_Device * dev, SANE_Bool enable) return SANE_STATUS_INVAL; /* switch KV-SS080 lamp off */ - if (dev->model->gpo_type == GPO_KVSS080) + if (dev->model->gpo_type == GPO_KVSS080) { RIE(sanei_genesys_read_register (dev, REG6C, &val)); if(enable) @@ -1978,7 +1978,7 @@ gl843_stop_action (Genesys_Device * dev) status = sanei_genesys_write_register (dev, REG01, val); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, "%s: failed to write register 01: %s\n", __FUNCTION__, + DBG (DBG_error, "%s: failed to write register 01: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } @@ -2110,7 +2110,7 @@ gl843_detect_document_end (Genesys_Device * dev) flines); } - /* adjust number of bytes to read + /* adjust number of bytes to read * we need to read the final bytes which are word per line * number of last lines * to have doc leaving feeder */ lines = @@ -2149,7 +2149,7 @@ gl843_detect_document_end (Genesys_Device * dev) if (flines > lines) { /* change the value controlling communication with the frontend : - * total bytes to read is current value plus the number of remaining lines + * total bytes to read is current value plus the number of remaining lines * multiplied by bytes per line */ sublines = flines - lines; @@ -2419,13 +2419,13 @@ gl843_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, if (val & (REG03_XPASEL|REG03_LAMPPWR)) { sanei_genesys_read_register (dev, REGA6, &val); - + /* switch on regular lamp */ val |= 0x40; /* no XPA lamp power (2 bits for level: __11 ____) */ val &= ~0x30; - + RIE (sanei_genesys_write_register (dev, REGA6, val)); } @@ -2459,7 +2459,7 @@ static SANE_Status gl843_park_xpa_lamp (Genesys_Device * dev) Genesys_Register_Set *r; uint8_t val; int loop = 0; - + DBGSTART; /* copy scan settings */ @@ -2470,7 +2470,7 @@ static SANE_Status gl843_park_xpa_lamp (Genesys_Device * dev) /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); - + /* set up for reverse and no scan */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; @@ -2591,7 +2591,7 @@ gl843_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) memcpy (local_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); - gl843_init_scan_regs (dev, + status = gl843_init_scan_regs (dev, local_reg, resolution, resolution, @@ -2607,10 +2607,18 @@ gl843_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl843_slow_back_home: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); - + /* set up for reverse and no scan */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; @@ -2795,7 +2803,7 @@ gl843_search_start_position (Genesys_Device * dev) return SANE_STATUS_GOOD; } -/* +/* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status @@ -2879,7 +2887,7 @@ gl843_feed (Genesys_Device * dev, unsigned int steps) memcpy (local_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); - gl843_init_scan_regs (dev, + status = gl843_init_scan_regs (dev, local_reg, resolution, resolution, @@ -2895,15 +2903,23 @@ gl843_feed (Genesys_Device * dev, unsigned int steps) SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_FEEDING | SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl843_feed: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT)); RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT)); - + /* set up for no scan */ r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; - + /* send registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL843_MAX_REGS)); @@ -2925,7 +2941,7 @@ gl843_feed (Genesys_Device * dev, unsigned int steps) status = sanei_genesys_get_status (dev, &val); } while (status == SANE_STATUS_GOOD && !(val & FEEDFSH)); - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2941,7 +2957,7 @@ gl843_init_regs_for_shading (Genesys_Device * dev) uint16_t strpixel; DBGSTART; - + /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); @@ -3053,7 +3069,7 @@ gl843_init_regs_for_scan (Genesys_Device * dev) flags = 0; /* enable emulated lineart from gray data */ - if(dev->settings.scan_mode == SCAN_MODE_LINEART + if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; @@ -3080,7 +3096,7 @@ gl843_init_regs_for_scan (Genesys_Device * dev) return SANE_STATUS_GOOD; } -/** +/** * This function sends gamma tables to ASIC */ static SANE_Status @@ -3210,7 +3226,7 @@ gl843_led_calibration (Genesys_Device * dev) if (!line) return SANE_STATUS_NO_MEM; -/* +/* we try to get equal bright leds here: loop: @@ -3294,9 +3310,9 @@ gl843_led_calibration (Genesys_Device * dev) /* keep the resulting exposures below this value. too long exposure drives the ccd into saturation. - we may fix this by relying on the fact that + we may fix this by relying on the fact that we get a striped scan without shading, by means of - statistical calculation + statistical calculation */ avge = (expr + expg + expb) / 3; @@ -3561,13 +3577,13 @@ gl843_offset_calibration (Genesys_Device * dev) } -/* alternative coarse gain calibration +/* alternative coarse gain calibration this on uses the settings from offset_calibration and uses only one scanline */ /* with offset and coarse calibration we only want to get our input range into - a reasonable shape. the fine calibration of the upper and lower bounds will + a reasonable shape. the fine calibration of the upper and lower bounds will be done with shading. */ static SANE_Status @@ -3781,7 +3797,7 @@ gl843_init_regs_for_warmup (Genesys_Device * dev, return SANE_STATUS_GOOD; } -/** +/** * set up GPIO/GPOE for idle state WRITE GPIO[17-21]= GPIO19 WRITE GPOE[17-21]= GPOE21 GPOE20 GPOE19 GPOE18 @@ -3842,7 +3858,7 @@ gl843_boot (Genesys_Device * dev, SANE_Bool cold) RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); } - + if(dev->usb_mode == 1) { val = 0x14; @@ -3898,7 +3914,7 @@ gl843_boot (Genesys_Device * dev, SANE_Bool cold) /* setup gpio */ RIE (gl843_init_gpio (dev)); - + gl843_feed (dev, 300); usleep (100000); @@ -3993,7 +4009,7 @@ SANE_Status gl843_move_to_ta (Genesys_Device * dev) /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. - * When searching backward, the searched area must completely be of the desired + * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward @@ -4310,7 +4326,7 @@ gl843_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) uint16_t dpiset, strpixel, endpixel, startx, factor; DBGSTART; - + offset=0; length=size; r = sanei_genesys_get_address (dev->reg, REG01); @@ -4337,7 +4353,7 @@ gl843_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&endpixel); strpixel*=tgtime; endpixel*=tgtime; - + /* 16 bit words, 2 words per color, 3 color channels */ offset=(strpixel-startx)*2*2*3; length=(endpixel-strpixel)*2*2*3; @@ -4378,13 +4394,13 @@ gl843_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) free(final_data); return status; } - + status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, final_data, count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send shading table: %s\n", __FUNCTION__, sane_strstatus (status)); } - + free(final_data); DBGCOMPLETED; return status; @@ -4446,7 +4462,8 @@ static Genesys_Command_Set gl843_cmd_set = { gl843_move_to_ta, gl843_send_shading_data, gl843_calculate_current_setup, - gl843_boot + gl843_boot, + NULL }; SANE_Status diff --git a/backend/genesys_gl843.h b/backend/genesys_gl843.h index 241a2ed..f31f0ee 100644 --- a/backend/genesys_gl843.h +++ b/backend/genesys_gl843.h @@ -3,42 +3,42 @@ Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #include "genesys.h" diff --git a/backend/genesys_gl846.c b/backend/genesys_gl846.c index 5e1f0f4..3991693 100644 --- a/backend/genesys_gl846.c +++ b/backend/genesys_gl846.c @@ -1,45 +1,45 @@ /* sane - Scanner Access Now Easy. Copyright (C) 2012-2013 Stéphane Voltz - - + + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ /** @file @@ -62,7 +62,7 @@ /** @brief read scanned data * Read in 0xeff0 maximum sized blocks. This read is done in 2 - * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the + * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the * remainder. Read addr is always 0x10000000 with the memory layout setup. * @param dev device to read data from * @param addr address within ASIC memory space, unused but kept for API @@ -128,7 +128,7 @@ gl846_bulk_read_data (Genesys_Device * dev, uint8_t addr, read /= 512; read *= 512; } - + DBG (DBG_io2, "gl846_bulk_read_data: trying to read %lu bytes of data\n", (u_long) read); @@ -180,7 +180,7 @@ gl846_bulk_read_data (Genesys_Device * dev, uint8_t addr, } /**************************************************************************** - Mid level functions + Mid level functions ****************************************************************************/ static SANE_Bool @@ -304,7 +304,7 @@ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi) } else { - if(sensors[i].dpi>=dpi + if(sensors[i].dpi>=dpi && sensors[i].dpisettings.yres==4444 && feed_steps>100 + if(dev->settings.yres==4444 && feed_steps>100 && ((flags & MOTOR_FLAG_FEED)==0)) { use_fast_fed=1; @@ -845,7 +845,7 @@ gl846_init_motor_regs_scan (Genesys_Device * dev, /* correct move distance by acceleration and deceleration amounts */ feedl=feed_steps; - if (use_fast_fed) + if (use_fast_fed) { feedl<<=fast_step_type; dist=(scan_steps+2*fast_steps)*factor; @@ -887,7 +887,7 @@ gl846_init_motor_regs_scan (Genesys_Device * dev, */ /* if quarter step, bipolar Vref2 */ - /* XXX STEF XXX GPIO + /* XXX STEF XXX GPIO if (scan_step_type > 1) { if (scan_step_type < 3) @@ -1021,11 +1021,11 @@ gl846_init_optical_regs_scan (Genesys_Device * dev, "half_ccd=%d, flags=%x\n", exposure_time, used_res, start, pixels, channels, depth, half_ccd, flags); - /* resolution is divided according to CKSEL */ + /* resolution is divided according to CKSEL */ r = sanei_genesys_get_address (reg, REG18); cksel= (r->value & REG18_CKSEL)+1; DBG (DBG_io2, "%s: cksel=%d\n", __FUNCTION__, cksel); - + /* to manage high resolution device while keeping good * low resolution scanning speed, we make hardware dpi vary */ dpihw=sanei_genesys_compute_dpihw(dev, used_res * cksel); @@ -1040,7 +1040,7 @@ gl846_init_optical_regs_scan (Genesys_Device * dev, /* start and end coordinate in optical dpi coordinates */ startx = start/cksel+dev->sensor.CCD_start_xoffset; used_pixels=pixels/cksel; - + /* end of sensor window */ endx = startx + used_pixels; @@ -1184,7 +1184,7 @@ gl846_init_optical_regs_scan (Genesys_Device * dev, { r->value |= REG87_LEDADD; } - /* RGB weighting + /* RGB weighting r = sanei_genesys_get_address (reg, 0x01); r->value &= ~REG01_TRUEGRAY; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) @@ -1229,7 +1229,7 @@ gl846_init_optical_regs_scan (Genesys_Device * dev, DBG (DBG_io2, "%s: dev->len =%lu\n", __FUNCTION__, (unsigned long)dev->len); DBG (DBG_io2, "%s: dev->dist =%lu\n", __FUNCTION__, (unsigned long)dev->dist); DBG (DBG_io2, "%s: dev->segnb =%lu\n", __FUNCTION__, (unsigned long)dev->segnb); - + words_per_line *= channels; dev->wpl = words_per_line; @@ -1248,7 +1248,7 @@ gl846_init_optical_regs_scan (Genesys_Device * dev, r = sanei_genesys_get_address (reg, 0x34); r->value = dev->sensor.dummy_pixel; - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -1383,7 +1383,7 @@ gl846_init_scan_regs (Genesys_Device * dev, depth = 8; } - /* we enable true gray for cis scanners only, and just when doing + /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ oflags = 0; @@ -1393,7 +1393,7 @@ gl846_init_scan_regs (Genesys_Device * dev, oflags |= OPTICAL_FLAG_DISABLE_GAMMA; if(flags & SCAN_FLAG_DISABLE_LAMP) oflags |= OPTICAL_FLAG_DISABLE_LAMP; - + if (dev->model->is_cis && dev->settings.true_gray) { oflags |= OPTICAL_FLAG_ENABLE_LEDADD; @@ -1504,12 +1504,12 @@ gl846_init_scan_regs (Genesys_Device * dev, /* theory : target_size = (dev->settings.pixels * dev->settings.lines * channels * depth) / 8; - but it suffers from integer overflow so we do the following: + but it suffers from integer overflow so we do the following: - 1 bit color images store color data byte-wise, eg byte 0 contains - 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains + 1 bit color images store color data byte-wise, eg byte 0 contains + 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 8 bits of blue. - This does not fix the overflow, though. + This does not fix the overflow, though. 644mp*16 = 10gp, leading to an overflow -- pierre */ @@ -1969,13 +1969,13 @@ gl846_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) } memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); - + resolution=sanei_genesys_get_lowest_ydpi(dev); - + /* TODO add scan_mode to the API */ scan_mode= dev->settings.scan_mode; dev->settings.scan_mode=SCAN_MODE_LINEART; - gl846_init_scan_regs (dev, + status = gl846_init_scan_regs (dev, local_reg, resolution, resolution, @@ -1989,11 +1989,19 @@ gl846_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl846_slow_back_home: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } dev->settings.scan_mode=scan_mode; /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); - + /* set up for reverse */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; @@ -2153,7 +2161,7 @@ gl846_search_start_position (Genesys_Device * dev) memcpy (dev->reg, local_reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); -/*TODO: find out where sanei_genesys_search_reference_point +/*TODO: find out where sanei_genesys_search_reference_point stores information, and use that correctly*/ status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, @@ -2171,7 +2179,7 @@ gl846_search_start_position (Genesys_Device * dev) return SANE_STATUS_GOOD; } -/* +/* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status @@ -2255,7 +2263,7 @@ gl846_feed (Genesys_Device * dev, unsigned int steps) memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); - gl846_init_scan_regs (dev, + status = gl846_init_scan_regs (dev, local_reg, resolution, resolution, @@ -2270,6 +2278,14 @@ gl846_feed (Genesys_Device * dev, unsigned int steps) SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_FEEDING | SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl846_feed: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } /* set exposure to zero */ sanei_genesys_set_triple(local_reg,REG_EXPR,0); @@ -2279,11 +2295,11 @@ gl846_feed (Genesys_Device * dev, unsigned int steps) /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT)); RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT)); - + /* set up for no scan */ r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; - + /* send registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS)); @@ -2308,7 +2324,7 @@ gl846_feed (Genesys_Device * dev, unsigned int steps) /* then stop scanning */ RIE(gl846_stop_action (dev)); - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2335,7 +2351,7 @@ gl846_init_regs_for_shading (Genesys_Device * dev) DBG (DBG_io, "%s: calib_lines = %d\n", __FUNCTION__, (unsigned int)dev->calib_lines); DBG (DBG_io, "%s: calib_pixels = %d\n", __FUNCTION__, (unsigned int)dev->calib_pixels); - /* this is aworkaround insufficent distance for slope + /* this is aworkaround insufficent distance for slope * motor acceleration TODO special motor slope for shading */ move=1; if(dev->calib_resolution<1200) @@ -2364,7 +2380,7 @@ gl846_init_regs_for_shading (Genesys_Device * dev) DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } - + status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS); if (status != SANE_STATUS_GOOD) { @@ -2421,9 +2437,9 @@ gl846_init_regs_for_scan (Genesys_Device * dev) assumption: steps are expressed at maximum motor resolution - we need: - SANE_Fixed y_offset; - SANE_Fixed y_size; + we need: + SANE_Fixed y_offset; + SANE_Fixed y_size; SANE_Fixed y_offset_calib; mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */ @@ -2453,7 +2469,7 @@ gl846_init_regs_for_scan (Genesys_Device * dev) } move=500; } - + DBG (DBG_info, "gl846_init_regs_for_scan: move=%f steps\n", move); DBG (DBG_info, "%s: move=%f steps\n", __FUNCTION__, move); @@ -2465,7 +2481,7 @@ gl846_init_regs_for_scan (Genesys_Device * dev) flags = 0; /* emulated lineart from gray data is required for now */ - if(dev->settings.scan_mode == SCAN_MODE_LINEART + if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; @@ -2489,7 +2505,7 @@ gl846_init_regs_for_scan (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) return status; - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2512,7 +2528,7 @@ gl846_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) DBGSTART; DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__FUNCTION__,size); - /* shading data is plit in 3 (up to 5 with IR) areas + /* shading data is plit in 3 (up to 5 with IR) areas write(0x10014000,0x00000dd8) URB 23429 bulk_out len 3544 wrote 0x33 0x10 0x.... write(0x1003e000,0x00000dd8) @@ -2542,14 +2558,14 @@ gl846_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255); } } - + pixels=endpixel-strpixel; /* since we're using SHDAREA, substract startx coordinate from shading */ strpixel-=((dev->sensor.CCD_start_xoffset*600)/dev->sensor.optical_res); - + /* turn pixel value into bytes 2x16 bits words */ - strpixel*=2*2; + strpixel*=2*2; pixels*=2*2; /* allocate temporary buffer */ @@ -2578,18 +2594,19 @@ gl846_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) ptr[1]=src[1]; ptr[2]=src[2]; ptr[3]=src[3]; - + /* next shading coefficient */ ptr+=4; } - RIE (sanei_genesys_read_register (dev, 0xd0+i, &val)); + RIEF (sanei_genesys_read_register (dev, 0xd0+i, &val), buffer); addr = val * 8192 + 0x10000000; status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, addr, pixels, buffer); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_send_shading_data; write to AHB failed (%s)\n", sane_strstatus (status)); + free(buffer); return status; } } @@ -2640,7 +2657,7 @@ gl846_led_calibration (Genesys_Device * dev) used_res=sanei_genesys_compute_dpihw(dev,dev->settings.xres); sensor=get_sensor_profile(dev->model->ccd_type, used_res); num_pixels = (dev->sensor.sensor_pixels*used_res)/dev->sensor.optical_res; - + /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); @@ -2770,18 +2787,18 @@ gl846_led_calibration (Genesys_Device * dev) /* cleanup before return */ free (line); - + /* go back home */ if(move>20) { status=gl846_slow_back_home (dev, SANE_TRUE); } - + DBGCOMPLETED; return status; } -/** +/** * set up GPIO/GPOE for idle state */ static SANE_Status @@ -2805,7 +2822,7 @@ gl846_init_gpio (Genesys_Device * dev) RIE (sanei_genesys_write_register (dev, REGA7, gpios[idx].ra7)); RIE (sanei_genesys_write_register (dev, REGA6, gpios[idx].ra6)); - + RIE (sanei_genesys_write_register (dev, REG6B, gpios[idx].r6b)); RIE (sanei_genesys_write_register (dev, REG6C, gpios[idx].r6c)); RIE (sanei_genesys_write_register (dev, REG6D, gpios[idx].r6d)); @@ -2819,7 +2836,7 @@ gl846_init_gpio (Genesys_Device * dev) return status; } -/** +/** * set memory layout by filling values in dedicated registers */ static SANE_Status @@ -2867,7 +2884,7 @@ gl846_init_memory_layout (Genesys_Device * dev) */ #ifndef UNIT_TESTING static -#endif +#endif SANE_Status gl846_boot (Genesys_Device * dev, SANE_Bool cold) { @@ -2882,7 +2899,7 @@ gl846_boot (Genesys_Device * dev, SANE_Bool cold) RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); } - + if(dev->usb_mode == 1) { val = 0x14; @@ -2950,7 +2967,7 @@ SANE_Status gl846_init (Genesys_Device * dev) DBG_INIT (); DBGSTART; - + status=sanei_genesys_asic_init(dev, GENESYS_GL846_MAX_REGS); DBGCOMPLETED; @@ -2990,7 +3007,7 @@ gl846_update_hardware_sensors (Genesys_Scanner * s) /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. - * When searching backward, the searched area must completely be of the desired + * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward @@ -3013,7 +3030,15 @@ gl846_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black) DBG (DBG_proc, "gl846_search_strip %s %s\n", black ? "black" : "white", forward ? "forward" : "reverse"); - gl846_set_fe (dev, AFE_SET); + status = gl846_set_fe (dev, AFE_SET); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl846_search_strip: gl846_set_fe() failed: %s\n", + sane_strstatus(status)); + return status; + } + status = gl846_stop_action (dev); if (status != SANE_STATUS_GOOD) { @@ -3415,7 +3440,7 @@ gl846_offset_calibration (Genesys_Device * dev) snprintf(title,20,"offset%03d.pnm",bottom); sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines); } - + bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl846_offset_calibration: bottom avg=%d\n", bottomavg); @@ -3429,7 +3454,7 @@ gl846_offset_calibration (Genesys_Device * dev) DBG (DBG_info, "gl846_offset_calibration: starting second line reading\n"); RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); - + topavg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl846_offset_calibration: top avg=%d\n", topavg); @@ -3572,24 +3597,10 @@ gl846_coarse_gain_calibration (Genesys_Device * dev, int dpi) max[j] = 0; for (i = pixels/4; i < (pixels*3/4); i++) { - if(bpp==16) - { - if (dev->model->is_cis) - val = - line[i * 2 + j * 2 * pixels + 1] * 256 + - line[i * 2 + j * 2 * pixels]; - else - val = - line[i * 2 * channels + 2 * j + 1] * 256 + - line[i * 2 * channels + 2 * j]; - } - else - { if (dev->model->is_cis) val = line[i + j * pixels]; else val = line[i * channels + j]; - } max[j] += val; } @@ -3619,12 +3630,6 @@ gl846_coarse_gain_calibration (Genesys_Device * dev, int dpi) dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0]; } - if (channels == 1) - { - dev->frontend.gain[0] = dev->frontend.gain[1]; - dev->frontend.gain[2] = dev->frontend.gain[1]; - } - free (line); RIE (gl846_stop_action (dev)); @@ -3691,7 +3696,8 @@ static Genesys_Command_Set gl846_cmd_set = { NULL, gl846_send_shading_data, gl846_calculate_current_setup, - gl846_boot + gl846_boot, + NULL }; SANE_Status diff --git a/backend/genesys_gl846.h b/backend/genesys_gl846.h index 58e9702..d57f149 100644 --- a/backend/genesys_gl846.h +++ b/backend/genesys_gl846.h @@ -3,42 +3,42 @@ Copyright (C) 2012-2013 Stéphane Voltz This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #include "genesys.h" @@ -566,7 +566,7 @@ gl846_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); #ifndef UNIT_TESTING static -#endif +#endif SANE_Status gl846_boot (Genesys_Device * dev, SANE_Bool cold); @@ -696,7 +696,7 @@ static Motor_Profile gl846_motors[]={ /* Image Formula 101 */ {MOTOR_IMG101, 11000, HALF_STEP , img101_high}, {MOTOR_PLUSTEK3800, 11000, HALF_STEP , img101_high}, - + /* end of database entry */ {0, 0, 0, NULL}, }; diff --git a/backend/genesys_gl847.c b/backend/genesys_gl847.c index 7c6a3c3..7c4d19c 100644 --- a/backend/genesys_gl847.c +++ b/backend/genesys_gl847.c @@ -1,45 +1,45 @@ /* sane - Scanner Access Now Easy. Copyright (C) 2010-2013 Stéphane Voltz - - + + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME @@ -58,7 +58,7 @@ /** @brief read scanned data * Read in 0xeff0 maximum sized blocks. This read is done in 2 - * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the + * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the * remainder. Read addr is always 0x10000000 with the memory layout setup. * @param dev device to read data from * @param addr address within ASIC memory space, unused but kept for API @@ -124,7 +124,7 @@ gl847_bulk_read_data (Genesys_Device * dev, uint8_t addr, read /= 512; read *= 512; } - + DBG (DBG_io2, "gl847_bulk_read_data: trying to read %lu bytes of data\n", (u_long) read); @@ -176,7 +176,7 @@ gl847_bulk_read_data (Genesys_Device * dev, uint8_t addr, } /**************************************************************************** - Mid level functions + Mid level functions ****************************************************************************/ static SANE_Bool @@ -300,7 +300,7 @@ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi) } else { - if(sensors[i].dpi>=dpi + if(sensors[i].dpi>=dpi && sensors[i].dpisettings.yres==4444 && feed_steps>100 + if(dev->settings.yres==4444 && feed_steps>100 && ((flags & MOTOR_FLAG_FEED)==0)) { use_fast_fed=1; @@ -888,7 +888,7 @@ gl847_init_motor_regs_scan (Genesys_Device * dev, /* correct move distance by acceleration and deceleration amounts */ feedl=feed_steps; - if (use_fast_fed) + if (use_fast_fed) { feedl<<=fast_step_type; dist=(scan_steps+2*fast_steps)*factor; @@ -1045,11 +1045,11 @@ gl847_init_optical_regs_scan (Genesys_Device * dev, "half_ccd=%d, flags=%x\n", exposure_time, used_res, start, pixels, channels, depth, half_ccd, flags); - /* resolution is divided according to CKSEL */ + /* resolution is divided according to CKSEL */ r = sanei_genesys_get_address (reg, REG18); cksel= (r->value & REG18_CKSEL)+1; DBG (DBG_io2, "%s: cksel=%d\n", __FUNCTION__, cksel); - + /* to manage high resolution device while keeping good * low resolution scanning speed, we make hardware dpi vary */ dpihw=sanei_genesys_compute_dpihw(dev, used_res * cksel); @@ -1064,7 +1064,7 @@ gl847_init_optical_regs_scan (Genesys_Device * dev, /* start and end coordinate in optical dpi coordinates */ startx = start/cksel+dev->sensor.CCD_start_xoffset; used_pixels=pixels/cksel; - + /* end of sensor window */ endx = startx + used_pixels; @@ -1208,7 +1208,7 @@ gl847_init_optical_regs_scan (Genesys_Device * dev, { r->value |= REG87_LEDADD; } - /* RGB weighting + /* RGB weighting r = sanei_genesys_get_address (reg, 0x01); r->value &= ~REG01_TRUEGRAY; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) @@ -1253,7 +1253,7 @@ gl847_init_optical_regs_scan (Genesys_Device * dev, DBG (DBG_io2, "%s: dev->len =%lu\n", __FUNCTION__, (unsigned long)dev->len); DBG (DBG_io2, "%s: dev->dist =%lu\n", __FUNCTION__, (unsigned long)dev->dist); DBG (DBG_io2, "%s: dev->segnb =%lu\n", __FUNCTION__, (unsigned long)dev->segnb); - + words_per_line *= channels; dev->wpl = words_per_line; @@ -1272,7 +1272,7 @@ gl847_init_optical_regs_scan (Genesys_Device * dev, r = sanei_genesys_get_address (reg, 0x34); r->value = dev->sensor.dummy_pixel; - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -1407,7 +1407,7 @@ gl847_init_scan_regs (Genesys_Device * dev, depth = 8; } - /* we enable true gray for cis scanners only, and just when doing + /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ oflags = 0; @@ -1417,7 +1417,7 @@ gl847_init_scan_regs (Genesys_Device * dev, oflags |= OPTICAL_FLAG_DISABLE_GAMMA; if(flags & SCAN_FLAG_DISABLE_LAMP) oflags |= OPTICAL_FLAG_DISABLE_LAMP; - + if (dev->model->is_cis && dev->settings.true_gray) { oflags |= OPTICAL_FLAG_ENABLE_LEDADD; @@ -1528,12 +1528,12 @@ gl847_init_scan_regs (Genesys_Device * dev, /* theory : target_size = (dev->settings.pixels * dev->settings.lines * channels * depth) / 8; - but it suffers from integer overflow so we do the following: + but it suffers from integer overflow so we do the following: - 1 bit color images store color data byte-wise, eg byte 0 contains - 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains + 1 bit color images store color data byte-wise, eg byte 0 contains + 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 8 bits of blue. - This does not fix the overflow, though. + This does not fix the overflow, though. 644mp*16 = 10gp, leading to an overflow -- pierre */ @@ -1989,13 +1989,13 @@ gl847_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) } memcpy (local_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); - + resolution=sanei_genesys_get_lowest_ydpi(dev); - + /* TODO add scan_mode to the API */ scan_mode= dev->settings.scan_mode; dev->settings.scan_mode=SCAN_MODE_LINEART; - gl847_init_scan_regs (dev, + status = gl847_init_scan_regs (dev, local_reg, resolution, resolution, @@ -2009,11 +2009,20 @@ gl847_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl847_slow_back_home: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } + dev->settings.scan_mode=scan_mode; /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); - + /* set up for reverse */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; @@ -2173,7 +2182,7 @@ gl847_search_start_position (Genesys_Device * dev) memcpy (dev->reg, local_reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); -/*TODO: find out where sanei_genesys_search_reference_point +/*TODO: find out where sanei_genesys_search_reference_point stores information, and use that correctly*/ status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, @@ -2191,7 +2200,7 @@ gl847_search_start_position (Genesys_Device * dev) return SANE_STATUS_GOOD; } -/* +/* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status @@ -2276,7 +2285,7 @@ gl847_feed (Genesys_Device * dev, unsigned int steps) memcpy (local_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); - gl847_init_scan_regs (dev, + status = gl847_init_scan_regs (dev, local_reg, resolution, resolution, @@ -2291,6 +2300,14 @@ gl847_feed (Genesys_Device * dev, unsigned int steps) SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_FEEDING | SCAN_FLAG_IGNORE_LINE_DISTANCE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl847_feed: failed to set up registers: %s\n", + sane_strstatus (status)); + DBGCOMPLETED; + return status; + } /* set exposure to zero */ sanei_genesys_set_triple(local_reg,REG_EXPR,0); @@ -2300,11 +2317,11 @@ gl847_feed (Genesys_Device * dev, unsigned int steps) /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT)); RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT)); - + /* set up for no scan */ r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; - + /* send registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS)); @@ -2329,7 +2346,7 @@ gl847_feed (Genesys_Device * dev, unsigned int steps) /* then stop scanning */ RIE(gl847_stop_action (dev)); - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2356,7 +2373,7 @@ gl847_init_regs_for_shading (Genesys_Device * dev) DBG (DBG_io, "%s: calib_lines = %d\n", __FUNCTION__, (int)dev->calib_lines); DBG (DBG_io, "%s: calib_pixels = %d\n", __FUNCTION__, (int)dev->calib_pixels); - /* this is aworkaround insufficent distance for slope + /* this is aworkaround insufficent distance for slope * motor acceleration TODO special motor slope for shading */ move=1; if(dev->calib_resolution<1200) @@ -2385,7 +2402,7 @@ gl847_init_regs_for_shading (Genesys_Device * dev) DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status)); return status; } - + status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS); if (status != SANE_STATUS_GOOD) { @@ -2442,9 +2459,9 @@ gl847_init_regs_for_scan (Genesys_Device * dev) assumption: steps are expressed at maximum motor resolution - we need: - SANE_Fixed y_offset; - SANE_Fixed y_size; + we need: + SANE_Fixed y_offset; + SANE_Fixed y_size; SANE_Fixed y_offset_calib; mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */ @@ -2474,7 +2491,7 @@ gl847_init_regs_for_scan (Genesys_Device * dev) } move=500; } - + DBG (DBG_info, "gl124_init_regs_for_scan: move=%f steps\n", move); DBG (DBG_info, "%s: move=%f steps\n", __FUNCTION__, move); @@ -2486,7 +2503,7 @@ gl847_init_regs_for_scan (Genesys_Device * dev) flags = 0; /* emulated lineart from gray data is required for now */ - if(dev->settings.scan_mode == SCAN_MODE_LINEART + if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; @@ -2510,7 +2527,7 @@ gl847_init_regs_for_scan (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) return status; - + DBGCOMPLETED; return SANE_STATUS_GOOD; } @@ -2533,7 +2550,7 @@ gl847_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) DBGSTART; DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__FUNCTION__,size); - /* shading data is plit in 3 (up to 5 with IR) areas + /* shading data is plit in 3 (up to 5 with IR) areas write(0x10014000,0x00000dd8) URB 23429 bulk_out len 3544 wrote 0x33 0x10 0x.... write(0x1003e000,0x00000dd8) @@ -2563,14 +2580,14 @@ gl847_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255); } } - + pixels=endpixel-strpixel; /* since we're using SHDAREA, substract startx coordinate from shading */ strpixel-=((dev->sensor.CCD_start_xoffset*600)/dev->sensor.optical_res); - + /* turn pixel value into bytes 2x16 bits words */ - strpixel*=2*2; + strpixel*=2*2; pixels*=2*2; /* allocate temporary buffer */ @@ -2599,7 +2616,7 @@ gl847_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) ptr[1]=src[1]; ptr[2]=src[2]; ptr[3]=src[3]; - + /* next shading coefficient */ ptr+=4; } @@ -2661,7 +2678,7 @@ gl847_led_calibration (Genesys_Device * dev) used_res=sanei_genesys_compute_dpihw(dev,dev->settings.xres); sensor=get_sensor_profile(dev->model->ccd_type, used_res); num_pixels = (dev->sensor.sensor_pixels*used_res)/dev->sensor.optical_res; - + /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); @@ -2791,18 +2808,18 @@ gl847_led_calibration (Genesys_Device * dev) /* cleanup before return */ free (line); - + /* go back home */ if(move>20) { status=gl847_slow_back_home (dev, SANE_TRUE); } - + DBGCOMPLETED; return status; } -/** +/** * set up GPIO/GPOE for idle state */ static SANE_Status @@ -2826,10 +2843,10 @@ gl847_init_gpio (Genesys_Device * dev) RIE (sanei_genesys_write_register (dev, REGA7, gpios[idx].ra7)); RIE (sanei_genesys_write_register (dev, REGA6, gpios[idx].ra6)); - + RIE (sanei_genesys_write_register (dev, REG6E, gpios[idx].r6e)); RIE (sanei_genesys_write_register (dev, REG6C, 0x00)); - + RIE (sanei_genesys_write_register (dev, REG6B, gpios[idx].r6b)); RIE (sanei_genesys_write_register (dev, REG6C, gpios[idx].r6c)); RIE (sanei_genesys_write_register (dev, REG6D, gpios[idx].r6d)); @@ -2843,7 +2860,7 @@ gl847_init_gpio (Genesys_Device * dev) return status; } -/** +/** * set memory layout by filling values in dedicated registers */ static SANE_Status @@ -3004,7 +3021,7 @@ SANE_Status gl847_init (Genesys_Device * dev) DBG_INIT (); DBGSTART; - + status=sanei_genesys_asic_init(dev, GENESYS_GL847_MAX_REGS); DBGCOMPLETED; @@ -3050,7 +3067,7 @@ gl847_update_hardware_sensors (Genesys_Scanner * s) /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. - * When searching backward, the searched area must completely be of the desired + * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward @@ -3476,7 +3493,7 @@ gl847_offset_calibration (Genesys_Device * dev) snprintf(title,20,"offset%03d.pnm",bottom); sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines); } - + bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl847_offset_calibration: bottom avg=%d\n", bottomavg); @@ -3490,7 +3507,7 @@ gl847_offset_calibration (Genesys_Device * dev) DBG (DBG_info, "gl847_offset_calibration: starting second line reading\n"); RIEF2 (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE),first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size),first_line, second_line); - + topavg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl847_offset_calibration: top avg=%d\n", topavg); @@ -3752,7 +3769,8 @@ static Genesys_Command_Set gl847_cmd_set = { NULL, gl847_send_shading_data, gl847_calculate_current_setup, - gl847_boot + gl847_boot, + NULL }; SANE_Status diff --git a/backend/genesys_gl847.h b/backend/genesys_gl847.h index d787f43..9901e23 100644 --- a/backend/genesys_gl847.h +++ b/backend/genesys_gl847.h @@ -3,42 +3,42 @@ Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #include "genesys.h" @@ -653,7 +653,7 @@ static uint32_t lide200_high[] = { 31680, 31680, 31680, 31680, 31680, 31680, 316 static uint32_t lide700_medium[] = { 46876,2342,2342,2342,2342,2342,2342,2342,2342,2302,2286,2274,2266,2258,2252,2244,2240,2234,2228,2224,2218,2216,2210,2208,2202,2200,2194,2192,2190,2186,2182,2180,2176,2174,2172,2170,2166,2162,2160,2156,2154,2152,2150,2150,2146,2144,2142,2140,2136,2134,2132,2130,2130,2128,2124,2122,2120,2120,2118,2116,2112,2112,2110,2108,2106,2106,2104,2102,2102,2098,2096,2094,2094,2092,2090,2090,2086,2084,2084,2082,2082,2080,2078,2078,2076,2074,2074,2070,2070,2068,2066,2066,2064,2064,2062,2062,2060,2058,2058,2054,2054,2052,2052,2050,2050,2048,2048,2046,2046,2044,2042,2042,2040,2040,2038,2038,2034,2034,2032,2032,2030,2030,2028,2028,2026,2026,2022,2022}; static uint32_t lide700_high[] = { 46876,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864}; /* 5190 trop - * 5186 pas assez + * 5186 pas assez */ /* static uint32_t lide200_max[] = { 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 2219,2212,2205,2198,2190,2183,2176,2168,2161,2154,2146,2139,2132,2125,2117,2110,2103,2095,2088,2081,2073,2066,2059,2052,2044,2037,2030,2022,2015,2008,2001,1993,1986,1979,1971,1964,1957,1949,1942,1935,1928,1920,1913,1906,1898,1891,1884,1876,1869,1862,1855,1847,1840,1833,1825,1818,1811,1803,1796,1789,1782,1774,1767,1760,1752,1745,1738,1731,1723,1716,1709,1701,1694,1687,1679,1672,1665,1658,1650,1643,1636,1628,1621,1614,1606,1599,1592,1585,1577,1570,1563,1555,1548,1541,1533,1526,1519,1512,1504,1497,1490,1482,1475,1468,1461,1453,1446,1439,1431,1424,1417,1409,1402,1395,1388,1380,1373,1366,1358,1351,1344,1336,1329,1322,1315,1307,1300,1293,1285,1278,1271,1263,1256,1249,1242,1234,1227,1220,1212,1205,1198,1191,1183,1176,1169,1161,1154,1147,1139,1132,1125,1118,1110,1103,1096,1088,1081,1074,1066,1059,1052,1045,1037,1030,1023,1015,1008,1001,993,986,979,972,964,957,950,942,935,928,921,913,906,899,891,884,877,869,862,855,848,840,833,826,818,811,804,796,789,782,775,767,760,753,745,738,731,723,716,709,702,694,687,680,672,665,658,651,643,636,629,621,614,607,599,592,585,578,570,563,556,534,534, 0}; @@ -671,7 +671,7 @@ static Motor_Profile gl847_motors[]={ {MOTOR_CANONLIDE100, 1432, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE100, 2712, QUARTER_STEP, lide200_medium}, {MOTOR_CANONLIDE100, 5280, EIGHTH_STEP , lide200_high}, - + /* LiDE 200 */ {MOTOR_CANONLIDE200, 2848, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE200, 1424, HALF_STEP , lide200_base}, diff --git a/backend/genesys_low.c b/backend/genesys_low.c index 62563ae..63420e4 100644 --- a/backend/genesys_low.c +++ b/backend/genesys_low.c @@ -1,45 +1,45 @@ /* sane - Scanner Access Now Easy. Copyright (C) 2010-2013 Stéphane Voltz - - + + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME #define BACKEND_NAME genesys_low @@ -261,7 +261,7 @@ sanei_genesys_read_hregister (Genesys_Device * dev, uint16_t reg, uint8_t * val) /** * Write to one GL847 ASIC register -URB 10 control 0x40 0x04 0x83 0x00 len 2 wrote 0xa6 0x04 +URB 10 control 0x40 0x04 0x83 0x00 len 2 wrote 0xa6 0x04 */ static SANE_Status sanei_genesys_write_gl847_register (Genesys_Device * dev, uint8_t reg, uint8_t val) @@ -310,8 +310,8 @@ sanei_genesys_write_register (Genesys_Device * dev, uint16_t reg, uint8_t val) /* route to gl847 function if needed */ if(dev->model->asic_type==GENESYS_GL847 - || dev->model->asic_type==GENESYS_GL845 - || dev->model->asic_type==GENESYS_GL846 + || dev->model->asic_type==GENESYS_GL845 + || dev->model->asic_type==GENESYS_GL846 || dev->model->asic_type==GENESYS_GL124) { return sanei_genesys_write_gl847_register(dev, reg, val); @@ -346,7 +346,7 @@ sanei_genesys_write_register (Genesys_Device * dev, uint16_t reg, uint8_t val) return status; } -/** +/** * @brief write command to 0x8c endpoint * Write a value to 0x8c end point (end access), for USB firmware related operations * Known values are 0x0f, 0x11 for USB 2.0 data transfer and 0x0f,0x14 for USB1.1 @@ -475,10 +475,10 @@ SANE_Status sanei_genesys_set_buffer_address (Genesys_Device * dev, uint32_t addr) { SANE_Status status; - + if(dev->model->asic_type==GENESYS_GL847 - || dev->model->asic_type==GENESYS_GL845 - || dev->model->asic_type==GENESYS_GL846 + || dev->model->asic_type==GENESYS_GL845 + || dev->model->asic_type==GENESYS_GL846 || dev->model->asic_type==GENESYS_GL124) { DBG (DBG_warn, @@ -1210,7 +1210,7 @@ SANE_Status sanei_genesys_generate_gamma_buffer(Genesys_Device * dev, max, dev->settings.contrast, dev->settings.brightness); - for (i = 0; i < size-1; i++) + for (i = 0; i < size; i++) { value=dev->sensor.gamma_table[GENESYS_RED][i]; value=lut[value]; @@ -1230,7 +1230,7 @@ SANE_Status sanei_genesys_generate_gamma_buffer(Genesys_Device * dev, } else { - for (i = 0; i < size-1; i++) + for (i = 0; i < size; i++) { value=dev->sensor.gamma_table[GENESYS_RED][i]; gamma[i * 2 + size * 0 + 0] = value & 0xff; @@ -1258,7 +1258,7 @@ SANE_Status sanei_genesys_generate_gamma_buffer(Genesys_Device * dev, /** @brief send gamma table to scanner * This function sends generic gamma table (ie ones built with - * provided gamma) or the user defined one if provided by + * provided gamma) or the user defined one if provided by * fontend. Used by gl846+ ASICs * @param dev device to write to */ @@ -1354,7 +1354,7 @@ sanei_genesys_asic_init (Genesys_Device * dev, int max_regs) } } - /* check if the device has already been initialized and powered up + /* 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 * reads can detect power down/up cycle*/ @@ -1429,7 +1429,7 @@ sanei_genesys_asic_init (Genesys_Device * dev, int max_regs) } /** - * Wait for the scanning head to park + * Wait for the scanning head to park */ SANE_Status sanei_genesys_wait_for_home (Genesys_Device * dev) @@ -1638,8 +1638,8 @@ Motor_Profile *profile; /* required speed */ target=((exposure * dpi) / base_dpi)>>step_type; - DBG (DBG_io2, "%s: target=%d\n", __FUNCTION__, target); - + DBG (DBG_io2, "%s: exposure=%d, dpi=%d, target=%d\n", __FUNCTION__, exposure, dpi, target); + /* fill result with target speed */ for(i=0;itable[0]; /* loop on profile copying and apply step type */ @@ -1662,6 +1662,14 @@ Motor_Profile *profile; current=profile->table[i]>>step_type; } + /* ensure last step is required speed in case profile doesn't contain it */ + if(current!=0 && currenttable[i]==0 && DBG_LEVEL >= DBG_warn && current>target) { @@ -1760,7 +1768,7 @@ sanei_genesys_is_compatible_calibration (Genesys_Device * dev, SANE_Status status; DBGSTART; - + if(dev->model->cmd_set->calculate_current_setup==NULL) { DBG (DBG_proc, @@ -1779,8 +1787,8 @@ sanei_genesys_is_compatible_calibration (Genesys_Device * dev, dev->current_setup.scan_method = dev->settings.scan_method; DBG (DBG_proc, "sanei_genesys_is_compatible_calibration: checking\n"); - - /* a calibration cache is compatible if color mode and x dpi match the user + + /* a calibration cache is compatible if color mode and x dpi match the user * requested scan. In the case of CIS scanners, dpi isn't a criteria */ if (dev->model->is_cis == SANE_FALSE) { diff --git a/backend/genesys_low.h b/backend/genesys_low.h index 1d5ef22..b1f29e1 100644 --- a/backend/genesys_low.h +++ b/backend/genesys_low.h @@ -8,44 +8,44 @@ Copyright (C) 2006 Laurent Charpentier Parts of the structs have been taken from the gt68xx backend by Sergey Vlasov et al. - + This file is part of the SANE package. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. - + The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. - + This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. - + If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. - + If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. + If you do not wish that, delete this exception notice. */ #ifndef GENESYS_LOW_H @@ -67,7 +67,7 @@ #ifdef HAVE_SYS_TYPES_H #include #endif -#ifdef HAVE_MKDIR +#ifdef HAVE_MKDIR #include #include #endif @@ -81,6 +81,12 @@ #include "../include/_stdint.h" +#ifndef UNIT_TESTING +#define GENESYS_STATIC static +#else +#define GENESYS_STATIC +#endif + #define DBG_error0 0 /* errors/warnings printed even with devuglevel 0 */ #define DBG_error 1 /* fatal errors */ #define DBG_init 2 /* initialization and scanning time messages */ @@ -140,11 +146,11 @@ #define GENESYS_FLAG_SKIP_WARMUP (1 << 4) /**< skip genesys_warmup() */ /** @brief offset calibration flag * signals that the scanner does offset calibration. In this case off_calibration() and - * coarse_gain_calibration() functions must be implemented + * coarse_gain_calibration() functions must be implemented */ #define GENESYS_FLAG_OFFSET_CALIBRATION (1 << 5) #define GENESYS_FLAG_SEARCH_START (1 << 6) /**< do start search before scanning */ -#define GENESYS_FLAG_REPARK (1 << 7) /**< repark head (and check for lock) by +#define GENESYS_FLAG_REPARK (1 << 7) /**< repark head (and check for lock) by moving without scanning */ #define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /**< do dark calibration */ #define GENESYS_FLAG_STAGGERED_LINE (1 << 9) /**< pixel columns are shifted vertically for hi-res modes */ @@ -286,8 +292,8 @@ typedef struct SANE_Int maximum_speed; /* maximum speed allowed. Unit: pixeltime/step */ SANE_Int minimum_steps; /* number of steps used for default curve */ float g; /* power for non-linear acceleration curves. */ -/* vs*(1-i^g)+ve*(i^g) where - vs = start speed, ve = end speed, +/* vs*(1-i^g)+ve*(i^g) where + vs = start speed, ve = end speed, i = 0.0 for first entry and i = 1.0 for last entry in default table*/ } Genesys_Motor_Slope; @@ -310,7 +316,6 @@ typedef enum Genesys_Color_Order Genesys_Color_Order; -#define MAX_SCANNERS 50 #define MAX_RESOLUTIONS 13 #define MAX_DPI 4 @@ -346,6 +351,7 @@ Genesys_Color_Order; #define DAC_CS8400F 17 #define DAC_IMG101 18 #define DAC_PLUSTEK3800 19 +#define DAC_CANONLIDE80 20 #define CCD_UMAX 0 #define CCD_ST12 1 /* SONY ILX548: 5340 Pixel ??? */ @@ -375,6 +381,7 @@ Genesys_Color_Order; #define CCD_IMG101 25 #define CCD_PLUSTEK3800 26 #define CIS_CANONLIDE210 27 +#define CIS_CANONLIDE80 28 #define GPO_UMAX 0 #define GPO_ST12 1 @@ -400,6 +407,7 @@ Genesys_Color_Order; #define GPO_CS8400F 21 #define GPO_IMG101 22 #define GPO_PLUSTEK3800 23 +#define GPO_CANONLIDE80 24 #define MOTOR_UMAX 0 #define MOTOR_5345 1 @@ -424,6 +432,7 @@ Genesys_Color_Order; #define MOTOR_IMG101 21 #define MOTOR_PLUSTEK3800 22 #define MOTOR_CANONLIDE210 23 +#define MOTOR_CANONLIDE80 24 /* Forward typedefs */ @@ -474,8 +483,8 @@ typedef struct Genesys_Command_Set SANE_Status (*save_power) (Genesys_Device * dev, SANE_Bool enable); void (*set_motor_power) (Genesys_Register_Set * regs, SANE_Bool set); - void (*set_lamp_power) (Genesys_Device * dev, - Genesys_Register_Set * regs, + void (*set_lamp_power) (Genesys_Device * dev, + Genesys_Register_Set * regs, SANE_Bool set); SANE_Status (*begin_scan) (Genesys_Device * dev, @@ -499,9 +508,9 @@ typedef struct Genesys_Command_Set SANE_Bool wait_until_home); SANE_Status (*bulk_write_register) (Genesys_Device * dev, - Genesys_Register_Set * reg, + Genesys_Register_Set * reg, size_t elems); - SANE_Status (*bulk_write_data) (Genesys_Device * dev, uint8_t addr, + SANE_Status (*bulk_write_data) (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len); SANE_Status (*bulk_read_data) (Genesys_Device * dev, uint8_t addr, @@ -511,7 +520,7 @@ typedef struct Genesys_Command_Set If possible, just get information for given option. The sensor state in Genesys_Scanner.val[] should be merged with the new sensor state, using the information that was last read by the frontend - in Genesys_Scanner.last_val[], in such a way that a button up/down + in Genesys_Scanner.last_val[], in such a way that a button up/down relative to Genesys_Scanner.last_val[] is not lost. */ SANE_Status (*update_hardware_sensors) (struct Genesys_Scanner * s); @@ -532,7 +541,7 @@ typedef struct Genesys_Command_Set */ SANE_Status (*eject_document) (Genesys_Device * dev); /** - * search for an black or white area in forward or reverse + * search for an black or white area in forward or reverse * direction */ SANE_Status (*search_strip) (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black); @@ -562,6 +571,24 @@ typedef struct Genesys_Command_Set */ SANE_Status (*asic_boot) (Genesys_Device * dev, SANE_Bool cold); + /** + * Scan register setting interface + */ + SANE_Status (*init_scan_regs) (Genesys_Device * dev, + Genesys_Register_Set * reg, + float xres, + float yres, + float startx, + float starty, + float pixels, + float lines, + unsigned int depth, + unsigned int channels, + int scan_method, + int scan_mode, + int color_filter, + unsigned int flags); + } Genesys_Command_Set; /** @brief structure to describe a scanner model @@ -583,7 +610,7 @@ typedef struct Genesys_Model SANE_Int bpp_color_values[MAX_DPI]; /* possible depths in color mode */ SANE_Fixed x_offset; /* Start of scan area in mm */ - SANE_Fixed y_offset; /* Start of scan area in mm (Amount of + SANE_Fixed y_offset; /* Start of scan area in mm (Amount of feeding needed to get to the medium) */ SANE_Fixed x_size; /* Size of scan area in mm */ SANE_Fixed y_size; /* Size of scan area in mm */ @@ -600,7 +627,7 @@ typedef struct Genesys_Model SANE_Fixed post_scan; /* Size of scan area after paper sensor stops sensing document in mm */ - SANE_Fixed eject_feed; /* Amount of feeding needed to eject document + SANE_Fixed eject_feed; /* Amount of feeding needed to eject document after finishing scanning in mm */ /* Line-distance correction (in pixel at optical_ydpi) for CCD scanners */ @@ -654,7 +681,7 @@ typedef struct unsigned int color_filter; /**< true if scan is true gray, false if monochrome scan */ - int true_gray; + int true_gray; /**< lineart threshold */ int threshold; @@ -691,7 +718,7 @@ typedef struct Genesys_Current_Setup float xres; /* used xres */ float yres; /* used yres*/ SANE_Bool half_ccd; /* half ccd mode */ - SANE_Int stagger; + SANE_Int stagger; SANE_Int max_shift; /* max shift of any ccd component, including staggered pixels*/ } Genesys_Current_Setup; @@ -780,7 +807,7 @@ struct Genesys_Device size_t wpl; /**< asic's word per line */ Genesys_Current_Setup current_setup; /* contains the real used values */ - + /**< look up table used in dynamic rasterization */ unsigned char lineart_lut[256]; @@ -850,7 +877,7 @@ typedef struct { #define SCAN_FLAG_CALIBRATION 0x100 #define SCAN_FLAG_FEEDING 0x200 #define SCAN_FLAG_USE_XPA 0x400 - +#define SCAN_FLAG_ENABLE_LEDADD 0x800 #define MOTOR_FLAG_AUTO_GO_HOME 0x01 #define MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE 0x02 #define MOTOR_FLAG_FEED 0x04 @@ -995,7 +1022,7 @@ extern void sanei_genesys_create_gamma_table (uint16_t * gamma_table, int size, float maximum, float gamma_max, float gamma); - + extern SANE_Status sanei_genesys_send_gamma_table (Genesys_Device * dev); extern SANE_Status sanei_genesys_start_motor (Genesys_Device * dev); @@ -1054,7 +1081,7 @@ sanei_genesys_wait_for_home(Genesys_Device *dev); extern SANE_Status sanei_genesys_asic_init(Genesys_Device *dev, SANE_Bool cold); -extern +extern int sanei_genesys_compute_dpihw(Genesys_Device *dev, int xres); extern @@ -1173,7 +1200,7 @@ compute_planar_coefficients (Genesys_Device * dev, unsigned int channels, unsigned int cmat[3], unsigned int offset, - unsigned int coeff, + unsigned int coeff, unsigned int target); void @@ -1190,6 +1217,10 @@ compute_shifted_coefficients (Genesys_Device * dev, SANE_Status probe_genesys_devices (void); + +SANE_Status genesys_flatbed_calibration (Genesys_Device *dev); + +SANE_Status genesys_send_shading_coefficient (Genesys_Device *dev); #endif diff --git a/backend/hp3900_debug.c b/backend/hp3900_debug.c index 18f6136..eb7d45c 100644 --- a/backend/hp3900_debug.c +++ b/backend/hp3900_debug.c @@ -597,7 +597,7 @@ dbg_tiff_save (char *sFile, SANE_Int width, SANE_Int height, SANE_Int depth, } else DBG (DBG_ERR, - "- dbg_tiff_save: Enviroment HOME variable does not exist\n"); + "- dbg_tiff_save: Environment HOME variable does not exist\n"); } #else /* silent gcc */ diff --git a/backend/hp3900_sane.c b/backend/hp3900_sane.c index a1c381c..b815572 100644 --- a/backend/hp3900_sane.c +++ b/backend/hp3900_sane.c @@ -1405,7 +1405,7 @@ options_init (TScanner * scanner) pDesc->title = SANE_I18N ("Scanner model"); pDesc->desc = SANE_I18N - ("Allows to test device behaviour with other supported models"); + ("Allows one to test device behaviour with other supported models"); pDesc->type = SANE_TYPE_STRING; pDesc->size = max_string_size (scanner->list_models); pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; diff --git a/backend/kodakaio.c b/backend/kodakaio.c index 8c4583a..e98208f 100644 --- a/backend/kodakaio.c +++ b/backend/kodakaio.c @@ -1,7 +1,7 @@ /* * kodakaio.c - SANE library for Kodak ESP Aio scanners. * - * Copyright (C) 2011-2013 Paul Newall + * Copyright (C) 2011-2015 Paul Newall * * Based on the Magicolor sane backend: * Based on the epson2 sane backend: @@ -14,19 +14,32 @@ * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. - * Using avahi now 25/11/12 for net autodiscovery. Use configure option --enable-avahi + * Modified 30/12/14 to fix bug where network connection was broken after 30s of idle time. + * The connection is now made in sane_start and ended in sane_cancel. * 01/01/13 Now with adf, the scan can be padded to make up the full page length, * or the page can terminate at the end of the paper. This is a selectable option. + * 25/11/12 Using avahi now for net autodiscovery. Use configure option --enable-avahi */ -/* convenient lines to paste -export SANE_DEBUG_KODAKAIO=10 +/* +Packages to add to a clean ubuntu install +libavahi-common-dev +libusb-dev +libsnmp-dev + +convenient lines to paste +export SANE_DEBUG_KODAKAIO=20 for ubuntu prior to 12.10 -./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS=kodakaio +./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS="kodakaio test" for ubuntu 12.10 -./configure --prefix=/usr --libdir=/usr/lib/i386-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS=kodakaio +./configure --prefix=/usr --libdir=/usr/lib/i386-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS="kodakaio test" + +for ubuntu 14.10 +./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS="kodakaio test" + +If you want to use the test backend, for example with sane-troubleshoot, you should enable it in /etc/sane.d/dll.conf */ @@ -50,20 +63,14 @@ for ubuntu 12.10 */ /* FUNCTION-TREE sane_init - sane_start - k_init_parametersta - k_lock_scanner - k_set_scanning_parameters - print_params - k_start_scan - cmd_start_scan - print_status - k_send - kodakaio_txrxack sane_open device_detect + k_dev_init + open_scanner + close_scanner sane_get_devices init_options + (open_scanner - moved to sane_start 27/12/14 ) sane_control_option getvalue setvalue @@ -71,6 +78,18 @@ for ubuntu 12.10 change_source activateOption deactivateOption + sane_start + open_scanner + k_init_parametersta + k_lock_scanner + k_hello + k_set_scanning_parameters + print_params + k_start_scan + cmd_start_scan + print_status + k_send + kodakaio_txrxack sane_get_parameters print_params sane_read @@ -78,6 +97,11 @@ for ubuntu 12.10 cmd_read_data (reads one block) k_recv cmp_array + sane_cancel + cmd_cancel_scan + close_scanner + sane_close + (close_scanner - moved to sane_cancel 27/12/14) sane_exit free_devices k_recv @@ -89,7 +113,9 @@ for ubuntu 12.10 open_scanner sanei_kodakaio_net_open close_scanner - sanei_kodakaio_net_close + k_scan_finish + cmd_cancel_scan + sanei_kodakaio_net_close or sanei_usb_close detect_usb kodakaio_getNumberOfUSBProductIds attach_one_config - (Passed to sanei_configure_attach) @@ -126,8 +152,8 @@ for ubuntu 12.10 #define KODAKAIO_VERSION 02 -#define KODAKAIO_REVISION 4 -#define KODAKAIO_BUILD 6 +#define KODAKAIO_REVISION 7 +#define KODAKAIO_BUILD 2 /* for usb (but also used for net though it's not required). */ #define MAX_BLOCK_SIZE 32768 @@ -214,10 +240,12 @@ 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 */ + /* This file is used to store directly the raster returned by the scanner for debugging If RawScanPath has no length it will not be created */ FILE *RawScan = NULL; -/* example: unsigned char RawScanPath[] = "TestRawScan.pgm"; */ +/* example: char RawScanPath[] = "TestRawScan.pgm"; */ char RawScanPath[] = ""; /* empty path means no raw scan file is made */ /* @@ -566,16 +594,17 @@ commandtype, max depth, pointer to depth list * The depth variable gets updated when the bit depth is modified. */ +/* could be affecting what data sane delivers */ static struct mode_param mode_params[] = { - /* {0x00, 1, 1}, // Lineart, 1 color, 1 bit */ + {0x03, 3, 24}, /* Color, 3 colors, 24 bit */ {0x02, 1, 8}, /* Grayscale, 1 color, 8 bit */ - {0x03, 3, 24} /* Color, 3 colors, 24 bit */ + {0x00, 1, 1} /* Lineart, 1 color, 8 bit (was 8 bit) */ }; static SANE_String_Const mode_list[] = { - /* SANE_VALUE_SCAN_MODE_LINEART, */ - SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, + SANE_VALUE_SCAN_MODE_GRAY, + SANE_VALUE_SCAN_MODE_LINEART, NULL }; @@ -602,6 +631,9 @@ static SANE_String_Const source_list[] = { NULL }; +static const SANE_Range percent_range_fixed = {SANE_FIX(0.0), SANE_FIX(100.0), SANE_FIX(1.0)}; +static const SANE_Range percent_range_int = {0, 100, 1}; + /* prototypes */ static SANE_Status attach_one_usb(SANE_String_Const devname); static SANE_Status attach_one_net(SANE_String_Const devname, unsigned int device); @@ -659,11 +691,12 @@ print_status(KodakAio_Scanner *s,int level) /**************************************************************************** * Low-level Network communication functions ****************************************************************************/ -/* We don't have a packet wrapper, which holds packet size etc., so we - don't have to use a *read_raw and a *_read function... */ static int kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted, SANE_Status * status) +/* there seems to be a condition where this returns no error and no data without detecting a timeout +That is probably if the scanner disconnected the network connection +*/ { size_t size, read = 0; struct pollfd fds[1]; @@ -676,7 +709,7 @@ kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted, fds[0].events = POLLIN; fds[0].revents = 0; if ((pollreply = poll (fds, 1, K_Request_Timeout)) <= 0) { - if (pollreply ==0) + if (pollreply == 0) DBG(1, "net poll timeout\n"); else /* pollreply is -ve */ @@ -684,21 +717,22 @@ kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted, *status = SANE_STATUS_IO_ERROR; return read; } - else if(fds[0].revents & POLLIN) { + 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); size = sanei_tcp_read(s->fd, buf + read, wanted - read); - - if (size == 0) - break; - + if (size == 0) { + DBG(1, "No data read. Scanner may have disconnected\n"); + break; + } read += size; } -/* this error removed 28/12/12 because adf scans end with less data than wanted - if (read < wanted) + if (read == 0) *status = SANE_STATUS_IO_ERROR; - */ + DBG(32, "net read %d bytes:%x,%x,%x,%x,%x,%x,%x,%x\n",read,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]); + return read; } else @@ -706,7 +740,7 @@ kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted, return read; } -/* kodak does not pad commands like magicolor, so there's only a write_raw function */ + static int sanei_kodakaio_net_write_raw(struct KodakAio_Scanner *s, const unsigned char *buf, size_t buf_size, @@ -832,6 +866,7 @@ k_recv(KodakAio_Scanner * s, void *buf, ssize_t buf_size, this function called by a number of others In USB mode, this function will wait until data is available for a maximum of SCANNER_READ_TIMEOUT seconds. +In NET mode the timeout is in kodakaio_net_read */ ssize_t n = 0; char fmt_buf[25]; @@ -847,6 +882,10 @@ In USB mode, this function will wait until data is available for a maximum of SC DBG(min(16,DBG_READ), "[%ld] %s: net req size = %ld ", (long) time_start, __func__, (long) buf_size); n = kodakaio_net_read(s, buf, buf_size, status); DBG(min(16,DBG_READ), "returned %d\n", n); + if (*status != SANE_STATUS_GOOD) { + DBG(1, "%s: err returned from kodakaio_net_read, %s\n", __func__, sane_strstatus(*status)); + } + } else if (s->hw->connection == SANE_KODAKAIO_USB) { /* Start the clock for USB timeout */ @@ -922,17 +961,30 @@ kodakaio_txrx(KodakAio_Scanner *s, unsigned char *txbuf, unsigned char *rxbuf) /* Sends 8 byte data to scanner and returns reply and appropriate status. */ { SANE_Status status; + ssize_t n = 0; k_send(s, txbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status)); return status; } - k_recv(s, rxbuf, 8, &status); + n = k_recv(s, rxbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: %s gave rx err, %s\n", __func__, "txvalue", sane_strstatus(status)); return status; } + if (n == 0) { + DBG(1, "%s: try 1 k_recv returned 0 bytes with status %s\n", __func__, sane_strstatus(status)); + n = k_recv(s, rxbuf, 8, &status); + if (status != SANE_STATUS_GOOD) { + DBG(1, "%s: %s gave rx err, %s\n", __func__, "txvalue", sane_strstatus(status)); + return status; + } + if (n == 0) { + DBG(1, "%s: try 2 k_recv returned 0 bytes with status %s\n", __func__, sane_strstatus(status)); + return status; + } + } return status; } @@ -962,7 +1014,8 @@ and returns appropriate status s->adf_loaded = SANE_TRUE; DBG(5, "%s: News - docs in ADF\n", __func__); } - else if (rxbuf[4] != 0x01 && s->adf_loaded == SANE_TRUE) { + else if (rxbuf[4] != +0x01 && s->adf_loaded == SANE_TRUE) { s->adf_loaded = SANE_FALSE; DBG(5, "%s: News - ADF is empty\n", __func__); } @@ -976,6 +1029,25 @@ and returns appropriate status return status; } +static ssize_t +kodakaio_rxflush(KodakAio_Scanner *s) +/* +Tries to get 64 byte reply +and returns number of bytes read +*/ +{ + SANE_Status status; + unsigned char rxbuf[64]; + ssize_t n = 0; + + n = k_recv(s, rxbuf, 64, &status); + if (status != SANE_STATUS_GOOD) { + DBG(1, "%s: %s gave rx err, %s\n", __func__, "status", sane_strstatus(status)); + } + DBG(5, "%s: flushed, %d bytes\n", __func__, (int)n); + return n; +} + /* * high-level communication commands */ @@ -988,6 +1060,13 @@ k_hello (KodakAio_Scanner * s) char fmt_buf[25]; DBG(5, "%s\n", __func__); + +/* check that there is nothing already in the input buffer before starting +kodakaio_rxflush(s); +*/ +/* preset the reply, so I can see if it gets changed */ +reply[0] = 0; reply[1] = 1; reply[2] = 2; reply[3] = 3; reply[4] = 4; reply[5] = 5; reply[6] = 6; reply[7] = 7; + if((status = kodakaio_txrx(s, KodakEsp_V, reply))!= SANE_STATUS_GOOD) { DBG(1, "%s: KodakEsp_V failure, %s\n", __func__, sane_strstatus(status)); return SANE_STATUS_IO_ERROR; @@ -998,6 +1077,8 @@ k_hello (KodakAio_Scanner * s) DBG(1, "%s: KodakEsp_v err, got %s\n", __func__, fmt_buf); return SANE_STATUS_IO_ERROR; } + + DBG(5, "%s: OK %s\n", __func__, sane_strstatus(status)); return status; } @@ -1045,12 +1126,24 @@ cmd_cancel_scan (SANE_Handle handle) unsigned char reply[8]; /* adf added 20/2/12 should it be adf? or adf with paper in? */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { /* adf */ - if (kodakaio_txrxack(s, KodakEsp_F, reply)!= SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR; - if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR; + if (kodakaio_txrxack(s, KodakEsp_F, reply)!= SANE_STATUS_GOOD) + { + DBG(1, "%s: KodakEsp_F command failed\n", __func__); + return SANE_STATUS_IO_ERROR; + } + if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) + { + DBG(1, "%s: KodakEsp_UnLock command failed\n", __func__); + return SANE_STATUS_IO_ERROR; + } DBG(5, "%s unlocked the scanner with adf F U\n", __func__); } else { /* no adf */ - if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR; + if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) + { + DBG(1, "%s: KodakEsp_UnLock command failed\n", __func__); + return SANE_STATUS_IO_ERROR; + } DBG(5, "%s unlocked the scanner U\n", __func__); } s->scanning = SANE_FALSE; @@ -1084,6 +1177,7 @@ Old mc cmd read this stuff from the scanner. I don't think kodak can do that eas return status; } +/* Set color curve command, low level, sends commands to the scanner*/ static SANE_Status cmd_set_color_curve(SANE_Handle handle, unsigned char col) { @@ -1093,11 +1187,12 @@ cmd_set_color_curve(SANE_Handle handle, unsigned char col) unsigned char tx_col[8]; unsigned char rx[8]; unsigned char tx_curve[256]; - unsigned char i; + int i; /* 7/9/14 was unsigned char and that stopped the loop that made the linear curve from going to 255 */ DBG(32, "%s: start\n", __func__); tx_col[0]=0x1b; tx_col[1]='S'; tx_col[2]='K'; tx_col[3]=col; tx_col[4]=0; tx_col[5]=0; tx_col[6]=0; tx_col[7]=0; /* linear curve now but could send tailor made curves in future */ - for(i=0;i<255;++i) tx_curve[i]=i; + for(i=0;i<=255;++i) tx_curve[i]=i; /* 7/9/14 was i<255 the missing elements caused speckles */ + k_send(s, tx_col, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, "curve command"); @@ -1113,7 +1208,7 @@ cmd_set_color_curve(SANE_Handle handle, unsigned char col) return status; } -/* Set scanning parameters command low level */ +/* Set scanning parameters command, low level, sends commands to the scanner*/ static SANE_Status cmd_set_scanning_parameters(SANE_Handle handle, int resolution, @@ -1210,8 +1305,6 @@ unsigned int i; return 0; } - - static SANE_Status cmd_read_data (SANE_Handle handle, unsigned char *buf, size_t *len) { @@ -1283,11 +1376,11 @@ But it seems that the scanner takes care of that, and gives you the ack as a sep } } else { - DBG(min(1,DBG_READ), "%s: tiny read, got %d bytes of %d\n", __func__, bytecount, *len); + DBG(min(1,DBG_READ), "%s: tiny read, got %d bytes of %d\n", __func__, (int) bytecount, *len); return SANE_STATUS_IO_ERROR; } if (*len > s->params.bytes_per_line) { - /* store average colour as background. That's not the ideal method but it's easy to implement. */ + /* store average colour as background. That's not the ideal method but it's easy to implement. What's it used for? */ lines = *len / s->params.bytes_per_line; s->background[0] = 0; s->background[1] = 0; @@ -1545,11 +1638,11 @@ k_set_scanning_parameters(KodakAio_Scanner * s) s->params.bytes_per_line *= 3; /* Calculate how many bytes per line will be returned by the scanner. - magicolor needed this because it uses padding. Scan bytes per line != image bytes per line + magicolor needed this because it uses padding so scan bytes per line != image bytes per line. * The values needed for this are returned by get_scanning_parameters */ - s->scan_bytes_per_line = 3 * ceil (scan_pixels_per_line * s->params.depth / 8.0); + s->scan_bytes_per_line = 3 * ceil (scan_pixels_per_line); /* we always scan in colour 8 bit */ s->data_len = s->scan_bytes_per_line * floor (s->height * dpi / optres + 0.5); /* NB this is the length for a full scan */ - DBG (1, "Check: scan_bytes_per_line = %d s->params.bytes_per_line = %d \n", s->scan_bytes_per_line, s->params.bytes_per_line); + DBG (5, "Check: scan_bytes_per_line = %d s->params.bytes_per_line = %d \n", s->scan_bytes_per_line, s->params.bytes_per_line); /* k_setup_block_mode at the start of each page for adf to work */ status = k_setup_block_mode (s); @@ -1604,10 +1697,14 @@ k_copy_image_data(KodakAio_Scanner * s, SANE_Byte * data, SANE_Int max_length, uncompressed data is RRRR...GGGG...BBBB per line */ { SANE_Int bytes_available; + SANE_Int threshold; DBG (min(18,DBG_READ), "%s: bytes_read in line: %d\n", __func__, s->bytes_read_in_line); *length = 0; + threshold = 255 - (int) (SANE_UNFIX(s->val[OPT_THRESHOLD].w) * 255.0 / 100.0 + 0.5); /* 255 - for the grey scale version */ + DBG (20, "%s: threshold: %d\n", __func__, threshold); + while ((max_length >= s->params.bytes_per_line) && (s->ptr < s->end)) { SANE_Int bytes_to_copy = s->scan_bytes_per_line - s->bytes_read_in_line; /* First, fill the line buffer for the current line: */ @@ -1635,23 +1732,36 @@ uncompressed data is RRRR...GGGG...BBBB per line */ *length += s->params.bytes_per_line; for (i=0; i< s->params.pixels_per_line; ++i) { + /* different behaviour for each mode */ if (s->val[OPT_MODE].w == MODE_COLOR){ - /*interlace */ - *data++ = 255-line[0]; /*red */ - *data++ = 255-line[s->params.pixels_per_line]; /*green */ - *data++ = 255-line[2 * s->params.pixels_per_line]; /*blue */ + /*interlace was subtracting from 255 until 6/9/14 */ + *data++ = 255-line[0]; /*red */ + *data++ = 255-line[s->params.pixels_per_line]; /*green */ + *data++ = 255-line[2 * s->params.pixels_per_line]; /*blue */ + } + else if (s->val[OPT_MODE].w == MODE_LINEART) { /* gives 1 bit output */ + /*output image location*/ + int offset = i % 8; + unsigned char mask = 0x80 >> offset; + /*set if any colour is over the threshold */ + if (line[0] < threshold || line[s->params.pixels_per_line] < threshold || line[2 * s->params.pixels_per_line] < threshold) + *data &= ~mask; /* white clear the bit in mask */ + else + *data |= mask; /* black set the bit in mask */ + + if (offset == 7 || i == s->params.pixels_per_line-1) + data++; /* move on a byte if the byte is full or the line is complete */ } - else { /* grey */ - /*Average*/ - *data++ = (255-line[0] + else { /* greyscale - Average the 3 colours */ + *data++ = (255-line[0] +255-line[s->params.pixels_per_line] +255-line[2 * s->params.pixels_per_line]) / 3; } - line++; + line++; } /*debug file The same for color or grey because the scan is colour */ if (RawScan != NULL) { @@ -1716,21 +1826,22 @@ k_init_parametersta(KodakAio_Scanner * s) SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w)); /* - * The default color depth is stored in mode_params.depth: + * The default color depth is stored in mode_params.depth:‭ */ if (mode_params[s->val[OPT_MODE].w].depth == 1) s->params.depth = 1; else { - DBG(20, "%s: setting depth = s->val[OPT_BIT_DEPTH].w = %d\n", __func__,s->val[OPT_BIT_DEPTH].w); s->params.depth = s->val[OPT_BIT_DEPTH].w; } + DBG(20, "%s: bit depth = s->params.depth = %d\n", __func__,s->params.depth); s->params.last_frame = SANE_TRUE; s->params.bytes_per_line = 3 * ceil (s->params.depth * s->params.pixels_per_line / 8.0); -/* kodak only scans in color and conversion to grey is done in the driver +/* kodak only scans in color and conversion to grey or lineart is done in the driver s->params.format = SANE_FRAME_RGB; */ - DBG(20, "%s: s->val[OPT_MODE].w = %d (color is %d)\n", __func__,s->val[OPT_MODE].w, MODE_COLOR); + DBG(20, "%s: s->val[OPT_MODE].w = %d (color is %d)\n", __func__,s->val[OPT_MODE].w, MODE_COLOR); if (s->val[OPT_MODE].w == MODE_COLOR) s->params.format = SANE_FRAME_RGB; + else if (s->val[OPT_MODE].w == MODE_LINEART) s->params.format = SANE_FRAME_GRAY; else s->params.format = SANE_FRAME_GRAY; DBG(20, "%s: format=%d, bytes_per_line=%d, lines=%d\n", __func__, s->params.format, s->params.bytes_per_line, s->params.lines); @@ -1761,19 +1872,16 @@ you don't know how many blocks there will be in advance because their size may b SANE_Status status = SANE_STATUS_GOOD; size_t buf_len = 0; - /* did we passed everything we read to sane? */ + /* have we passed everything we read to sane? */ if (s->ptr == s->end) { - if (s->eof) return SANE_STATUS_EOF; s->counter++; - if (s->bytes_unread >= s->block_len) buf_len = s->block_len; else buf_len = s->bytes_unread; - DBG(min(20,DBG_READ), "%s: block %d, size %lu\n", __func__, s->counter, (unsigned long) buf_len); @@ -1810,9 +1918,7 @@ you don't know how many blocks there will be in advance because their size may b return SANE_STATUS_IO_ERROR; } } - } - s->end = s->buf + buf_len; s->ptr = s->buf; } @@ -1858,7 +1964,6 @@ get_device_from_identification (const char *ident, const char *vid, const char * return NULL; } - /* * close_scanner() * @@ -2184,6 +2289,7 @@ static void resolve_callback( AvahiLookupResultFlags flags, AVAHI_GCC_UNUSED void* userdata) { + AvahiStringList *vid_pair_list = NULL, *pid_pair_list = NULL; char *pidkey, *pidvalue; char *vidkey, *vidvalue; size_t valuesize; @@ -2204,20 +2310,40 @@ static void resolve_callback( avahi_address_snprint(a, sizeof(a), address); /* Output short for Kodak ESP */ - DBG(min(10,DBG_AUTO), "%s:%u %s ", a,port,host_name); - avahi_string_list_get_pair(avahi_string_list_find(txt, "vid"), - &vidkey, &vidvalue, &valuesize); - DBG(min(10,DBG_AUTO), "%s=%s ", vidkey, vidvalue); - avahi_string_list_get_pair(avahi_string_list_find(txt, "pid"), - &pidkey, &pidvalue, &valuesize); - DBG(min(10,DBG_AUTO), "%s=%s\n", pidkey, pidvalue); + DBG(min(10,DBG_AUTO), "%s:%u %s\n", a,port,host_name); + + vid_pair_list = avahi_string_list_find(txt, "vid"); + if(vid_pair_list != NULL) { + avahi_string_list_get_pair(vid_pair_list, &vidkey, &vidvalue, &valuesize); + DBG(min(10,DBG_AUTO), "%s=%s ", vidkey, vidvalue); + } + else DBG(min(10,DBG_AUTO), "failed to find key vid\n"); + pid_pair_list = avahi_string_list_find(txt, "pid"); + if(pid_pair_list != NULL) { + avahi_string_list_get_pair(pid_pair_list, &pidkey, &pidvalue, &valuesize); + DBG(min(10,DBG_AUTO), "%s=%s\n", pidkey, pidvalue); + } + else DBG(min(10,DBG_AUTO), "failed to find key pid\n"); + + if(pid_pair_list != NULL && vid_pair_list != NULL) { ProcessAvahiDevice(name, vidvalue, pidvalue, a); - avahi_free(vidkey); avahi_free(vidvalue); - avahi_free(pidkey); avahi_free(pidvalue); + } + else DBG(min(10,DBG_AUTO), "didn't call ProcessAvahiDevice\n"); + + if(vid_pair_list != NULL) { + avahi_free(vidkey); + avahi_free(vidvalue); + DBG(min(15,DBG_AUTO), "vidkey and vidvalue freed\n"); + } + if(pid_pair_list != NULL) { + avahi_free(pidkey); + avahi_free(pidvalue); + DBG(min(15,DBG_AUTO), "pidkey and pidvalue freed\n"); + } } } - + DBG(min(10,DBG_AUTO), "ending resolve_callback\n"); avahi_service_resolver_free(r); } @@ -2619,8 +2745,32 @@ init_options(KodakAio_Scanner *s) s->opt[OPT_MODE].size = max_string_size(mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; - s->val[OPT_MODE].w = 0; /* Binary */ - DBG(20, "%s: mode_list has first entry %s\n", __func__, mode_list[0]); + s->val[OPT_MODE].w = MODE_COLOR; /* default */ + DBG(20, "%s: mode_list has first entry %s, default mode is %s\n", __func__, mode_list[0],mode_list[s->val[OPT_MODE].w]); + + /* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255 */ + s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; + s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; + s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; + s->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; + s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; + s->opt[OPT_THRESHOLD].size = sizeof(SANE_Word); + s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; + s->opt[OPT_THRESHOLD].constraint.range = &percent_range_fixed; + s->val[OPT_THRESHOLD].w = SANE_FIX(50.0); + DBG(20, "%s: threshold initialised to fixed %f\n", __func__, SANE_UNFIX(s->val[OPT_THRESHOLD].w)); + + /* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255 + s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; + s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; + s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; + s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; + s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; + s->opt[OPT_THRESHOLD].size = sizeof(SANE_Word); + s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; + s->opt[OPT_THRESHOLD].constraint.range = &percent_range_int; + s->val[OPT_THRESHOLD].w = 51; + DBG(20, "%s: threshold initialised to int %d\n", __func__, s->val[OPT_THRESHOLD].w); */ /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; @@ -2656,6 +2806,17 @@ init_options(KodakAio_Scanner *s) s->val[OPT_RESOLUTION].w = s->hw->cap->dpi_range.min; + /* trial option for debugging + s->opt[OPT_TRIALOPT].name = "trialoption"; + s->opt[OPT_TRIALOPT].title = "trialoption"; + s->opt[OPT_TRIALOPT].desc = "trialoption"; + s->opt[OPT_TRIALOPT].type = SANE_TYPE_INT; + s->opt[OPT_TRIALOPT].unit = SANE_UNIT_NONE; + s->opt[OPT_TRIALOPT].size = sizeof(SANE_Word); + s->opt[OPT_TRIALOPT].constraint_type = SANE_CONSTRAINT_RANGE; + s->opt[OPT_TRIALOPT].constraint.range = &percent_range_int; + s->val[OPT_TRIALOPT].w = 1; */ + /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; @@ -2831,12 +2992,13 @@ maybe we should only be rebuilding the source list here? */ *handle = (SANE_Handle) s; +/* moving the open scanner section below to sane_start 27/12/14 status = open_scanner(s); if (status != SANE_STATUS_GOOD) { free(s); return status; } - +*/ return status; } @@ -2853,8 +3015,11 @@ sane_close(SANE_Handle handle) s = (KodakAio_Scanner *) handle; DBG(2, "%s: called\n", __func__); +/* moving the close scanner section below to sane_cancel 27/12/14 */ if (s->fd != -1) close_scanner(s); +/* end of section */ + if(RawScan != NULL) fclose(RawScan); RawScan = NULL; @@ -2867,7 +3032,7 @@ sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) /* this may be a sane call, but it happens way too often to have DBG level 2 */ KodakAio_Scanner *s = (KodakAio_Scanner *) handle; - DBG(20, "%s: called for option %d\n", __func__, option); + DBG(30, "%s: called for option %d\n", __func__, option); if (option < 0 || option >= NUM_OPTIONS) return NULL; @@ -2922,7 +3087,7 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value) case OPT_NUM_OPTS: case OPT_BIT_DEPTH: -/* case OPT_BRIGHTNESS: */ + /* case OPT_TRIALOPT: */ case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: @@ -2930,6 +3095,13 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value) case OPT_BR_X: case OPT_BR_Y: *((SANE_Word *) value) = sval->w; + DBG(20, "%s: got option %d as %d\n", __func__, option, *((SANE_Word *) value)); + break; + + case OPT_THRESHOLD: + *((SANE_Word *) value) = sval->w; + DBG(20, "%s: got option %d as %f\n", __func__, option, SANE_UNFIX(*((SANE_Word *) value))); + /*DBG(20, "%s: got option %d as %d\n", __func__, option, *((SANE_Word *) value));*/ break; case OPT_MODE: @@ -2942,9 +3114,11 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value) break; default: + DBG(20, "%s: returning inval\n", __func__); return SANE_STATUS_INVAL; } + DBG(20, "%s: returning good\n", __func__); return SANE_STATUS_GOOD; } @@ -3050,18 +3224,23 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) case OPT_MODE: { sval->w = optindex; - /* if binary, then disable the bit depth selection */ - if (optindex == 0) { + /* if binary, then disable the bit depth selection and enable threshold */ + if (optindex == MODE_LINEART) { + DBG(17, "%s: binary mode setting depth to 1\n", __func__); + s->val[OPT_BIT_DEPTH].w = 1; s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { - if (s->hw->cap->depth_list[0] == 1) - s->opt[OPT_BIT_DEPTH].cap |= - SANE_CAP_INACTIVE; - else { - s->opt[OPT_BIT_DEPTH].cap &= - ~SANE_CAP_INACTIVE; - s->val[OPT_BIT_DEPTH].w = - mode_params[optindex].depth; + if (s->hw->cap->depth_list[0] == 1) { /* only one entry in the list ? */ + DBG(17, "%s: non-binary mode but only one depth available\n", __func__); + s->val[OPT_BIT_DEPTH].w = s->hw->cap->depth_list[1]; + s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; + } else { /* there is a list to choose from ? */ + DBG(17, "%s: non-binary mode and depth list available\n", __func__); + s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; + s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth; + s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* does not work in xsane ? */ } } reload = SANE_TRUE; @@ -3074,6 +3253,13 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) reload = SANE_TRUE; break; + case OPT_THRESHOLD: + sval->w = *((SANE_Word *) value); + DBG(17, "setting threshold to %f\n", SANE_UNFIX(sval->w)); + /*DBG(17, "setting threshold to %d\n", sval->w);*/ + /*reload = SANE_TRUE; what does this do?*/ + break; + case OPT_RESOLUTION: sval->w = *((SANE_Word *) value); DBG(17, "setting resolution to %d\n", sval->w); @@ -3109,7 +3295,7 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) sval->w = *((SANE_Word *) value); break; -/* case OPT_BRIGHTNESS: */ + /* case OPT_TRIALOPT: */ case OPT_PREVIEW: /* needed? */ sval->w = *((SANE_Word *) value); break; @@ -3131,14 +3317,14 @@ sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; - DBG(2, "%s: action = %x, option = %d %s\n", __func__, action, option, s->opt[option].name); - if (option < 0 || option >= NUM_OPTIONS) { - DBG(1, "%s: option num = %d (%s) out of range\n", __func__, option, s->opt[option].name); + DBG(1, "%s: option num = %d out of range (0..%d)\n", __func__, option, NUM_OPTIONS - 1); return SANE_STATUS_INVAL; } + DBG(5, "%s: action = %x, option = %d %s\n", __func__, action, option, s->opt[option].name); + if (info != NULL) *info = 0; @@ -3209,6 +3395,16 @@ sane_start(SANE_Handle handle) * them to s->params Only set scanning params the first time, or after a cancel try change 22/2/12 take lock scanner out of k_set_scanning_parameters */ + +/* moved open_scanner here 27/12/14 from sane_open */ + status = open_scanner(s); + if (status != SANE_STATUS_GOOD) { + free(s); + return status; + } +/* end of open scanner section */ + + status = k_lock_scanner(s); if (status != SANE_STATUS_GOOD) { DBG(1, "could not lock scanner\n"); @@ -3299,24 +3495,24 @@ sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, return status; } -/* - * void sane_cancel(SANE_Handle handle) - * - * Set the cancel flag to true. The next time the backend requests data - * from the scanner the CAN message will be sent. - */ void sane_cancel(SANE_Handle handle) { + SANE_Status status; KodakAio_Scanner *s = (KodakAio_Scanner *) handle; DBG(2, "%s: called\n", __func__); -/* used to set cancelling flag to tell sane_read to cancel -changed 20/2/12 - s->canceling = SANE_TRUE; -*/ - cmd_cancel_scan(s); + status = cmd_cancel_scan(s); + if (status != SANE_STATUS_GOOD) + DBG(1, "%s: cmd_cancel_scan failed: %s\n", __func__, + sane_strstatus(status)); + +/* moved from close scanner section 27/12/14 */ + if (s->fd != -1) + close_scanner(s); +/* end of section */ + } /* diff --git a/backend/kodakaio.h b/backend/kodakaio.h index f2265f5..6804e3b 100644 --- a/backend/kodakaio.h +++ b/backend/kodakaio.h @@ -97,8 +97,10 @@ enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, + OPT_THRESHOLD, OPT_BIT_DEPTH, OPT_RESOLUTION, + OPT_TRIALOPT, /* for debuggging */ OPT_PREVIEW, OPT_SOURCE, OPT_ADF_MODE, @@ -163,6 +165,7 @@ struct KodakAio_Scanner SANE_Int left, top; /* in optres units? */ SANE_Int width, height; /* in optres units? */ + /* SANE_Int threshold; 0..255 for lineart*/ /* image block data */ SANE_Int data_len; @@ -192,7 +195,7 @@ struct mode_param }; enum { - MODE_GRAY, MODE_COLOR + MODE_COLOR, MODE_GRAY, MODE_LINEART }; #endif diff --git a/backend/kvs1025.conf.in b/backend/kvs1025.conf.in new file mode 100644 index 0000000..1e3cb59 --- /dev/null +++ b/backend/kvs1025.conf.in @@ -0,0 +1,2 @@ +usb "Panasonic KV-S1025C" +/dev/scanner diff --git a/backend/mustek_pp_ccd300.c b/backend/mustek_pp_ccd300.c index c5351a4..dc43c0f 100644 --- a/backend/mustek_pp_ccd300.c +++ b/backend/mustek_pp_ccd300.c @@ -1660,7 +1660,7 @@ ccd300_open (SANE_String port, SANE_Int caps, SANE_Int * fd) if (caps & ~(CAP_NOTHING | CAP_INVERT | CAP_LAMP_OFF)) { - DBG (1, "ccd300_open: called with unknonw capabilities (%#02x)\n", + DBG (1, "ccd300_open: called with unknown capabilities (%#02x)\n", caps); return SANE_STATUS_INVAL; } @@ -1816,7 +1816,7 @@ ccd300_config (SANE_Handle handle, SANE_String_Const optname, } else { - DBG (1, "ccd300_config: unkown option ``%s''", optname); + DBG (1, "ccd300_config: unknown option ``%s''", optname); return SANE_STATUS_INVAL; } diff --git a/backend/pixma.c b/backend/pixma.c index 6a2492e..4c7ec46 100644 --- a/backend/pixma.c +++ b/backend/pixma.c @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. diff --git a/backend/pixma.h b/backend/pixma.h index 56bd14d..af38725 100644 --- a/backend/pixma.h +++ b/backend/pixma.h @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. @@ -114,7 +114,7 @@ typedef uint32_t uint32_t; /**@{*/ #define PIXMA_VERSION_MAJOR 0 #define PIXMA_VERSION_MINOR 17 -#define PIXMA_VERSION_BUILD 4 +#define PIXMA_VERSION_BUILD 14 /**@}*/ /** \name Error codes */ diff --git a/backend/pixma_bjnp.c b/backend/pixma_bjnp.c index 3046e9d..dece926 100644 --- a/backend/pixma_bjnp.c +++ b/backend/pixma_bjnp.c @@ -65,6 +65,9 @@ #ifdef HAVE_SYS_TIME_H #include #endif +#ifdef HAVE_LIMITS_H +#include +#endif /* * networking stuff @@ -99,6 +102,9 @@ #include "pixma.h" #include "pixma_common.h" +#ifndef SSIZE_MAX +# define SSIZE_MAX LONG_MAX +#endif /* static data */ static bjnp_device_t device[BJNP_NO_DEVICES]; @@ -130,11 +136,11 @@ static void u32tohex (uint32_t x, char *str) { uint8_t uint8[4]; - uint8[0]= (uint8_t) x >> 24; - uint8[1] = (uint8_t)x >> 16; - uint8[2] = (uint8_t)x >> 8; - uint8[3] = (uint8_t)x ; - u8tohex(str, uint8, 4); + uint8[0] = (uint8_t)(x >> 24); + uint8[1] = (uint8_t)(x >> 16); + uint8[2] = (uint8_t)(x >> 8); + uint8[3] = (uint8_t)x ; + u8tohex(str, uint8, 4); } static void @@ -284,7 +290,8 @@ parse_IEEE1284_to_model (char *scanner_id, char *model) char s[BJNP_IEEE1284_MAX]; char *tok; - strcpy (s, scanner_id); + strncpy (s, scanner_id, BJNP_IEEE1284_MAX); + s[BJNP_IEEE1284_MAX - 1] = '\0'; model[0] = '\0'; tok = strtok (s, ";"); @@ -294,7 +301,8 @@ parse_IEEE1284_to_model (char *scanner_id, char *model) if (strncmp (tok, "MDL:", 4) == 0) { - strcpy (model, tok + 4); + strncpy (model, tok + 4, BJNP_IEEE1284_MAX); + model[BJNP_IEEE1284_MAX -1] = '\0'; return 1; } tok = strtok (NULL, ";"); @@ -334,6 +342,34 @@ charTo2byte (char *d, const char *s, int len) return copied; } +static bjnp_protocol_defs_t *get_protocol_by_method( char *method) +{ + int i = 0; + while ( bjnp_protocol_defs[i].method_string != NULL) + { + if (strcmp(method, bjnp_protocol_defs[i].method_string) == 0) + { + return &bjnp_protocol_defs[i]; + } + i++; + } + return NULL; +} + +static bjnp_protocol_defs_t *get_protocol_by_proto_string( char *proto_string) +{ + int i = 0; + while ( bjnp_protocol_defs[i].proto_string != NULL) + { + if (strncmp(proto_string, bjnp_protocol_defs[i].proto_string, 4) == 0) + { + return &bjnp_protocol_defs[i]; + } + i++; + } + return NULL; +} + static char * getusername (void) { @@ -364,11 +400,13 @@ determine_scanner_serial (const char *hostname, const char * mac_address, char * /* if this is a FQDN, not an ip-address, remove domain part of the name */ if ((dot = strchr (copy, '.')) != NULL) { - *dot = '\0'; + *dot = '\0'; } else - strcpy(copy, mac_address); - break; + { + strcpy(copy, mac_address); + break; + } } strcpy( serial, copy ); return serial; @@ -389,7 +427,7 @@ bjnp_open_tcp (int devno) if ((sock = socket (get_protocol_family( addr ) , SOCK_STREAM, 0)) < 0) { - PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: Can not create socket: %s\n", + PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not create socket: %s\n", strerror (errno))); return -1; } @@ -422,7 +460,7 @@ bjnp_open_tcp (int devno) (sock, &(addr->addr), sa_size(device[devno].addr) )!= 0) { PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_open_tcp: Can not connect to scanner: %s\n", + (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not connect to scanner: %s\n", strerror (errno))); return -1; } @@ -439,7 +477,8 @@ split_uri (const char *devname, char *method, char *host, char *port, char next; int i; - strcpy (copy, devname); + strncpy (copy, devname, 1024); + copy[1023] = '\0'; start = copy; /* @@ -453,7 +492,7 @@ split_uri (const char *devname, char *method, char *host, char *port, if (((strncmp (start + i, "://", 3) != 0)) || (i > BJNP_METHOD_MAX -1 )) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find method in %s (offset %d)\n", + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find method in %s (offset %d)\n", devname, i)); return -1; } @@ -476,7 +515,7 @@ split_uri (const char *devname, char *method, char *host, char *port, ( (end_of_address[1] != ':') && (end_of_address[1] != '/' ) && (end_of_address[1] != '\0' )) || ( (end_of_address - start) >= BJNP_HOST_MAX ) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find hostname or address in %s\n", devname)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find hostname or address in %s\n", devname)); return -1; } next = end_of_address[1]; @@ -495,7 +534,7 @@ split_uri (const char *devname, char *method, char *host, char *port, start[i] = '\0'; if ((i == 0) || (i >= BJNP_HOST_MAX ) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find hostname or address in %s\n", devname)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find hostname or address in %s\n", devname)); return -1; } strcpy (host, start); @@ -523,7 +562,7 @@ split_uri (const char *devname, char *method, char *host, char *port, } if ((strlen(start) == 0) || (strlen(start) >= BJNP_PORT_MAX ) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find port in %s (have \"%s\")\n", devname, start)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find port in %s (have \"%s\")\n", devname, start)); return -1; } strcpy(port, start); @@ -538,7 +577,7 @@ split_uri (const char *devname, char *method, char *host, char *port, i = strlen(start); if ( i >= BJNP_ARGS_MAX) { - PDBG (bjnp_dbg (LOG_NOTICE, "Argument string too long in %s\n", devname)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Argument string too long in %s\n", devname)); } strcpy (args, start); } @@ -550,28 +589,40 @@ split_uri (const char *devname, char *method, char *host, char *port, static void -set_cmd (int devno, struct BJNP_command *cmd, char cmd_code, int payload_len) +set_cmd_from_string (char* protocol_string, struct BJNP_command *cmd, char cmd_code, int payload_len) { /* - * Set command buffer with command code, session_id and lenght of payload + * Set command buffer with command code, session_id and length of payload * Returns: sequence number of command */ - strncpy (cmd->BJNP_id, BJNP_STRING, sizeof (cmd->BJNP_id)); + + strncpy (cmd->BJNP_id, protocol_string, sizeof (cmd->BJNP_id)); cmd->dev_type = BJNP_CMD_SCAN; cmd->cmd_code = cmd_code; cmd->unknown1 = htons (0); - if (devno == -1) - { - /* device not yet opened, use 0 for serial and session) */ - cmd->seq_no = htons (0); - cmd->session_id = htons (0); - } - else - { - cmd->seq_no = htons (++(device[devno].serial)); - cmd->session_id = (cmd_code == CMD_UDP_POLL ) ? 0 : htons (device[devno].session_id); - device[devno].last_cmd = cmd_code; - } + + /* device not yet opened, use 0 for serial and session) */ + cmd->seq_no = htons (0); + cmd->session_id = htons (0); + cmd->payload_len = htonl (payload_len); +} + +static void +set_cmd_for_dev (int devno, struct BJNP_command *cmd, char cmd_code, int payload_len) +{ + /* + * Set command buffer with command code, session_id and length of payload + * Returns: sequence number of command + * If devno < 0, then use devno as negativ index into bjnp_protocol_defs + */ + + strncpy (cmd->BJNP_id, device[devno].protocol_string, sizeof (cmd->BJNP_id)); + cmd->dev_type = BJNP_CMD_SCAN; + cmd->cmd_code = cmd_code; + cmd->unknown1 = htons (0); + cmd->seq_no = htons (++(device[devno].serial)); + cmd->session_id = (cmd_code == CMD_UDP_POLL ) ? 0 : htons (device[devno].session_id); + device[devno].last_cmd = cmd_code; cmd->payload_len = htonl (payload_len); } @@ -596,7 +647,7 @@ bjnp_setup_udp_socket ( const int dev_no ) if ((sockfd = socket (get_protocol_family( addr ), SOCK_DGRAM, IPPROTO_UDP)) == -1) { PDBG (bjnp_dbg - (LOG_CRIT, "setup_udp_socket: can not open socket - %s\n", + (LOG_CRIT, "setup_udp_socket: ERROR - can not open socket - %s\n", strerror (errno))); return -1; } @@ -605,7 +656,7 @@ bjnp_setup_udp_socket ( const int dev_no ) (sockfd, &(device[dev_no].addr->addr), sa_size(device[dev_no].addr) )!= 0) { PDBG (bjnp_dbg - (LOG_CRIT, "setup_udp_socket: connect failed- %s\n", + (LOG_CRIT, "setup_udp_socket: ERROR - connect failed- %s\n", strerror (errno))); close(sockfd); return -1; @@ -632,7 +683,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if ( (sockfd = bjnp_setup_udp_socket(dev_no) ) == -1 ) { - PDBG (bjnp_dbg( LOG_CRIT, "udp_command: Can not setup socket\n") ); + PDBG (bjnp_dbg( LOG_CRIT, "udp_command: ERROR - Can not setup socket\n") ); return -1; } @@ -641,7 +692,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if ((numbytes = send (sockfd, command, cmd_len, 0)) != cmd_len) { PDBG (bjnp_dbg - (LOG_NOTICE, "udp_command: Sent %d bytes, expected %d\n", + (LOG_NOTICE, "udp_command: ERROR - Sent %d bytes, expected %d\n", numbytes, cmd_len)); continue; } @@ -666,7 +717,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if (result <= 0) { PDBG (bjnp_dbg - (LOG_NOTICE, "udp_command: select failed: %s\n", + (LOG_NOTICE, "udp_command: ERROR - select failed: %s\n", result == 0 ? "timed out" : strerror (errno))); continue; } @@ -674,7 +725,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if ((numbytes = recv (sockfd, response, resp_len, 0)) == -1) { PDBG (bjnp_dbg - (LOG_NOTICE, "udp_command: recv failed: %s", + (LOG_NOTICE, "udp_command: ERROR - recv failed: %s", strerror (errno))); continue; } @@ -686,7 +737,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, close(sockfd); PDBG (bjnp_dbg - (LOG_CRIT, "udp_command: no data received\n" ) ); + (LOG_CRIT, "udp_command: ERROR - no data received\n" ) ); return -1; } @@ -710,36 +761,43 @@ get_scanner_id (const int dev_no, char *model) strcpy (model, "Unidentified scanner"); - set_cmd (dev_no, &cmd, CMD_UDP_GET_ID, 0); + set_cmd_for_dev (dev_no, &cmd, CMD_UDP_GET_ID, 0); - PDBG (bjnp_dbg (LOG_DEBUG2, "Get scanner identity\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "get_scanner_id: Get scanner identity\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &cmd, sizeof (struct BJNP_command))); if ( ( resp_len = udp_command (dev_no, (char *) &cmd, sizeof (struct BJNP_command), resp_buf, BJNP_RESP_MAX) ) < (int)sizeof(struct BJNP_command) ) { - PDBG (bjnp_dbg (LOG_DEBUG, "Failed to retrieve scanner identity:\n")); + PDBG (bjnp_dbg (LOG_DEBUG, "get_scanner_id: ERROR - Failed to retrieve scanner identity:\n")); return -1; } - PDBG (bjnp_dbg (LOG_DEBUG2, "scanner identity:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "get_scanner_id: scanner identity:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); id = (struct IDENTITY *) resp_buf; - /* truncate string to be safe */ - id_len = htons( id-> id_len ) - sizeof(id->id_len); - id->id[id_len] = '\0'; - strcpy (scanner_id, id->id); - - PDBG (bjnp_dbg (LOG_INFO, "Scanner identity string = %s - lenght = %d\n", scanner_id, id_len)); + if (device[dev_no].protocol == PROTOCOL_BJNP) + { + id_len = MIN(ntohl( id-> cmd.payload_len ) - sizeof(id-> payload.bjnp.id_len), BJNP_IEEE1284_MAX); + strncpy(scanner_id, id->payload.bjnp.id, id_len); + scanner_id[id_len] = '\0'; + } + else + { + id_len = MIN(ntohl( id-> cmd.payload_len ), BJNP_IEEE1284_MAX); + strncpy(scanner_id, id->payload.mfnp.id, id_len); + scanner_id[id_len] = '\0'; + } + PDBG (bjnp_dbg (LOG_INFO, "get_scanner_id: Scanner identity string = %s - length = %d\n", scanner_id, id_len)); /* get make&model from IEEE1284 id */ if (model != NULL) { parse_IEEE1284_to_model (scanner_id, model); - PDBG (bjnp_dbg (LOG_INFO, "Scanner model = %s\n", model)); + PDBG (bjnp_dbg (LOG_INFO, "get_scanner_id: Scanner model = %s\n", model)); } return 0; } @@ -776,7 +834,7 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) if( (error = getnameinfo( &(scanner_sa -> addr) , sa_size( scanner_sa), host, BJNP_HOST_MAX , NULL, 0, NI_NAMEREQD) ) != 0 ) { - PDBG (bjnp_dbg(LOG_INFO, "Name for %s not found : %s\n", + PDBG (bjnp_dbg(LOG_INFO, "get_scanner_name: Name for %s not found : %s\n", ip_address, gai_strerror(error) ) ); strcpy(host, ip_address); return level; @@ -797,7 +855,7 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) { /* found match, good */ PDBG (bjnp_dbg (LOG_INFO, - "Forward lookup for %s succeeded, using as hostname\n", host)); + "get_scanner_name: Forward lookup for %s succeeded, using as hostname\n", host)); match = 1; level = BJNP_ADDRESS_HAS_FQDN; break; @@ -809,7 +867,7 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) if (match != 1) { PDBG (bjnp_dbg (LOG_INFO, - "Forward lookup for %s succeeded, IP-address does not match, using IP-address %s instead\n", + "get_scanner_name: Forward lookup for %s succeeded, IP-address does not match, using IP-address %s instead\n", host, ip_address)); strcpy (host, ip_address); } @@ -817,13 +875,30 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) else { /* forward lookup failed, use ip-address */ - PDBG ( bjnp_dbg (LOG_INFO, "Forward lookup of %s failed, using IP-address", ip_address)); + PDBG ( bjnp_dbg (LOG_INFO, "get_scanner_name: Forward lookup of %s failed, using IP-address", ip_address)); strcpy (host, ip_address); } } return level; } +static int +get_port_from_sa(const bjnp_sockaddr_t scanner_sa) +{ +#ifdef ENABLE_IPV6 + if ( scanner_sa.addr.sa_family == AF_INET6 ) + { + return ntohs(scanner_sa.ipv6.sin6_port); + } + else +#endif + if ( scanner_sa.addr.sa_family == AF_INET ) + { + return ntohs(scanner_sa.ipv4.sin_port); + } + return -1; +} + static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { int sockfd = -1; @@ -834,7 +909,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) if ((sockfd = socket (local_addr-> addr.sa_family, SOCK_DGRAM, 0)) == -1) { PDBG (bjnp_dbg - (LOG_CRIT, "create_broadcast_socket: can not open socket - %s", + (LOG_CRIT, "create_broadcast_socket: ERROR - can not open socket - %s", strerror (errno))); return -1; } @@ -847,7 +922,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { PDBG (bjnp_dbg (LOG_CRIT, - "create_broadcast_socket: setting socket option SO_BROADCAST failed - %s", + "create_broadcast_socket: ERROR - setting socket option SO_BROADCAST failed - %s", strerror (errno))); close (sockfd); return -1; @@ -860,7 +935,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { PDBG (bjnp_dbg (LOG_CRIT, - "create_broadcast_socket: setting socket option IPV6_V6ONLY failed - %s", + "create_broadcast_socket: ERROR - setting socket option IPV6_V6ONLY failed - %s", strerror (errno))); close (sockfd); return -1; @@ -872,7 +947,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { PDBG (bjnp_dbg (LOG_CRIT, - "create_broadcast_socket: bind socket to local address failed - %s\n", + "create_broadcast_socket: ERROR - bind socket to local address failed - %s\n", strerror (errno))); close (sockfd); return -1; @@ -900,7 +975,7 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, if ( local_sa == NULL ) { PDBG (bjnp_dbg (LOG_DEBUG, - "%s is not a valid IPv4 interface, skipping...\n", + "prepare_socket: %s is not a valid IPv4 interface, skipping...\n", if_name)); return -1; } @@ -919,7 +994,7 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, /* not a valid interface */ PDBG (bjnp_dbg (LOG_DEBUG, - "%s is not a valid IPv4 interface, skipping...\n", + "prepare_socket: %s is not a valid IPv4 interface, skipping...\n", if_name)); return -1; } @@ -928,15 +1003,18 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, /* send broadcasts to the broadcast address of the interface */ memcpy(dest_sa, broadcast_sa, sa_size(dest_sa) ); - dest_sa -> ipv4.sin_port = htons(BJNP_PORT_SCAN); + + /* we fill port when we send the broadcast */ + dest_sa -> ipv4.sin_port = htons(0); + if ( (socket = create_broadcast_socket( &local_sa_copy) ) != -1) { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv4 capable, sending broadcast, socket = %d\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: %s is IPv4 capable, sending broadcast, socket = %d\n", if_name, socket)); } else { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv4 capable, but failed to create a socket.\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: ERROR - %s is IPv4 capable, but failed to create a socket.\n", if_name)); return -1; } @@ -952,23 +1030,26 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, /* not a valid interface */ PDBG (bjnp_dbg (LOG_DEBUG, - "%s is not a valid IPv6 interface, skipping...\n", + "prepare_socket: %s is not a valid IPv6 interface, skipping...\n", if_name)); return -1; } else { dest_sa -> ipv6.sin6_family = AF_INET6; - dest_sa -> ipv6.sin6_port = htons(BJNP_PORT_SCAN); + + /* We fill port when we send the broadcast */ + dest_sa -> ipv6.sin6_port = htons(0); + inet_pton(AF_INET6, "ff02::1", dest_sa -> ipv6.sin6_addr.s6_addr); if ( (socket = create_broadcast_socket( &local_sa_copy ) ) != -1) { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv6 capable, sending broadcast, socket = %d\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: %s is IPv6 capable, sending broadcast, socket = %d\n", if_name, socket)); } else { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv6 capable, but failed to create a socket.\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: ERROR - %s is IPv6 capable, but failed to create a socket.\n", if_name)); return -1; } @@ -984,20 +1065,33 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, } static int -bjnp_send_broadcast (int sockfd, const bjnp_sockaddr_t * broadcast_addr, +bjnp_send_broadcast (int sockfd, const bjnp_sockaddr_t * broadcast_addr, int port, struct BJNP_command cmd, int size) { int num_bytes; + bjnp_sockaddr_t dest_addr; + + /* set address to send packet to broadcast address of interface, */ + /* with port set to the destination port */ - /* set address to send packet to */ - /* usebroadcast address of interface */ + memcpy(&dest_addr, broadcast_addr, sizeof(dest_addr)); + if( dest_addr.addr.sa_family == AF_INET) + { + dest_addr.ipv4.sin_port = htons(port); + } +#ifdef ENABLE_IPV6 + if( dest_addr.addr.sa_family == AF_INET6) + { + dest_addr.ipv6.sin6_port = htons(port); + } +#endif if ((num_bytes = sendto (sockfd, &cmd, size, 0, - &(broadcast_addr->addr), + &(dest_addr.addr), sa_size( broadcast_addr)) ) != size) { PDBG (bjnp_dbg (LOG_INFO, - "bjnp_send_broadcast: Socket: %d: sent only %x = %d bytes of packet, error = %s\n", + "bjnp_send_broadcast: Socket: %d: ERROR - sent only %x = %d bytes of packet, error = %s\n", sockfd, num_bytes, num_bytes, strerror (errno))); /* not allowed, skip this interface */ @@ -1017,9 +1111,9 @@ bjnp_finish_job (int devno) int resp_len; struct BJNP_command cmd; - set_cmd (devno, &cmd, CMD_UDP_CLOSE, 0); + set_cmd_for_dev (devno, &cmd, CMD_UDP_CLOSE, 0); - PDBG (bjnp_dbg (LOG_DEBUG2, "Finish scanjob\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_finish_job: Finish scanjob\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &cmd, sizeof (struct BJNP_command))); resp_len = @@ -1030,11 +1124,11 @@ bjnp_finish_job (int devno) { PDBG (bjnp_dbg (LOG_INFO, - "Received %d characters on close scanjob command, expected %d\n", + "bjnp_finish_job: ERROR - Received %d characters on close scanjob command, expected %d\n", resp_len, (int) sizeof (struct BJNP_command))); return; } - PDBG (bjnp_dbg (LOG_DEBUG2, "Finish scanjob response\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_finish_job: Finish scanjob response\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); } @@ -1101,11 +1195,11 @@ bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *s return -1; }; /* we can only now set the header as we now know the length of the payload */ - set_cmd (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_POLL, + set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_POLL, len); buf_len = len + sizeof(struct BJNP_command); - PDBG (bjnp_dbg (LOG_DEBUG2, "Poll details (type %d)\n", type)); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_poll_scanner: Poll details (type %d)\n", type)); PDBG (bjnp_hexdump (LOG_DEBUG2, cmd_buf, buf_len)); @@ -1113,7 +1207,7 @@ bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *s if (resp_len > 0) { - PDBG (bjnp_dbg (LOG_DEBUG2, "Poll details response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_poll_scanner: Poll details response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); response = (struct POLL_RESPONSE *) resp_buf; @@ -1126,7 +1220,7 @@ bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *s if ( (response -> result[2] & 0x80) != 0) { memcpy( status, response->status, size); - PDBG( bjnp_dbg(LOG_INFO, "received button status!\n")); + PDBG( bjnp_dbg(LOG_INFO, "bjnp_poll_scanner: received button status!\n")); PDBG (bjnp_hexdump( LOG_DEBUG2, status, size )); device[devno].status_key = ntohl( response -> key ); return size; @@ -1151,7 +1245,7 @@ bjnp_send_job_details (int devno, char *hostname, char *user, char *title) /* send job details command */ - set_cmd (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_JOB_DETAILS, + set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_JOB_DETAILS, sizeof (*job) - sizeof (struct BJNP_command)); /* create payload */ @@ -1162,7 +1256,7 @@ bjnp_send_job_details (int devno, char *hostname, char *user, char *title) charTo2byte (job->username, user, sizeof (job->username)); charTo2byte (job->jobtitle, title, sizeof (job->jobtitle)); - PDBG (bjnp_dbg (LOG_DEBUG2, "Job details\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_send_job_details: Job details\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, cmd_buf, (sizeof (struct BJNP_command) + sizeof (*job)))); @@ -1172,7 +1266,7 @@ bjnp_send_job_details (int devno, char *hostname, char *user, char *title) if (resp_len > 0) { - PDBG (bjnp_dbg (LOG_DEBUG2, "Job details response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_send_job_details: Job details response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); resp = (struct BJNP_command *) resp_buf; device[devno].session_id = ntohs (resp->session_id); @@ -1193,14 +1287,14 @@ bjnp_get_scanner_mac_address ( int devno, char *mac_address ) /* send job details command */ - set_cmd (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_DISCOVER, 0); + set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_DISCOVER, 0); resp_len = udp_command (devno, cmd_buf, sizeof (struct BJNP_command), resp_buf, BJNP_RESP_MAX); if (resp_len > 0) { - PDBG (bjnp_dbg (LOG_DEBUG2, "Discover response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_get_scanner_mac_address: Discover response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); u8tohex( mac_address, resp -> mac_addr, sizeof( resp -> mac_addr ) ); return 0; @@ -1212,7 +1306,7 @@ static int bjnp_write (int devno, const SANE_Byte * buf, size_t count) { /* - * This function writes scandata to the scanner. + * This function writes TCP data to the scanner. * Returns: number of bytes written to the scanner */ int sent_bytes; @@ -1220,14 +1314,15 @@ bjnp_write (int devno, const SANE_Byte * buf, size_t count) struct SCAN_BUF bjnp_buf; if (device[devno].scanner_data_left) - PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_write: ERROR: scanner data left = 0x%lx = %ld\n", - (unsigned long) device[devno].scanner_data_left, - (unsigned long) device[devno].scanner_data_left)); - + { + PDBG (bjnp_dbg + (LOG_CRIT, "bjnp_write: ERROR - scanner data left = 0x%lx = %ld\n", + (unsigned long) device[devno].scanner_data_left, + (unsigned long) device[devno].scanner_data_left)); + } /* set BJNP command header */ - set_cmd (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_SEND, count); + set_cmd_for_dev (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_SEND, count); memcpy (bjnp_buf.scan_data, buf, count); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_write: sending 0x%lx = %ld bytes\n", (unsigned long) count, (unsigned long) count); @@ -1241,7 +1336,7 @@ bjnp_write (int devno, const SANE_Byte * buf, size_t count) { /* return result from write */ terrno = errno; - PDBG (bjnp_dbg (LOG_CRIT, "bjnp_write: Could not send data!\n")); + PDBG (bjnp_dbg (LOG_CRIT, "bjnp_write: ERROR - Could not send data!\n")); errno = terrno; return sent_bytes; } @@ -1270,13 +1365,13 @@ bjnp_send_read_request (int devno) if (device[devno].scanner_data_left) PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_send_read_request: ERROR scanner data left = 0x%lx = %ld\n", + "bjnp_send_read_request: ERROR - scanner data left = 0x%lx = %ld\n", (unsigned long) device[devno].scanner_data_left, (unsigned long) device[devno].scanner_data_left)); /* set BJNP command header */ - set_cmd (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_REQ, 0); + set_cmd_for_dev (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_REQ, 0); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_send_read_req sending command\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &bjnp_buf, @@ -1289,7 +1384,7 @@ bjnp_send_read_request (int devno) /* return result from write */ terrno = errno; PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_send_read_request: Could not send data!\n")); + (LOG_CRIT, "bjnp_send_read_request: ERROR - Could not send data!\n")); errno = terrno; return -1; } @@ -1338,7 +1433,7 @@ bjnp_recv_header (int devno, size_t *payload_size ) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header: could not read response header (select): %s!\n", + "bjnp_recv_header: ERROR - could not read response header (select): %s!\n", strerror (terrno))); errno = terrno; return SANE_STATUS_IO_ERROR; @@ -1347,7 +1442,7 @@ bjnp_recv_header (int devno, size_t *payload_size ) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header: could not read response header (select timed out)!\n" ) ); + "bjnp_recv_header: ERROR - could not read response header (select timed out)!\n" ) ); errno = terrno; return SANE_STATUS_IO_ERROR; } @@ -1360,12 +1455,18 @@ bjnp_recv_header (int devno, size_t *payload_size ) 0)) != sizeof (struct BJNP_command)) { terrno = errno; - PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header: (recv) could not read response header, received %d bytes!\n", + if (recv_bytes == 0) + { + PDBG (bjnp_dbg (LOG_CRIT, + "bjnp_recv_header: ERROR - (recv) Scanner closed the TCP-connection!\n")); + } else { + PDBG (bjnp_dbg (LOG_CRIT, + "bjnp_recv_header: ERROR - (recv) could not read response header, received %d bytes!\n", recv_bytes)); - PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_recv_header: (recv) error: %s!\n", - strerror (terrno))); + PDBG (bjnp_dbg + (LOG_CRIT, "bjnp_recv_header: ERROR - (recv) error: %s!\n", + strerror (terrno))); + } errno = terrno; return SANE_STATUS_IO_ERROR; } @@ -1374,7 +1475,7 @@ bjnp_recv_header (int devno, size_t *payload_size ) { PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header:ERROR, Received response has cmd code %d, expected %d\n", + "bjnp_recv_header: ERROR - Received response has cmd code %d, expected %d\n", resp_buf.cmd_code, device[devno].last_cmd)); return SANE_STATUS_IO_ERROR; } @@ -1383,17 +1484,17 @@ bjnp_recv_header (int devno, size_t *payload_size ) { PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header:ERROR, Received response has serial %d, expected %d\n", + "bjnp_recv_header: ERROR - Received response has serial %d, expected %d\n", (int) ntohs (resp_buf.seq_no), (int) device[devno].serial)); return SANE_STATUS_IO_ERROR; } - /* got response header back, retrieve length of scanner data */ + /* got response header back, retrieve length of payload */ *payload_size = ntohl (resp_buf.payload_len); PDBG (bjnp_dbg - (LOG_DEBUG, "TCP response header(scanner data = %ld bytes):\n", + (LOG_DEBUG, "bjnp_recv_header: TCP response header(payload data = %ld bytes):\n", *payload_size) ); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &resp_buf, sizeof (struct BJNP_command))); @@ -1401,7 +1502,7 @@ bjnp_recv_header (int devno, size_t *payload_size ) } static int -bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa ) +bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa, bjnp_protocol_defs_t *protocol_defs) { /* initialize device structure */ @@ -1413,6 +1514,8 @@ bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa ) device[dn].dialog = 0; device[dn].status_key = 0; #endif + device[dn].protocol = protocol_defs->protocol_version; + device[dn].protocol_string = protocol_defs->proto_string; device[dn].tcp_socket = -1; device[dn].addr = (bjnp_sockaddr_t *) malloc(sizeof ( bjnp_sockaddr_t) ); @@ -1424,14 +1527,14 @@ bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa ) device[dn].bjnp_timeout = 0; device[dn].scanner_data_left = 0; device[dn].last_cmd = 0; - device[dn].blocksize = 2048; /* safe assumption, we start low */ + device[dn].blocksize = BJNP_BLOCKSIZE_START; device[dn].last_block = 0; /* fill mac_address */ if (bjnp_get_scanner_mac_address(dn, device[dn].mac_address) != 0 ) { PDBG (bjnp_dbg - (LOG_CRIT, "Cannot read mac address, skipping this scanner\n" ) ); + (LOG_CRIT, "bjnp_init_device_structure: Cannot read mac address, skipping this scanner\n" ) ); return -1; } return 0; @@ -1449,11 +1552,12 @@ bjnp_free_device_structure( int dn) } static SANE_Status -bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) +bjnp_recv_data (int devno, SANE_Byte * buffer, size_t start_pos, size_t * len) { /* - * This function receives the responses to the write commands. + * This function receives the payload data. * NOTE: len may not exceed SSIZE_MAX (as that is max for recv) + * len will be restricted to SSIZE_MAX to be sure * Returns: number of bytes of payload received from device */ @@ -1465,13 +1569,28 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) int fd; int attempt; - PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_recv_data: receiving response data\n")); - fd = device[devno].tcp_socket; - PDBG (bjnp_dbg - (LOG_DEBUG, "bjnp_recv_data: read response payload (%ld bytes max)\n", - (unsigned long) *len)); + (LOG_DEBUG, "bjnp_recv_data: read response payload (0x%lx bytes max), buffer: 0x%lx, start_pos: 0x%lx\n", + (long) *len, (long) buffer, (long) start_pos)); + + if (*len == 0) + { + /* nothing to do */ + PDBG (bjnp_dbg + (LOG_DEBUG, "bjnp_recv_data: Nothing to do (%ld bytes requested)\n", + (long) *len)); + return SANE_STATUS_GOOD; + } + else if ( *len > SSIZE_MAX ) + { + PDBG (bjnp_dbg + (LOG_DEBUG, "bjnp_recv_data: WARNING - requested block size (%ld) exceeds maximum, setting to maximum %ld\n", + (long)*len, SSIZE_MAX)); + *len = SSIZE_MAX; + } + + fd = device[devno].tcp_socket; attempt = 0; do { @@ -1488,7 +1607,7 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_data: could not read response payload (select): %s!\n", + "bjnp_recv_data: ERROR - could not read response payload (select failed): %s!\n", strerror (errno))); errno = terrno; *len = 0; @@ -1498,24 +1617,23 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_data: could not read response payload (select timed out): %s!\n", - strerror (terrno))); + "bjnp_recv_data: ERROR - could not read response payload (select timed out)!\n") ); errno = terrno; *len = 0; return SANE_STATUS_IO_ERROR; } - if ((recv_bytes = recv (fd, buffer, *len, 0)) < 0) + if ((recv_bytes = recv (fd, buffer + start_pos, *len, 0)) < 0) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_data: could not read response payload (recv): %s!\n", - strerror (errno))); + "bjnp_recv_data: ERROR - could not read response payload (%ld + %ld = %ld) (recv): %s!\n", + (long) buffer, (long) start_pos, (long) buffer + start_pos, strerror (errno))); errno = terrno; *len = 0; return SANE_STATUS_IO_ERROR; } - PDBG (bjnp_dbg (LOG_DEBUG2, "Received TCP response payload (%ld bytes):\n", + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_recv_data: Received TCP response payload (%ld bytes):\n", (unsigned long) recv_bytes)); PDBG (bjnp_hexdump (LOG_DEBUG2, buffer, recv_bytes)); @@ -1531,6 +1649,7 @@ bjnp_allocate_device (SANE_String_Const devname, char host[BJNP_HOST_MAX]; char port[BJNP_PORT_MAX] = ""; char args[BJNP_ARGS_MAX]; + bjnp_protocol_defs_t *protocol_defs; struct addrinfo *res, *cur; struct addrinfo hints; int result; @@ -1547,22 +1666,22 @@ bjnp_allocate_device (SANE_String_Const devname, { PDBG (bjnp_dbg (LOG_CRIT, - "URI may not contain userid, password or aguments: %s\n", + "bjnp_allocate_device: ERROR - URI may not contain userid, password or aguments: %s\n", devname)); return BJNP_STATUS_INVAL; } - if (strcmp (method, BJNP_METHOD) != 0) + if ( (protocol_defs = get_protocol_by_method(method)) == NULL) { PDBG (bjnp_dbg - (LOG_CRIT, "URI %s contains invalid method: %s\n", devname, + (LOG_CRIT, "bjnp_allocate_device: ERROR - URI %s contains invalid method: %s\n", devname, method)); return BJNP_STATUS_INVAL; } if (strlen(port) == 0) { - sprintf( port, "%d", BJNP_PORT_SCAN ); + sprintf( port, "%d", protocol_defs->default_port ); } hints.ai_flags = 0; @@ -1581,7 +1700,7 @@ bjnp_allocate_device (SANE_String_Const devname, result = getaddrinfo (host, port, &hints, &res ); if (result != 0 ) { - PDBG (bjnp_dbg (LOG_CRIT, "Cannot resolve host: %s port %s\n", host, port)); + PDBG (bjnp_dbg (LOG_CRIT, "bjnp_allocate_device: ERROR - Cannot resolve host: %s port %s\n", host, port)); return SANE_STATUS_INVAL; } @@ -1596,12 +1715,13 @@ bjnp_allocate_device (SANE_String_Const devname, { PDBG (bjnp_dbg (LOG_CRIT, - "Too many devices, ran out of device structures, can not add %s\n", + "bjnp_allocate_device: WARNING - Too many devices, ran out of device structures, can not add %s\n", devname)); freeaddrinfo(res); return BJNP_STATUS_INVAL; } - if (bjnp_init_device_structure( bjnp_no_devices, (bjnp_sockaddr_t *)cur -> ai_addr) != 0) + if (bjnp_init_device_structure( bjnp_no_devices, (bjnp_sockaddr_t *)cur -> ai_addr, + protocol_defs) != 0) { /* giving up on this address, try next one if any */ break; @@ -1632,7 +1752,7 @@ bjnp_allocate_device (SANE_String_Const devname, } freeaddrinfo(res); - PDBG (bjnp_dbg (LOG_INFO, "Scanner not yet in our list, added it: %s:%s\n", host, port)); + PDBG (bjnp_dbg (LOG_INFO, "bjnp_allocate_device: Scanner not yet in our list, added it: %s:%s\n", host, port)); /* return hostname if required */ @@ -1670,7 +1790,7 @@ static void add_scanner(SANE_Int *dev_no, case BJNP_STATUS_GOOD: if (get_scanner_id (*dev_no, makemodel) != 0) { - PDBG (bjnp_dbg (LOG_CRIT, "Cannot read scanner make & model: %s\n", + PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: ERROR - Cannot read scanner make & model: %s\n", uri)); } else @@ -1685,12 +1805,12 @@ static void add_scanner(SANE_Int *dev_no, } break; case BJNP_STATUS_ALREADY_ALLOCATED: - PDBG (bjnp_dbg (LOG_NOTICE, "Scanner at %s was added before, good!\n", + PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: Scanner at %s was added before, good!\n", uri)); break; case BJNP_STATUS_INVAL: - PDBG (bjnp_dbg (LOG_NOTICE, "Scanner at %s can not be added\n", + PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: Scanner at %s can not be added\n", uri)); break; } @@ -1738,6 +1858,7 @@ sanei_bjnp_find_devices (const char **conf_devices, int socket_fd[BJNP_SOCK_MAX]; int no_sockets; int i; + int j; int attempt; int last_socketfd = 0; fd_set fdset; @@ -1746,9 +1867,11 @@ sanei_bjnp_find_devices (const char **conf_devices, char scanner_host[256]; char uri[256]; int dev_no; + int port; bjnp_sockaddr_t broadcast_addr[BJNP_SOCK_MAX]; bjnp_sockaddr_t scanner_sa; socklen_t socklen; + bjnp_protocol_defs_t *protocol_defs; memset( broadcast_addr, 0, sizeof( broadcast_addr) ); memset( &scanner_sa, 0 ,sizeof( scanner_sa ) ); @@ -1762,24 +1885,23 @@ sanei_bjnp_find_devices (const char **conf_devices, /* First add devices from config file */ if (conf_devices[0] == NULL) - PDBG (bjnp_dbg( LOG_DEBUG, "No devices specified in configuration file.\n" ) ); + PDBG (bjnp_dbg( LOG_DEBUG, "sanei_bjnp_find_devices: No devices specified in configuration file.\n" ) ); for (i = 0; conf_devices[i] != NULL; i++) { PDBG (bjnp_dbg - (LOG_DEBUG, "Adding scanner from pixma.conf: %s\n", conf_devices[i])); + (LOG_DEBUG, "sanei_bjnp_find_devices: Adding scanner from pixma.conf: %s\n", conf_devices[i])); add_scanner(&dev_no, conf_devices[i], attach_bjnp, pixma_devices); } PDBG (bjnp_dbg (LOG_DEBUG, - "Added all configured scanners, now do auto detection...\n")); + "sanei_bjnp_find_devices: Added all configured scanners, now do auto detection...\n")); /* * Send UDP DISCOVER to discover scanners and return the list of scanners found */ FD_ZERO (&fdset); - set_cmd (-1, &cmd, CMD_UDP_DISCOVER, 0); no_sockets = 0; #ifdef HAVE_IFADDRS_H @@ -1824,7 +1946,7 @@ sanei_bjnp_find_devices (const char **conf_devices, local.ipv4.sin_addr.s_addr = htonl (INADDR_ANY); bc_addr.ipv4.sin_family = AF_INET; - bc_addr.ipv4.sin_port = htons(BJNP_PORT_SCAN); + bc_addr.ipv4.sin_port = htons(0); bc_addr.ipv4.sin_addr.s_addr = htonl (INADDR_BROADCAST); socket_fd[no_sockets] = prepare_socket( "any_interface", @@ -1866,7 +1988,14 @@ sanei_bjnp_find_devices (const char **conf_devices, { for ( i=0; i < no_sockets; i++) { - bjnp_send_broadcast ( socket_fd[i], &broadcast_addr[i], cmd, sizeof (cmd)); + j = 0; + while(bjnp_protocol_defs[j].protocol_version != PROTOCOL_NONE) + { + set_cmd_from_string (bjnp_protocol_defs[j].proto_string, &cmd, CMD_UDP_DISCOVER, 0); + bjnp_send_broadcast ( socket_fd[i], &broadcast_addr[i], + bjnp_protocol_defs[j].default_port, cmd, sizeof (cmd)); + j++; + } } /* wait for some time between broadcast packets */ usleep (BJNP_BROADCAST_INTERVAL * BJNP_USLEEP_MS); @@ -1882,7 +2011,7 @@ sanei_bjnp_find_devices (const char **conf_devices, while (select (last_socketfd + 1, &active_fdset, NULL, NULL, &timeout) > 0) { - PDBG (bjnp_dbg (LOG_DEBUG, "Select returned, time left %d.%d....\n", + PDBG (bjnp_dbg (LOG_DEBUG, "sanei_bjnp_find_devices: Select returned, time left %d.%d....\n", (int) timeout.tv_sec, (int) timeout.tv_usec)); for (i = 0; i < no_sockets; i++) { @@ -1894,17 +2023,18 @@ sanei_bjnp_find_devices (const char **conf_devices, &(scanner_sa.addr), &socklen ) ) == -1) { PDBG (bjnp_dbg - (LOG_INFO, "find_devices: no data received")); + (LOG_INFO, "sanei_find_devices: no data received")); break; } else { - PDBG (bjnp_dbg (LOG_DEBUG2, "Discover response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "sanei_find_devices: Discover response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, &resp_buf, numbytes)); /* check if something sensible is returned */ + protocol_defs = get_protocol_by_proto_string(disc_resp-> response.BJNP_id); if ( (numbytes < (int)sizeof (struct BJNP_command)) || - (strncmp ("BJNP", disc_resp-> response.BJNP_id, 4) != 0)) + (protocol_defs == NULL)) { /* not a valid response, assume not a scanner */ @@ -1912,11 +2042,11 @@ sanei_bjnp_find_devices (const char **conf_devices, strncpy(bjnp_id, disc_resp-> response.BJNP_id, 4); bjnp_id[4] = '\0'; PDBG (bjnp_dbg (LOG_INFO, - "Invalid discover response! Length = %d, Id = %s\n", + "sanei_find_devices: Invalid discover response! Length = %d, Id = %s\n", numbytes, bjnp_id ) ); break; } - if ( ! ((disc_resp -> response.dev_type) & 0x80) ) + if ( !(disc_resp -> response.dev_type & 0x80) ) { /* not a response, a command from somebody else or */ /* a discover command that we generated */ @@ -1924,12 +2054,13 @@ sanei_bjnp_find_devices (const char **conf_devices, } }; + port = get_port_from_sa(scanner_sa); /* scanner found, get IP-address or hostname */ get_scanner_name( &scanner_sa, scanner_host); /* construct URI */ - sprintf (uri, "%s://%s:%d", BJNP_METHOD, scanner_host, - BJNP_PORT_SCAN); + sprintf (uri, "%s://%s:%d", protocol_defs->method_string, scanner_host, + port); add_scanner( &dev_no, uri, attach_bjnp, pixma_devices); @@ -1939,7 +2070,7 @@ sanei_bjnp_find_devices (const char **conf_devices, timeout.tv_sec = 0; timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * BJNP_USLEEP_MS; } - PDBG (bjnp_dbg (LOG_DEBUG, "scanner discovery finished...\n")); + PDBG (bjnp_dbg (LOG_DEBUG, "sanei_find_devices: scanner discovery finished...\n")); for (i = 0; i < no_sockets; i++) close (socket_fd[i]); @@ -1979,8 +2110,6 @@ sanei_bjnp_open (SANE_String_Const devname, SANE_Int * dn) result = bjnp_allocate_device (devname, dn, NULL); if ( (result != BJNP_STATUS_GOOD) && (result != BJNP_STATUS_ALREADY_ALLOCATED ) ) return SANE_STATUS_INVAL; - - return sanei_bjnp_activate( *dn);; } /** Close a BJNP device. @@ -1992,8 +2121,9 @@ void sanei_bjnp_close (SANE_Int dn) { PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_close(%d):\n", dn)); - sanei_bjnp_deactivate(dn); + device[dn].open = 0; + sanei_bjnp_deactivate(dn); } /** Activate BJNP device connection @@ -2008,7 +2138,6 @@ sanei_bjnp_activate (SANE_Int dn) char pid_str[64]; PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_activate (%d)\n", dn)); - gethostname (hostname, 256); hostname[255] = '\0'; sprintf (pid_str, "Process ID = %d", getpid ()); @@ -2032,11 +2161,9 @@ SANE_Status sanei_bjnp_deactivate (SANE_Int dn) { PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_deactivate (%d)\n", dn)); - - bjnp_finish_job (dn); - if ( device[dn].tcp_socket != -1) { + bjnp_finish_job (dn); close (device[dn].tcp_socket); device[dn].tcp_socket = -1; } @@ -2079,12 +2206,13 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) SANE_Status result; SANE_Status error; size_t recvd; - size_t more; + size_t read_size; + size_t read_size_max; size_t requested; PDBG (bjnp_dbg - (LOG_INFO, "bjnp_read_bulk(%d, bufferptr, 0x%lx = %ld)\n", dn, - (unsigned long) *size, (unsigned long) *size)); + (LOG_INFO, "bjnp_read_bulk(dn=%d, bufferptr=%lx, 0x%lx = %ld)\n", dn, + (long) buffer, (unsigned long) *size, (unsigned long) *size)); recvd = 0; requested = *size; @@ -2095,20 +2223,21 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) (unsigned long) device[dn].scanner_data_left ) ); while ( (recvd < requested) && !( device[dn].last_block && (device[dn].scanner_data_left == 0)) ) - { PDBG (bjnp_dbg (LOG_DEBUG, - "Received 0x%lx = %ld bytes, backend requested 0x%lx = %ld bytes\n", + "bjnp_read_bulk: Already received 0x%lx = %ld bytes, backend requested 0x%lx = %ld bytes\n", (unsigned long) recvd, (unsigned long) recvd, (unsigned long) requested, (unsigned long)requested )); + /* Check first if there is data in flight from the scanner */ + if (device[dn].scanner_data_left == 0) { - /* send new read request */ + /* There is no data in flight from the scanner, send new read request */ PDBG (bjnp_dbg (LOG_DEBUG, - "No (more) scanner data available, requesting more( blocksize = %ld =%lx\n", + "bjnp_read_bulk: No (more) scanner data available, requesting more( blocksize = %ld = %lx\n", (long int) device[dn].blocksize, (long int) device[dn].blocksize )); if ((error = bjnp_send_read_request (dn)) != SANE_STATUS_GOOD) @@ -2133,43 +2262,40 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) device[dn].last_block = 1; } - if ( device[dn].scanner_data_left == 0 ) - { - break; - } } - PDBG (bjnp_dbg (LOG_DEBUG, "Scanner reports 0x%lx = %ld bytes available\n", + PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: In flight: 0x%lx = %ld bytes available\n", (unsigned long) device[dn].scanner_data_left, (unsigned long) device[dn].scanner_data_left)); - /* read as many bytes as needed and available */ + /* read as many bytes as needed and available */ - more = MIN( device[dn].scanner_data_left, (requested - recvd) ); + read_size_max = MIN( device[dn].scanner_data_left, (requested - recvd) ); + read_size = read_size_max; PDBG (bjnp_dbg (LOG_DEBUG, - "reading 0x%lx = %ld (of max 0x%lx = %ld) bytes\n", - (unsigned long) more, - (unsigned long) more, + "bjnp_read_bulk: Try to read 0x%lx = %ld (of max 0x%lx = %ld) bytes\n", + (unsigned long) read_size_max, + (unsigned long) read_size_max, (unsigned long) device[dn].scanner_data_left, (unsigned long) device[dn].scanner_data_left) ); - result = bjnp_recv_data (dn, buffer + recvd, &more); + result = bjnp_recv_data (dn, buffer , recvd, &read_size); if (result != SANE_STATUS_GOOD) { *size = recvd; return SANE_STATUS_IO_ERROR; } - PDBG (bjnp_dbg (LOG_DEBUG, "Requested %ld bytes, received: %ld\n", - MIN( device[dn].scanner_data_left, (requested - recvd) ), more) ); + PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: Expected at most %ld bytes, received this time: %ld\n", + read_size_max, read_size) ); - device[dn].scanner_data_left = device[dn].scanner_data_left - more; - recvd = recvd + more; + device[dn].scanner_data_left = device[dn].scanner_data_left - read_size; + recvd = recvd + read_size; } - PDBG (bjnp_dbg (LOG_DEBUG, "returning %ld bytes, backend expexts %ld\n", - recvd, *size ) ); + PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: %s: Returning %ld bytes, backend expexts %ld\n", + (recvd == *size)? "OK": "NOTICE",recvd, *size ) ); *size = recvd; if ( *size == 0 ) return SANE_STATUS_EOF; @@ -2199,51 +2325,50 @@ sanei_bjnp_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) uint32_t buf; size_t payload_size; - PDBG (bjnp_dbg - (LOG_INFO, "bjnp_write_bulk(%d, bufferptr, 0x%lx = %ld)\n", dn, - (unsigned long) *size, (unsigned long) *size)); + /* Write received data to scanner */ + sent = bjnp_write (dn, buffer, *size); if (sent < 0) return SANE_STATUS_IO_ERROR; if (sent != (int) *size) { PDBG (bjnp_dbg - (LOG_CRIT, "Sent only %ld bytes to scanner, expected %ld!!\n", + (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Sent only %ld bytes to scanner, expected %ld!!\n", (unsigned long) sent, (unsigned long) *size)); return SANE_STATUS_IO_ERROR; } if (bjnp_recv_header (dn, &payload_size) != SANE_STATUS_GOOD) { - PDBG (bjnp_dbg (LOG_CRIT, "Could not read response to command!\n")); + PDBG (bjnp_dbg (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Could not read response to command!\n")); return SANE_STATUS_IO_ERROR; } if (payload_size != 4) { PDBG (bjnp_dbg (LOG_CRIT, - "Scanner length of write confirmation = 0x%lx bytes = %ld, expected %d!!\n", + "sanei_bjnp_write_bulk: ERROR - Scanner length of write confirmation = 0x%lx bytes = %ld, expected %d!!\n", (unsigned long) payload_size, (unsigned long) payload_size, 4)); return SANE_STATUS_IO_ERROR; } recvd = payload_size; - if ((bjnp_recv_data (dn, (unsigned char *) &buf, &recvd) != + if ((bjnp_recv_data (dn, (unsigned char *) &buf, 0, &recvd) != SANE_STATUS_GOOD) || (recvd != payload_size)) { PDBG (bjnp_dbg (LOG_CRIT, - "Could not read length of data confirmed by device\n")); + "sanei_bjnp_write_bulk: ERROR - Could not read length of data confirmed by device\n")); return SANE_STATUS_IO_ERROR; } recvd = ntohl (buf); if (recvd != *size) { PDBG (bjnp_dbg - (LOG_CRIT, "Scanner confirmed %ld bytes, expected %ld!!\n", + (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Scanner confirmed %ld bytes, expected %ld!!\n", (unsigned long) recvd, (unsigned long) *size)); return SANE_STATUS_IO_ERROR; } - /* we can expect data from the scanner again */ + /* we can expect data from the scanner */ device[dn].last_block = 0; @@ -2304,13 +2429,15 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) if ( (bjnp_poll_scanner (dn, 0, hostname, getusername (), buffer, *size ) != 0) || (bjnp_poll_scanner (dn, 1, hostname, getusername (), buffer, *size ) != 0) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Failed to setup read_intr dialog with device!\n")); + PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: WARNING - Failed to setup read_intr dialog with device!\n")); device[dn].dialog = 0; device[dn].status_key = 0; return SANE_STATUS_IO_ERROR; } device[dn].polling_status = BJNP_POLL_STARTED; + /* fall through to BJNP_POLL_STARTED */ + case BJNP_POLL_STARTED: /* we use only seonds accuracy between poll attempts */ timeout = device[dn].bjnp_timeout /1000; @@ -2319,7 +2446,7 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) { if ( (resp_len = bjnp_poll_scanner (dn, 2, hostname, getusername (), buffer, *size ) ) < 0 ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Restarting polling dialog!\n")); + PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: Restarting polling dialog!\n")); device[dn].polling_status = BJNP_POLL_STOPPED; *size = 0; return SANE_STATUS_EOF; @@ -2332,8 +2459,11 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) /* this is a bit of a hack, but the scanner does not like */ /* us to continue using the existing tcp socket */ + /* No longer required? Does not work anymore now we moved code from sanei_bjnp_activate/sanei_bjnp_deactivate + to the isanei_bjnp_open and sanei_bjnp_close sanei_bjnp_deactivate(dn); sanei_bjnp_activate(dn); + */ return SANE_STATUS_GOOD; } @@ -2345,7 +2475,7 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) case BJNP_POLL_STATUS_RECEIVED: if ( (resp_len = bjnp_poll_scanner (dn, 5, hostname, getusername (), buffer, *size ) ) < 0 ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Restarting polling dialog!\n")); + PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: Restarting polling dialog!\n")); device[dn].polling_status = BJNP_POLL_STOPPED; *size = 0; break; diff --git a/backend/pixma_bjnp.h b/backend/pixma_bjnp.h index e2939d7..3770bfd 100644 --- a/backend/pixma_bjnp.h +++ b/backend/pixma_bjnp.h @@ -96,7 +96,7 @@ sanei_bjnp_find_devices (const char **conf_devices, * Where: * method = bjnp * hostname = resolvable name or IP-address - * port = 8612 for a scanner + * port = 8612 for a bjnp scanner, 8610 for a mfnp device * An example could look like this: bjnp://host.domain:8612 * * @param devname name of the device to open diff --git a/backend/pixma_bjnp_private.h b/backend/pixma_bjnp_private.h index 859baa5..1902c7a 100644 --- a/backend/pixma_bjnp_private.h +++ b/backend/pixma_bjnp_private.h @@ -75,6 +75,7 @@ #define BJNP_SERIAL_MAX 16 /* maximum length of serial number */ #define BJNP_NO_DEVICES 16 /* max number of open devices */ #define BJNP_SCAN_BUF_MAX 65536 /* size of scanner data intermediate buffer */ +#define BJNP_BLOCKSIZE_START 512 /* startsize for last block detection */ /* timers */ #define BJNP_BROADCAST_INTERVAL 10 /* ms between broadcasts */ @@ -109,15 +110,34 @@ /* port numbers */ typedef enum bjnp_port_e { - BJNP_PORT_BROADCAST_BASE = 8610, + MFNP_PORT_SCAN = 8610, BJNP_PORT_PRINT = 8611, BJNP_PORT_SCAN = 8612, BJNP_PORT_3 = 8613, BJNP_PORT_4 = 8614 } bjnp_port_t; -#define BJNP_METHOD "bjnp" -#define BJNP_STRING "BJNP" +typedef enum +{ + PROTOCOL_BJNP = 0, + PROTOCOL_MFNP = 1, + PROTOCOL_NONE =2 +} bjnp_protocol_t; + +typedef struct +{ + bjnp_protocol_t protocol_version; + int default_port; + char * proto_string; + char * method_string; +} bjnp_protocol_defs_t; + +bjnp_protocol_defs_t bjnp_protocol_defs[] = +{ + {PROTOCOL_BJNP, BJNP_PORT_SCAN,"BJNP", "bjnp"}, + {PROTOCOL_MFNP, MFNP_PORT_SCAN,"MFNP", "mfnp"}, + {PROTOCOL_NONE, -1, NULL, NULL} +}; /* commands */ typedef enum bjnp_cmd_e @@ -168,7 +188,7 @@ struct __attribute__ ((__packed__)) DISCOVER_RESPONSE struct BJNP_command response; /* reponse header */ char unknown1[4]; /* 00 01 08 00 */ char mac_len; /* length of mac address */ - char addr_len; /* length od address field */ + char addr_len; /* length of address field */ unsigned char mac_addr[6]; /* printers mac address */ union { struct __attribute__ ((__packed__)) { @@ -251,8 +271,18 @@ struct __attribute__ ((__packed__)) POLL_RESPONSE struct __attribute__ ((__packed__)) IDENTITY { struct BJNP_command cmd; - uint16_t id_len; /* length of identity */ - char id[BJNP_IEEE1284_MAX]; /* identity */ + union __attribute__ ((__packed__)) + { + struct __attribute__ ((__packed__)) payload_s + { + uint16_t id_len; /* length of identity */ + char id[BJNP_IEEE1284_MAX]; /* identity */ + } bjnp; + struct __attribute__ ((__packed__)) mfnp + { + char id[BJNP_IEEE1284_MAX]; + } mfnp; + } payload; }; @@ -314,6 +344,10 @@ typedef enum typedef struct device_s { int open; /* connection to scanner is opened */ + + /* protocol version */ + int protocol; + char *protocol_string; /* sockets */ diff --git a/backend/pixma_common.c b/backend/pixma_common.c index b417d07..771a5af 100644 --- a/backend/pixma_common.c +++ b/backend/pixma_common.c @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. @@ -318,7 +318,7 @@ pixma_get_time (time_t * sec, uint32_t * usec) uint8_t * pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c) { - unsigned i, j, g; + unsigned i; /* PDBG (pixma_dbg (4, "*pixma_rgb_to_ir*****\n")); */ @@ -655,7 +655,10 @@ pixma_cmd_transaction (pixma_t * s, const void *cmd, unsigned cmdlen, { error = pixma_read (s->io, data, expected_len); if (error == PIXMA_ETIMEDOUT) + { PDBG (pixma_dbg (2, "No response yet. Timed out in %d sec.\n", tmo)); + pixma_sleep (1000000); /* 1s timeout */ + } } while (error == PIXMA_ETIMEDOUT && --tmo != 0); if (error < 0) @@ -1048,9 +1051,11 @@ pixma_check_scan_param (pixma_t * s, pixma_scan_param_t * sp) if (s->ops->check_param (s, sp) < 0) return PIXMA_EINVAL; - /* FIXME: I assume the same minimum width and height for every model. */ - CLAMP2 (sp->x, sp->w, 13, s->cfg->width, sp->xdpi); - CLAMP2 (sp->y, sp->h, 8, s->cfg->height, sp->ydpi); + /* FIXME: I assume the same minimum width and height for every model. + * new scanners need minimum 16 px height + * minimum image size: 16 px x 16 px */ + CLAMP2 (sp->x, sp->w, 16, s->cfg->width, sp->xdpi); + CLAMP2 (sp->y, sp->h, 16, s->cfg->height, sp->ydpi); switch (sp->source) { diff --git a/backend/pixma_common.h b/backend/pixma_common.h index 86d459f..55ab570 100644 --- a/backend/pixma_common.h +++ b/backend/pixma_common.h @@ -1,7 +1,7 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. diff --git a/backend/pixma_imageclass.c b/backend/pixma_imageclass.c index c0287a3..b2526fa 100644 --- a/backend/pixma_imageclass.c +++ b/backend/pixma_imageclass.c @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2007-2009 Nicolas Martin, Copyright (C) 2008 Dennis Lou, dlou 99 at yahoo dot com - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. @@ -64,24 +64,29 @@ # define UNUSED(v) #endif -#define IMAGE_BLOCK_SIZE (0xffff) +#define IMAGE_BLOCK_SIZE (0x80000) #define MAX_CHUNK_SIZE (0x1000) #define MIN_CHUNK_SIZE (0x0200) #define CMDBUF_SIZE 512 -#define MF4200_PID 0x26b5 #define MF4100_PID 0x26a3 #define MF4600_PID 0x26b0 #define MF4010_PID 0x26b4 +#define MF4200_PID 0x26b5 #define MF4360_PID 0x26ec #define D480_PID 0x26ed #define MF4320_PID 0x26ee #define D420_PID 0x26ef #define MF3200_PID 0x2684 #define MF6500_PID 0x2686 +/* generation 2 scanners (>=0x2707) */ +#define MF4500_PID 0x2736 #define MF4410_PID 0x2737 #define MF3010_PID 0x2759 -#define MF4770_PID 0x2774 +#define MF4570_PID 0x275a +#define MF4800_PID 0x2773 +#define MF4700_PID 0x2774 +#define MF8200_PID 0x2779 /* the following are all untested */ #define MF5630_PID 0x264e #define MF5650_PID 0x264f @@ -89,9 +94,9 @@ #define MF5880_PID 0x26f9 #define MF6680_PID 0x26fa #define MF8030_PID 0x2707 -#define MF4550_PID 0x2736 -#define MF4570_PID 0x275a #define IR1133_PID 0x2742 +#define D530_PID 0x2775 +#define MF8500_PID 0x277a enum iclass_state_t @@ -280,16 +285,10 @@ request_image_block (pixma_t * s, unsigned flag, uint8_t * info, const int hlen = 2 + 6; memset (mf->cb.buf, 0, 11); - pixma_set_be16 (((s->cfg->pid == MF3010_PID || - s->cfg->pid == MF4410_PID || - s->cfg->pid == MF4770_PID || - s->cfg->pid == MF4550_PID) ? cmd_read_image2 : cmd_read_image), mf->cb.buf); + pixma_set_be16 (((mf->generation >= 2) ? cmd_read_image2 : cmd_read_image), mf->cb.buf); mf->cb.buf[8] = flag; mf->cb.buf[10] = 0x06; - expected_len = (s->cfg->pid == MF3010_PID || - s->cfg->pid == MF4410_PID || - s->cfg->pid == MF4770_PID || - s->cfg->pid == MF4550_PID || + expected_len = (mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) ? 512 : hlen; @@ -300,10 +299,7 @@ request_image_block (pixma_t * s, unsigned flag, uint8_t * info, *size = pixma_get_be16 (mf->cb.buf + 6); /* 16bit size */ error = 0; - if (s->cfg->pid == MF3010_PID || - s->cfg->pid == MF4410_PID || - s->cfg->pid == MF4770_PID || - s->cfg->pid == MF4550_PID || + if (mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) @@ -312,6 +308,7 @@ request_image_block (pixma_t * s, unsigned flag, uint8_t * info, *size = (*datalen + hlen == 512) ? pixma_get_be32 (mf->cb.buf + 4) - *datalen : 0; memcpy (data, mf->cb.buf + hlen, *datalen); } + PDBG (pixma_dbg (11, "*request_image_block***** size = %u *****\n", *size)); } else { @@ -323,13 +320,11 @@ request_image_block (pixma_t * s, unsigned flag, uint8_t * info, static int read_image_block (pixma_t * s, uint8_t * data, unsigned size) { + iclass_t *mf = (iclass_t *) s->subdriver; int error; unsigned maxchunksize, chunksize, count = 0; - maxchunksize = MAX_CHUNK_SIZE * ((s->cfg->pid == MF3010_PID || - s->cfg->pid == MF4410_PID || - s->cfg->pid == MF4770_PID || - s->cfg->pid == MF4550_PID || + maxchunksize = MAX_CHUNK_SIZE * ((mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) ? 4 : 1); @@ -514,7 +509,10 @@ 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 == MF4770_PID )) + && ( s->cfg->pid == MF4700_PID || + s->cfg->pid == MF4800_PID || + s->cfg->pid == MF8200_PID || + s->cfg->pid == MF8500_PID)) sp->h = MIN (sp->h, 877 * sp->xdpi / 75); return 0; @@ -651,10 +649,7 @@ iclass_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) if (n != 0) { if (s->param->channels != 1 && - s->cfg->pid != MF3010_PID && - s->cfg->pid != MF4410_PID && - s->cfg->pid != MF4770_PID && - s->cfg->pid != MF4550_PID && + mf->generation == 1 && s->cfg->pid != MF4600_PID && s->cfg->pid != MF6500_PID && s->cfg->pid != MF8030_PID) @@ -706,10 +701,15 @@ iclass_finish_scan (pixma_t * s) activate (s, 0); query_status (s); } - /* 0x38 = last block and ADF empty - * 0x28 = last block and Paper in ADF */ - if (mf->last_block==0x38 /* ADF empty */ - || (mf->generation == 1 && mf->last_block == 0x28)) /* generation 1 scanner or Paper in ADF */ + /* generation = 1: + * 0x28 = last block (no multi page scan) + * generation >= 2: + * 0x38 = last block and ADF empty (generation >= 2) + * 0x28 = last block and Paper in ADF (multi page scan) + * some generation 2 scanners don't use 0x38 for ADF empty => check status */ + if (mf->last_block==0x38 /* generation 2 scanner ADF empty */ + || (mf->generation == 1 && mf->last_block == 0x28) /* generation 1 scanner last block */ + || (mf->generation >= 2 && !has_paper(s))) /* check status: no paper in ADF */ { PDBG (pixma_dbg (3, "*iclass_finish_scan***** abort session *****\n")); abort_session (s); @@ -759,41 +759,46 @@ static const pixma_scan_ops_t pixma_iclass_ops = { iclass_get_status }; -#define DEV(name, model, pid, dpi, w, h, cap) { \ +#define DEV(name, model, pid, dpi, adftpu_max_dpi, w, h, cap) { \ name, /* name */ \ model, /* model */ \ 0x04a9, pid, /* vid pid */ \ 1, /* iface */ \ &pixma_iclass_ops, /* ops */ \ dpi, dpi, /* xdpi, ydpi */ \ - 0, 0, /* adftpu_min_dpi & adftpu_max_dpi not used in this subdriver */ \ + 0, /* adftpu_min_dpi not used in this subdriver */ \ + adftpu_max_dpi, /* adftpu_max_dpi */ \ 0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \ w, h, /* width, height */ \ PIXMA_CAP_GRAY|PIXMA_CAP_EVENTS|cap \ } const pixma_config_t pixma_iclass_devices[] = { - DEV ("Canon imageCLASS MF4270", "MF4270", MF4200_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon imageCLASS MF4150", "MF4100", MF4100_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon imageCLASS MF4690", "MF4690", MF4600_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon imageCLASS D420", "D420", D420_PID, 600, 640, 877, PIXMA_CAP_ADFDUP), - DEV ("Canon imageCLASS D480", "D480", D480_PID, 600, 640, 877, PIXMA_CAP_ADFDUP), - DEV ("Canon imageCLASS MF4360", "MF4360", MF4360_PID, 600, 640, 877, PIXMA_CAP_ADFDUP), - DEV ("Canon imageCLASS MF4320", "MF4320", MF4320_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon imageCLASS MF4010", "MF4010", MF4010_PID, 600, 640, 877, 0), - DEV ("Canon imageCLASS MF3240", "MF3240", MF3200_PID, 600, 640, 877, 0), - DEV ("Canon imageClass MF6500", "MF6500", MF6500_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon imageCLASS MF4410", "MF4410", MF4410_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon i-SENSYS MF4550d", "MF4550", MF4550_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon i-SENSYS MF3010", "MF3010", MF3010_PID, 600, 640, 877, 0), - DEV ("Canon imageCLASS MF4770n", "MF4770", MF4770_PID, 600, 640, 1050, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS MF4270", "MF4270", MF4200_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS MF4150", "MF4100", MF4100_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS MF4690", "MF4690", MF4600_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS D420", "D420", D420_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), + DEV ("Canon imageCLASS D480", "D480", D480_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), + DEV ("Canon imageCLASS MF4360", "MF4360", MF4360_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), + DEV ("Canon imageCLASS MF4320", "MF4320", MF4320_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS MF4010", "MF4010", MF4010_PID, 600, 0, 640, 877, 0), + DEV ("Canon imageCLASS MF3240", "MF3240", MF3200_PID, 600, 0, 640, 877, 0), + DEV ("Canon imageClass MF6500", "MF6500", MF6500_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS MF4410", "MF4410", MF4410_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon i-SENSYS MF4500 Series", "MF4500", MF4500_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon i-SENSYS MF3010", "MF3010", MF3010_PID, 600, 0, 640, 877, 0), + DEV ("Canon i-SENSYS MF4700 Series", "MF4700", MF4700_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), + DEV ("Canon i-SENSYS MF4800 Series", "MF4800", MF4800_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS MF4570dw", "MF4570dw", MF4570_PID, 600, 0, 640, 877, 0), + DEV ("Canon i-SENSYS MF8200C Series", "MF8200C", MF8200_PID, 600, 300, 640, 1050, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS D530", "D530", D530_PID, 600, 0, 640, 877, 0), /* FIXME: the following capabilities all need updating/verifying */ - DEV ("Canon imageCLASS MF5630", "MF5630", MF5630_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon laserBase MF5650", "MF5650", MF5650_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon imageCLASS MF8170c", "MF8170c", MF8100_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon imageClass MF8030", "MF8030", MF8030_PID, 600, 640, 877, PIXMA_CAP_ADF), - DEV ("Canon i-SENSYS MF5880dn", "MF5880", MF5880_PID, 600, 640, 877, PIXMA_CAP_ADFDUP), - DEV ("Canon i-SENSYS MF6680dn", "MF6680", MF6680_PID, 600, 640, 877, PIXMA_CAP_ADFDUP), - DEV ("Canon imageCLASS MF4570dw", "MF4570dw", MF4570_PID, 600, 640, 877, 0), - DEV ("Canon imageRUNNER 1133", "iR1133", IR1133_PID, 600, 637, 877, PIXMA_CAP_ADFDUP), - DEV (NULL, NULL, 0, 0, 0, 0, 0) + DEV ("Canon imageCLASS MF5630", "MF5630", MF5630_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon laserBase MF5650", "MF5650", MF5650_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon imageCLASS MF8170c", "MF8170c", MF8100_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon imageClass MF8030", "MF8030", MF8030_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), + DEV ("Canon i-SENSYS MF5880dn", "MF5880", MF5880_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), + DEV ("Canon i-SENSYS MF6680dn", "MF6680", MF6680_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), + DEV ("Canon imageRUNNER 1133", "iR1133", IR1133_PID, 600, 0, 637, 877, PIXMA_CAP_ADFDUP), + DEV ("Canon i-SENSYS MF8500C Series", "MF8500C", MF8500_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP), + DEV (NULL, NULL, 0, 0, 0, 0, 0, 0) }; diff --git a/backend/pixma_io_sanei.c b/backend/pixma_io_sanei.c index b25c7eb..59d1602 100644 --- a/backend/pixma_io_sanei.c +++ b/backend/pixma_io_sanei.c @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. * For limitations, see function sanei_usb_get_vendor_product(). + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. diff --git a/backend/pixma_mp150.c b/backend/pixma_mp150.c index e29dccd..22ca41d 100644 --- a/backend/pixma_mp150.c +++ b/backend/pixma_mp150.c @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2007-2009 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. @@ -209,6 +209,21 @@ #define MG5500_PID 0x1771 #define MG7100_PID 0x1772 +/* 2014 new devices (untested) */ +#define MX470_PID 0x1774 +#define MX530_PID 0x1775 +#define MB5000_PID 0x1776 +#define MB5300_PID 0x1777 +#define MB2000_PID 0x1778 +#define MB2300_PID 0x1779 +#define E400_PID 0x177a +#define E560_PID 0x177b +#define MG7500_PID 0x177c +#define MG6600_PID 0x177e +#define MG5600_PID 0x177f +#define MG2900_PID 0x1780 +#define E460_PID 0x1788 + /* Generation 4 XML messages that encapsulates the Pixma protocol messages */ #define XML_START_1 \ @@ -284,6 +299,7 @@ typedef struct mp150_t unsigned stripe_shift; uint8_t tpu_datalen; uint8_t tpu_data[0x40]; + uint8_t adf_state; /* handle adf scanning */ } mp150_t; /* @@ -420,7 +436,7 @@ is_calibrated (pixma_t * s) mp150_t *mp = (mp150_t *) s->subdriver; if (mp->generation >= 3) { - return ((mp->current_status[0] & 0x01) == 1); + return ((mp->current_status[0] & 0x01) == 1 || (mp->current_status[0] & 0x02) == 2); } if (mp->generation == 1) { @@ -454,6 +470,7 @@ static int abort_session (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; + mp->adf_state = state_idle; /* reset adf scanning */ return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session); } @@ -630,10 +647,14 @@ calc_shifting (pixma_t * s) /* If stripes shift needed (CCD devices), how many pixels shift */ mp->stripe_shift = 0; + /* If color plane shift (CCD devices), how many pixels shift */ + mp->color_shift = mp->shift[0] = mp->shift[1] = mp->shift[2] = 0; + switch (s->cfg->pid) { case MP800_PID: case MP800R_PID: + case MP830_PID: if (s->param->xdpi == 2400) { if (is_scanning_from_tpu(s)) @@ -641,35 +662,15 @@ calc_shifting (pixma_t * s) else mp->stripe_shift = 3; } - break; - - case MP830_PID: - if (s->param->xdpi == 2400) + if (s->param->ydpi > 75) { - if (is_scanning_from_tpu(s)) - mp->stripe_shift = 6; - else - mp->stripe_shift = 3; - } - break; - - default: /* Default, and all CIS devices */ - break; - } - /* If color plane shift (CCD devices), how many pixels shift */ - mp->color_shift = mp->shift[0] = mp->shift[1] = mp->shift[2] = 0; - if (s->param->ydpi > 75) - { - switch (s->cfg->pid) - { - case MP800_PID: - case MP800R_PID: - case MP830_PID: mp->color_shift = s->param->ydpi / ((s->param->ydpi < 1200) ? 150 : 75); if (is_scanning_from_tpu (s)) mp->color_shift = s->param->ydpi / 75; + /* If you're trying to decipher this color-shifting code, + the following line is where the magic is revealed. */ mp->shift[1] = mp->color_shift * get_cis_ccd_line_size (s); if (is_scanning_from_adf (s)) { /* ADF */ @@ -681,11 +682,11 @@ calc_shifting (pixma_t * s) mp->shift[0] = 2 * mp->shift[1]; mp->shift[2] = 0; } - break; + } + break; - default: - break; - } + default: /* Default, and all CIS devices */ + break; } return (2 * mp->color_shift + mp->stripe_shift); } @@ -940,7 +941,10 @@ handle_interrupt (pixma_t * s, int timeout) * rr: scan resolution * poll event with 'scanimage -A' */ if (s->cfg->pid == MG6200_PID - || s->cfg->pid == MG6300_PID) + || s->cfg->pid == MG6300_PID + || s->cfg->pid == MX520_PID + || s->cfg->pid == MX720_PID + || s->cfg->pid == MX920_PID) /* button no. in buf[7] * size in buf[10] 01=A4; 02=Letter; 08=10x15; 09=13x18; 0b=auto * format in buf[11] 01=JPEG; 02=TIFF; 03=PDF; 04=Kompakt-PDF @@ -1000,7 +1004,7 @@ static int wait_until_ready (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; - int error, tmo = 60; + int error, tmo = 120; /* some scanners need a long timeout */ RET_IF_ERR ((mp->generation >= 3) ? query_status_3 (s) : query_status (s)); @@ -1135,11 +1139,17 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib) && s->cfg->pid != MP220_PID && s->cfg->pid != MX360_PID && s->cfg->pid != MX370_PID + && s->cfg->pid != MX530_PID && s->cfg->pid != MX890_PID + && s->cfg->pid != MX720_PID + && s->cfg->pid != MX920_PID && s->cfg->pid != MG3100_PID + && s->cfg->pid != MG3500_PID && s->cfg->pid != MG2100_PID && s->cfg->pid != MG5300_PID - && s->cfg->pid != MG6300_PID) + && s->cfg->pid != MG5500_PID + && s->cfg->pid != MG6300_PID + && s->cfg->pid != MG7100_PID) reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->wx, line_size); /* Crop line to selected borders */ @@ -1201,9 +1211,14 @@ mp150_open (pixma_t * s) if (s->cfg->pid == MP140_PID) mp->generation = 2; + PDBG (pixma_dbg (3, "*mp150_open***** This is a generation %d scanner. *****\n", mp->generation)); + /* TPU info data setup */ mp->tpu_datalen = 0; + /* adf scanning */ + mp->adf_state = state_idle; + if (mp->generation < 4) { query_status (s); @@ -1281,21 +1296,9 @@ mp150_check_param (pixma_t * s, pixma_scan_param_t * sp) /*PDBG (pixma_dbg (4, "*mp150_check_param***** Final scan width and line-size: %i, %i *****\n", sp->wx, sp->line_size));*/ /* Some exceptions here for particular devices */ - /* Those devices can scan up to 14" with ADF, but A4 11.7" in flatbed */ - if (( s->cfg->pid == MX850_PID || - s->cfg->pid == MX860_PID || - s->cfg->pid == MX870_PID || - s->cfg->pid == MX880_PID || - s->cfg->pid == MX320_PID || - s->cfg->pid == MX330_PID || - s->cfg->pid == MX340_PID || - s->cfg->pid == MX350_PID || - s->cfg->pid == MX360_PID || - s->cfg->pid == MX410_PID || - s->cfg->pid == MX420_PID || - s->cfg->pid == MX7600_PID ) - && - sp->source == PIXMA_SOURCE_FLATBED) + /* Those devices can scan up to legal 14" with ADF, but A4 11.7" in flatbed */ + /* PIXMA_CAP_ADF also works for PIXMA_CAP_ADFDUP */ + if ((s->cfg->cap & PIXMA_CAP_ADF) && sp->source == PIXMA_SOURCE_FLATBED) sp->h = MIN (sp->h, 877 * sp->xdpi / 75); if (sp->source == PIXMA_SOURCE_TPU) @@ -1349,7 +1352,8 @@ mp150_scan (pixma_t * s) return PIXMA_EBUSY; /* Generation 4: send XML dialog */ - if (mp->generation == 4 && s->param->adf_pageid == 0) + /* adf: first page or idle */ + if (mp->generation == 4 && mp->adf_state == state_idle) { if (!send_xml_dialog (s, XML_START_1)) return PIXMA_EPROTO; @@ -1367,15 +1371,38 @@ mp150_scan (pixma_t * s) { if ((error = query_status (s)) < 0) return error; + + /* wait for inserted paper + * timeout: 10 sec */ tmo = 10; while (!has_paper (s) && --tmo >= 0) { + if ((error = query_status (s)) < 0) + return error; WAIT_INTERRUPT (1000); PDBG (pixma_dbg (2, "No paper in ADF. Timed out in %d sec.\n", tmo)); } + + /* no paper inserted + * => abort session */ if (!has_paper (s)) + { + PDBG (pixma_dbg (4, "*mp150_scan***** no paper in ADF *****\n")); + error = abort_session (s); + if (error < 0) + return error; + + /* Generation 4: send XML dialog */ + /* adf: first page or idle */ + if (mp->generation == 4 && mp->adf_state == state_idle) + { + if (!send_xml_dialog (s, XML_END)) + return PIXMA_EPROTO; + } + return PIXMA_ENO_PAPER; + } } if (has_ccd_sensor (s) && (mp->generation <= 2)) @@ -1406,8 +1433,10 @@ mp150_scan (pixma_t * s) } tmo = 10; - if (s->param->adf_pageid == 0 || mp->generation <= 2) - { + /* adf: first page or idle */ + if (mp->generation <= 2 || mp->adf_state == state_idle) + { /* single sheet or first sheet from ADF */ + PDBG (pixma_dbg (4, "*mp150_scan***** start scanning *****\n")); error = start_session (s); while (error == PIXMA_EBUSY && --tmo >= 0) { @@ -1448,7 +1477,11 @@ mp150_scan (pixma_t * s) error = send_set_tpu_info (s); } else /* ADF pageid != 0 and gen3 or above */ + { /* next sheet from ADF */ + PDBG (pixma_dbg (4, "*mp150_scan***** scan next sheet from ADF *****\n")); pixma_sleep (1000000); + } + if ((error >= 0) || (mp->generation >= 3)) mp->state = state_warmup; @@ -1462,6 +1495,10 @@ mp150_scan (pixma_t * s) mp150_finish_scan (s); return error; } + + /* ADF scanning active */ + if (is_scanning_from_adf (s)) + mp->adf_state = state_scanning; return 0; } @@ -1495,9 +1532,13 @@ mp150_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) do { if (s->cancel) + { + PDBG (pixma_dbg (4, "*mp150_fill_buffer***** s->cancel *****\n")); return PIXMA_ECANCELED; + } if ((mp->last_block & 0x28) == 0x28) - { /* end of image */ + { /* end of image */ + PDBG (pixma_dbg (4, "*mp150_fill_buffer***** end of image *****\n")); mp->state = state_finished; return 0; } @@ -1506,6 +1547,8 @@ mp150_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) error = read_image_block (s, header, mp->imgbuf + mp->data_left_len); if (error < 0) { + PDBG (pixma_dbg (4, "*mp150_fill_buffer***** scanner error (%d): end scan *****\n", error)); + mp->last_block = 0x38; /* end scan in mp150_finish_scan() */ if (error == PIXMA_ECANCELED) { /* NOTE: I see this in traffic logs but I don't know its meaning. */ @@ -1569,6 +1612,7 @@ mp150_finish_scan (pixma_t * s) * abort_session and start_session between pages (last_block=0x28) */ if (mp->generation <= 2 || !is_scanning_from_adf (s) || mp->last_block == 0x38) { + PDBG (pixma_dbg (4, "*mp150_finish_scan***** abort session *****\n")); error = abort_session (s); /* FIXME: it probably doesn't work in duplex mode! */ if (error < 0) PDBG (pixma_dbg (1, "WARNING:abort_session() failed %d\n", error)); @@ -1580,6 +1624,9 @@ mp150_finish_scan (pixma_t * s) PDBG (pixma_dbg (1, "WARNING:XML_END dialog failed \n")); } } + else + PDBG (pixma_dbg (4, "*mp150_finish_scan***** wait for next page from ADF *****\n")); + mp->state = state_idle; /* fall through */ case state_idle: @@ -1669,8 +1716,8 @@ const pixma_config_t pixma_mp150_devices[] = { DEVICE ("Canon PIXMA MP610", "MP610", MP610_PID, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MX300", "MX300", MX300_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), - DEVICE ("Canon PIXMA MX310", "MX310", MX310_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX700", "MX700", MX700_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX310", "MX310", MX310_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX700", "MX700", MX700_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX850", "MX850", MX850_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA MX7600", "MX7600", MX7600_PID, 4800, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), @@ -1699,7 +1746,7 @@ const pixma_config_t pixma_mp150_devices[] = { DEVICE ("Canon PIXMA MX360", "MX360", MX360_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX410", "MX410", MX410_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX420", "MX420", MX420_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX880 Series", "MX880", MX880_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon PIXMA MX880 Series", "MX880", MX880_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), /* Generation 4: CIS */ DEVICE ("Canon PIXMA MP640", "MP640", MP640_PID, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS), @@ -1726,27 +1773,27 @@ const pixma_config_t pixma_mp150_devices[] = { DEVICE ("Canon PIXMA E500", "E500", E500_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2012) Generation 4 CIS */ - DEVICE ("Canon PIXMA MX370 Series", "MX370", MX370_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX430 Series", "MX430", MX430_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX510 Series", "MX510", MX510_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX710 Series", "MX710", MX710_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), - DEVICE ("Canon PIXMA MX890 Series", "MX890", MX890_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), - DEVICE ("Canon PIXMA E600 Series", "E600", E600_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX370 Series", "MX370", MX370_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX430 Series", "MX430", MX430_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX510 Series", "MX510", MX510_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX710 Series", "MX710", MX710_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon PIXMA MX890 Series", "MX890", MX890_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon PIXMA E600 Series", "E600", E600_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MG4200", "MG4200", MG4200_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2013) Generation 4 CIS */ DEVICE ("Canon PIXMA E510", "E510", E510_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), - DEVICE ("Canon PIXMA E610", "E610", E610_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA E610", "E610", E610_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MP230", "MP230", MP230_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG2200 Series", "MG2200", MG2200_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG3200 Series", "MG3200", MG3200_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5400 Series", "MG5400", MG5400_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6300 Series", "MG6300", MG6300_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), - DEVICE ("Canon PIXMA MX390 Series", "MX390", MX390_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX450 Series", "MX450", MX450_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX520 Series", "MX520", MX520_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX720 Series", "MX720", MX720_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), - DEVICE ("Canon PIXMA MX920 Series", "MX920", MX920_PID, 2400, 0, 600, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon PIXMA MX390 Series", "MX390", MX390_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX450 Series", "MX450", MX450_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX520 Series", "MX520", MX520_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX720 Series", "MX720", MX720_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon PIXMA MX920 Series", "MX920", MX920_PID, 2400, 0, 600, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA MG2400 Series", "MG2400", MG2400_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG2500 Series", "MG2500", MG2500_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG3500 Series", "MG3500", MG3500_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), @@ -1755,5 +1802,20 @@ const pixma_config_t pixma_mp150_devices[] = { DEVICE ("Canon PIXMA MG6500 Series", "MG6500", MG6500_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG7100 Series", "MG7100", MG7100_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), + /* Latest devices (2014) Generation 4 CIS */ + DEVICE ("Canon PIXMA MX470 Series", "MX470", MX470_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA MX530 Series", "MX530", MX530_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon MAXIFY MB5000 Series", "MB5000", MB5000_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon MAXIFY MB5300 Series", "MB5300", MB5300_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon MAXIFY MB2000 Series", "MB2000", MB2000_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon MAXIFY MB2300 Series", "MB2300", MB2300_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), + DEVICE ("Canon PIXMA E400", "E400", E400_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA E560", "E560", E560_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA MG7500 Series", "MG7500", MG7500_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA MG6600 Series", "MG6600", MG6600_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA MG5600 Series", "MG5600", MG5600_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA MG2900 Series", "MG2900", MG2900_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA E460 Series", "E460", E460_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), + END_OF_DEVICE_LIST }; diff --git a/backend/pixma_mp730.c b/backend/pixma_mp730.c index 1980fcc..58d1994 100644 --- a/backend/pixma_mp730.c +++ b/backend/pixma_mp730.c @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. diff --git a/backend/pixma_mp750.c b/backend/pixma_mp750.c index ea35851..e46a942 100644 --- a/backend/pixma_mp750.c +++ b/backend/pixma_mp750.c @@ -1,7 +1,7 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. diff --git a/backend/pixma_mp810.c b/backend/pixma_mp810.c index 5b6cdfe..59e96eb 100644 --- a/backend/pixma_mp810.c +++ b/backend/pixma_mp810.c @@ -1,8 +1,8 @@ /* SANE - Scanner Access Now Easy. + Copyright (C) 2011-2014 Rolf Bensch Copyright (C) 2007-2009 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong - Copyright (C) 2011-2013 Rolf Bensch This file is part of the SANE package. diff --git a/backend/pnm.c b/backend/pnm.c index 88b6e4a..b8d3192 100644 --- a/backend/pnm.c +++ b/backend/pnm.c @@ -267,7 +267,7 @@ static SANE_Option_Descriptor sod[] = { SANE_I18N ("Hand-Scanner Simulation"), SANE_I18N ("Simulate a hand-scanner. Hand-scanners often do not know the " "image height a priori. Instead, they return a height of -1. " - "Setting this option allows to test whether a frontend can " + "Setting this option allows one to test whether a frontend can " "handle this correctly."), SANE_TYPE_BOOL, SANE_UNIT_NONE, diff --git a/backend/rts8891.c b/backend/rts8891.c index d86347b..bdb4011 100644 --- a/backend/rts8891.c +++ b/backend/rts8891.c @@ -2212,7 +2212,13 @@ sane_close (SANE_Handle handle) /* switch off lamp and close usb */ if (dev->conf.allowsharing == SANE_TRUE) { - sanei_usb_claim_interface (dev->devnum, 0); + SANE_Status status = sanei_usb_claim_interface (dev->devnum, 0); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_warn, "sane_close: cannot claim usb interface: %s\n", + sane_strstatus(status)); + DBG (DBG_warn, "sane_close: continuing anyway\n"); + } } set_lamp_state (session, 0); sanei_usb_close (dev->devnum); @@ -3197,14 +3203,6 @@ find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) return status; } - if (status != SANE_STATUS_GOOD) - { - free(image); - free(data); - DBG (DBG_error, "find_origin: failed to wait for data\n"); - return status; - } - if (DBG_LEVEL > DBG_io2) { write_gray_data (data, "find_origin.pnm", width, height); diff --git a/backend/scripts/pixma_gen_options.py b/backend/scripts/pixma_gen_options.py new file mode 100755 index 0000000..20f0037 --- /dev/null +++ b/backend/scripts/pixma_gen_options.py @@ -0,0 +1,390 @@ +#!/usr/bin/env python + +import sys,os,re + +class Error(Exception): + pass + + +class ParseError(Error): + def __init__(self, errline): + Error.__init__(self, errline) + + +class Struct: + pass + + +def createCNameMap(): + t = '' + for i in range(256): + if ((ord('A') <= i) and (i <= ord('Z'))) or \ + ((ord('a') <= i) and (i <= ord('z'))) or \ + ((ord('0') <= i) and (i <= ord('9'))): + t += chr(i) + else: + t += '_' + return t + + +def seekBegin(f): + while True: + line = f.readline() + if not line: + return False + if line.startswith('BEGIN SANE_Option_Descriptor'): + return True + + +def parseVerbatim(o, line): + words = line.split(None, 1) + if (len(words) < 2) or (words[1][0] != '@'): + return False + o[words[0]] = words[1] + return True + + +def parseLine_type(o, line): + words = line.split(None, 2) + otype = words[1] + o['type'] = 'SANE_TYPE_' + otype.upper() + if otype == 'group': + g.ngroups += 1 + oname = '_group_%d' % g.ngroups + o['size'] = 0 + else: + temp = words[2] + idx = temp.find('[') + if idx == -1: + oname = temp + o['size'] = 1 + else: + oname = temp[0:idx] + o['size'] = int(temp[idx+1:-1]) + o['name'] = oname + + +def parseLine_title(o, line): + o['title'] = line.split(None, 1)[1] + + +def parseLine_desc(o, line): + o['desc'] = line.split(None, 1)[1] + + +def parseLine_unit(o, line): + o['unit'] = 'SANE_UNIT_' + line.split(None, 1)[1].upper() + + +def parseLine_default(o, line): + o['default'] = line.split(None, 1)[1] + + +def parseLine_cap(o, line): + words = line.split() + o['cap'] = ['SANE_CAP_' + s.upper() for s in words[1:]] + + +def parseLine_constraint(o, line): + c = line.split(None,1)[1] + if c[0] == '{': + o['constraint'] = c[1:-1].split('|') + elif c[0] == '(': + o['constraint'] = tuple(c[1:-1].split(',')) + else: + sys.stderr.write('Ignored: %s\n' % line) + + +def parseLine_info(o, line): + words = line.split() + o['info'] = ['SANE_INFO_' + s.upper() for s in words[1:]] + +def parseLine_rem(o, line): + pass + +def normalize(o): + if 'cname' not in o: + cname = o['name'].translate(cnameMap) + o['cname'] = cname + else: + cname = o['cname'] + o['cname_opt'] = 'opt_' + cname + o['cname_con'] = 'constraint_' + cname + if 'title' not in o: + o['title'] = 'NO TITLE' + if 'desc' not in o: + o['desc'] = '@sod->title' % o + if 'unit' not in o: + o['unit'] = 'SANE_UNIT_NONE' + if 'constraint_type' not in o: + if 'constraint' not in o: + ct = 'SANE_CONSTRAINT_NONE' + elif isinstance(o['constraint'], list): + if o['type'] == 'SANE_TYPE_STRING': + ct = 'SANE_CONSTRAINT_STRING_LIST' + else: + ct = 'SANE_CONSTRAINT_WORD_LIST' + elif isinstance(o['constraint'], tuple): + ct = 'SANE_CONSTRAINT_RANGE' + elif isinstance(o['constraint'], str): + oc = o['constraint'] + if oc.startswith('@range'): + ct = 'SANE_CONSTRAINT_RANGE' + elif oc.startswith('@word_list'): + ct = 'SANE_CONSTRAINT_WORD_LIST' + elif oc.startswith('@string_list'): + ct = 'SANE_CONSTRAINT_STRING_LIST' + o['constraint_type'] = ct + return o + + +def parseFile(f): + if not seekBegin(f): + return None + options = [ { + 'name' : '', + 'cname' : 'opt_num_opts', + 'title' : '@SANE_TITLE_NUM_OPTIONS', + 'desc' : '@SANE_DESC_NUM_OPTIONS', + 'type' : 'SANE_TYPE_INT', + 'unit' : 'SANE_UNIT_NONE', + 'size' : 1, + 'cap' : ['SANE_CAP_SOFT_DETECT'], + 'constraint_type' : 'SANE_CONSTRAINT_NONE', + 'default' : '@w = ' + opt_prefix + 'last' + } ] + o = {} + while True: + line = f.readline() + if not line: + break + line = line.strip() + if not line: + continue + token = line.split(None, 1)[0].lower() + if token == 'end': + break + if token == 'type': + if 'name' in o: + options.append(o) + o = {} + funcName = 'parseLine_' + token + if funcName in globals(): + if not parseVerbatim(o, line): + func = globals()[funcName] + func(o, line) + else: + sys.stderr.write('Skip: %s\n' % line) + if 'name' in o: + options.append(o) + return [normalize(o) for o in options] + + +def genHeader(options): + print """ +typedef union { + SANE_Word w; + SANE_Int i; + SANE_Bool b; + SANE_Fixed f; + SANE_String s; + void *ptr; +} option_value_t; +""" + print 'typedef enum {' + for o in options: + print ' %(cname_opt)s,' % o + print ' ' + opt_prefix + 'last' + print '} option_t;' + print """ + +typedef struct { + SANE_Option_Descriptor sod; + option_value_t val,def; + SANE_Word info; +} option_descriptor_t; + + +struct pixma_sane_t; +static int build_option_descriptors(struct pixma_sane_t *ss); +""" + + +def genMinMaxRange(n, t, r): + if t == 'SANE_TYPE_FIXED': + r = ['SANE_FIX(%s)' % x for x in r] + print 'static const SANE_Range ' + n + ' = ' + print ' { ' + r[0] + ',' + r[1] + ',' + r[2] + ' };' + + +def genList(n, t, l): + if t == 'SANE_TYPE_INT': + etype = 'SANE_Word' + l = [str(len(l))] + l + elif t == 'SANE_TYPE_FIXED': + etype = 'SANE_Word' + l = [str(len(l))] + ['SANE_FIX(%s)' % x for x in l] + elif t == 'SANE_TYPE_STRING': + etype = 'SANE_String_Const' + l = ['SANE_I18N("%s")' % x for x in l] + ['NULL'] + print 'static const %s %s[%d] = {' % (etype, n, len(l)) + for x in l[0:-1]: + print '\t' + x + ',' + print '\t' + l[-1] + ' };' + + +def genConstraints(options): + for o in options: + if 'constraint' not in o: continue + c = o['constraint'] + oname = o['cname_con'] + otype = o['type'] + if isinstance(c, tuple): + genMinMaxRange(oname, otype, c) + elif isinstance(c, list): + genList(oname, otype, c) + print + +def buildCodeVerbatim(o): + for f in ('name', 'title', 'desc', 'type', 'unit', 'size', 'cap', + 'constraint_type', 'constraint', 'default'): + if (f not in o): continue + temp = o[f] + if (not isinstance(temp,str)) or \ + (len(temp) < 1) or (temp[0] != '@'): + continue + o['code_' + f] = temp[1:] + +def ccode(o): + buildCodeVerbatim(o) + if 'code_name' not in o: + o['code_name'] = '"' + o['name'] + '"' + for f in ('title', 'desc'): + cf = 'code_' + f + if cf in o: continue + o[cf] = 'SANE_I18N("' + o[f] + '")' + + for f in ('type', 'unit', 'constraint_type'): + cf = 'code_' + f + if cf in o: continue + o[cf] = o[f] + + if 'code_size' not in o: + otype = o['type'] + osize = o['size'] + if otype == 'SANE_TYPE_STRING': + code = str(osize + 1) + elif otype == 'SANE_TYPE_INT' or otype == 'SANE_TYPE_FIXED': + code = str(osize) + ' * sizeof(SANE_Word)' + elif otype == 'SANE_TYPE_BUTTON': + code = '0' + else: + code = 'sizeof(SANE_Word)' + o['code_size'] = code + + if ('code_cap' not in o) and ('cap' in o): + o['code_cap'] = reduce(lambda a,b: a+'|'+b, o['cap']) + else: + o['code_cap'] = '0' + + if ('code_info' not in o) and ('info' in o): + o['code_info'] = reduce(lambda a,b: a+'|'+b, o['info']) + else: + o['code_info'] = '0' + + if ('code_default' not in o) and ('default' in o): + odefault = o['default'] + otype = o['type'] + if odefault == '_MIN': + rhs = 'w = sod->constraint.range->min' + elif odefault == '_MAX': + rhs = 'w = sod->constraint.range->max' + elif otype in ('SANE_TYPE_INT', 'SANE_TYPE_BOOL'): + rhs = 'w = %(default)s' + elif otype == 'SANE_TYPE_FIXED': + rhs = 'w = SANE_FIX(%(default)s)' + elif otype == 'SANE_TYPE_STRING': + rhs = 's = SANE_I18N("%(default)s")' + o['code_default'] = rhs % o + if 'code_default' in o: + code = ' opt->def.%(code_default)s;\n' + if o['constraint_type'] != 'SANE_CONSTRAINT_STRING_LIST': + code += ' opt->val.%(code_default)s;\n' + else: + code += ' opt->val.w = find_string_in_list' \ + '(opt->def.s, sod->constraint.string_list);\n' + o['full_code_default'] = code % o + else: + o['full_code_default'] = '' + + if ('code_constraint' not in o) and ('constraint' in o): + ct = o['constraint_type'] + idx = len('SANE_CONSTRAINT_') + ctype = ct[idx:].lower() + if ctype == 'range': + rhs = '&%(cname_con)s' % o + else: + rhs = '%(cname_con)s' % o + o['code_constraint'] = ctype + ' = ' + rhs + if 'code_constraint' in o: + code = ' sod->constraint.%(code_constraint)s;\n' + o['full_code_constraint'] = code % o + else: + o['full_code_constraint'] = '' + + return o + +def genBuildOptions(options): + print """ +static +int find_string_in_list(SANE_String_Const str, const SANE_String_Const *list) +{ + int i; + for (i = 0; list[i] && strcmp(str, list[i]) != 0; i++) {} + return i; +} + +static +int build_option_descriptors(struct pixma_sane_t *ss) +{ + SANE_Option_Descriptor *sod; + option_descriptor_t *opt; + + memset(OPT_IN_CTX, 0, sizeof(OPT_IN_CTX));""" + + for o in options: + o = ccode(o) + otype = o['type'] + code = '\n opt = &(OPT_IN_CTX[%(cname_opt)s]);\n' \ + ' sod = &opt->sod;\n' \ + ' sod->type = %(code_type)s;\n' \ + ' sod->title = %(code_title)s;\n' \ + ' sod->desc = %(code_desc)s;\n' + if otype != 'SANE_TYPE_GROUP': + code += ' sod->name = %(code_name)s;\n' \ + ' sod->unit = %(code_unit)s;\n' \ + ' sod->size = %(code_size)s;\n' \ + ' sod->cap = %(code_cap)s;\n' \ + ' sod->constraint_type = %(code_constraint_type)s;\n' \ + '%(full_code_constraint)s' \ + ' OPT_IN_CTX[%(cname_opt)s].info = %(code_info)s;\n' \ + '%(full_code_default)s' + sys.stdout.write(code % o) + print + print ' return 0;\n' + print '}' + print + +g = Struct() +g.ngroups = 0 +opt_prefix = 'opt_' +con_prefix = 'constraint_' +cnameMap = createCNameMap() +options = parseFile(sys.stdin) +print "/* Automatically generated from pixma_sane.c */" +if (len(sys.argv) == 2) and (sys.argv[1] == 'h'): + genHeader(options) +else: + genConstraints(options) + genBuildOptions(options) + diff --git a/backend/test.c b/backend/test.c index 8f8851a..505c821 100644 --- a/backend/test.c +++ b/backend/test.c @@ -348,7 +348,7 @@ init_options (Test_Device * test_device) od->title = SANE_I18N ("Hand-scanner simulation"); od->desc = SANE_I18N ("Simulate a hand-scanner. Hand-scanners do not " "know the image height a priori. Instead, they " - "return a height of -1. Setting this option allows " + "return a height of -1. Setting this option allows one " "to test whether a frontend can handle this " "correctly. This option also enables a fixed width " "of 11 cm."); diff --git a/backend/umax-uc630.c b/backend/umax-uc630.c index 26c6831..0fbc59f 100644 --- a/backend/umax-uc630.c +++ b/backend/umax-uc630.c @@ -76,14 +76,14 @@ static unsigned char UC630_INQUIRY[] = /* 60 -62 scanner capability */ 0xfd, - 0x8c, /* 0xbc ? */ + 0x80, 0x03, /* 63 reserved */ 0x00, /* 64 gamma */ - 0xa1, + 0x00, /* 65 reserved */ 0x00, @@ -113,13 +113,13 @@ static unsigned char UC630_INQUIRY[] = 0x00, /* 73 max optical res in 100 dpi */ - 0x04, + 0x03, /* 74 max x_res in 100 dpi */ - 0x04, + 0x03, /* 75 max y_res in 100 dpi */ - 0x04, + 0x06, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x52, @@ -167,7 +167,7 @@ static unsigned char UC630_INQUIRY[] = 0x00, /* 92-93 window descriptor block length */ - 0x00, 0x30, + 0x00, 0x31, /* 94 optical resolution residue (1dpi) */ 0x00, diff --git a/backend/umax.c b/backend/umax.c index b2ceb00..0d8ddba 100644 --- a/backend/umax.c +++ b/backend/umax.c @@ -1035,7 +1035,7 @@ static SANE_Status sense_handler(int scsi_fd, unsigned char *result, void *arg) if (asc == 0x00) { - DBG(DBG_sense, "-> button protocoll\n"); + DBG(DBG_sense, "-> button protocol\n"); if (ascq & 1) { dev->button0_pressed = 1; diff --git a/backend/umax_pp_low.c b/backend/umax_pp_low.c index ef10bd7..c5f58a7 100644 --- a/backend/umax_pp_low.c +++ b/backend/umax_pp_low.c @@ -10898,7 +10898,7 @@ sanei_umax_pp_scan (int x, int y, int width, int height, int dpi, int color, /* scan time are high enough to forget about usec */ elapsed = tf.tv_sec - td.tv_sec; - DBG (8, "%ld bytes transfered in %f seconds ( %.2f Kb/s)\n", somme, + DBG (8, "%ld bytes transferred in %f seconds ( %.2f Kb/s)\n", somme, elapsed, (somme / elapsed) / 1024.0); #endif diff --git a/configure b/configure index 65d8cdc..bd6249f 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sane-backends 1.0.24. +# Generated by GNU Autoconf 2.69 for sane-backends 1.0.25git. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sane-backends' PACKAGE_TARNAME='sane-backends' -PACKAGE_VERSION='1.0.24' -PACKAGE_STRING='sane-backends 1.0.24' +PACKAGE_VERSION='1.0.25git' +PACKAGE_STRING='sane-backends 1.0.25git' PACKAGE_BUGREPORT='sane-devel@lists.alioth.debian.org' PACKAGE_URL='' @@ -1414,7 +1414,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sane-backends 1.0.24 to adapt to many kinds of systems. +\`configure' configures sane-backends 1.0.25git to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1484,7 +1484,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sane-backends 1.0.24:";; + short | recursive ) echo "Configuration of sane-backends 1.0.25git:";; esac cat <<\_ACEOF @@ -1643,7 +1643,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sane-backends configure 1.0.24 +sane-backends configure 1.0.25git generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2249,7 +2249,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sane-backends $as_me 1.0.24, which was +It was created by sane-backends $as_me 1.0.25git, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2602,8 +2602,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu V_MAJOR=1 V_MINOR=0 -V_REV=24 -is_release=yes +V_REV=25 +is_release=no @@ -3122,7 +3122,7 @@ fi # Define the identity of the package. PACKAGE='sane-backends' - VERSION='1.0.24' + VERSION='1.0.25git' cat >>confdefs.h <<_ACEOF @@ -3201,7 +3201,7 @@ ac_config_headers="$ac_config_headers include/sane/config.h" PACKAGE=sane-backends -VERSION=1.0.24 +VERSION=1.0.25git NUMBER_VERSION=${V_MAJOR}.${V_MINOR}.${V_REV} cat >>confdefs.h <<_ACEOF @@ -18816,7 +18816,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sane-backends $as_me 1.0.24, which was +This file was extended by sane-backends $as_me 1.0.25git, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18882,7 +18882,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sane-backends config.status 1.0.24 +sane-backends config.status 1.0.25git configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.in b/configure.in index a91d584..4365868 100644 --- a/configure.in +++ b/configure.in @@ -3,11 +3,11 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*- dnl *********************************************************************** dnl When preparing a release, increase the numeric and string version numbers, dnl remove the "cvs" suffix, and set is_release=yes -AC_INIT([sane-backends],[1.0.24],[sane-devel@lists.alioth.debian.org]) +AC_INIT([sane-backends],[1.0.25git],[sane-devel@lists.alioth.debian.org]) V_MAJOR=1 V_MINOR=0 -V_REV=24 -is_release=yes +V_REV=25 +is_release=no dnl *********************************************************************** m4_ifdef([AC_CONFIG_MACRO_DIR], [AC_CONFIG_MACRO_DIR([m4])]) @@ -332,17 +332,17 @@ if test -c /dev/urandom ; then AC_DEFINE(HAVE_DEV_URANDOM, 1, [Is /dev/urandom available?]) fi -dnl added by PN 3/2/12 to detect cups -$as_echo "checking for cups" -if test -e /usr/include/cups/cups.h ; then - AC_DEFINE(HAVE_CUPS, 1, [Is /usr/include/cups/cups.h available?]) - with_cups="yes" - LIBS="-lcups $LIBS" -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" -fi +dnl added by PN 3/2/12 to detect cups commented out 15/10/13 since avahi is now used instead +dnl $as_echo "checking for cups" +dnl if test -e /usr/include/cups/cups.h ; then +dnl AC_DEFINE(HAVE_CUPS, 1, [Is /usr/include/cups/cups.h available?]) +dnl with_cups="yes" +dnl LIBS="-lcups $LIBS" +dnl else +dnl $as_echo "cups.h not found, you may want to install a cups development package" +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..." @@ -816,7 +816,7 @@ 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}`" +dnl echo "CUPS support: `eval eval echo ${with_cups}`" commented out 15/10/13 echo "-> The following backends will be built:" for backend in ${BACKENDS} ; do echo $ECHO_N "${backend} " diff --git a/debian/changelog b/debian/changelog index f14118b..c7f5ad4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,32 @@ +sane-backends (1.0.25+git20150102-1) experimental; urgency=medium + + * Build from daily snapshot sane-backends-git20150102.tar.gz. + * Remove applied patches from debian/patches: + - fix-FTBFS-format-not-a-string-literal-error.patch + - kodakaio.patch + - saned.man.patch + - man-page-spelling.patch + - source-spelling.patch + - hp5370c.patch + - out_of_bounds.patch + - 0100-usb3-corrections.patch + * Refresh patches: + - sane-desc.c_debian_mods.patch + - 0500-systemd_configure.patch + * debian/rules: + - Add line to extract the version from debian/changelog. + - Add version string to dpkg-gensymbols. + + -- Jörg Frings-Fürst Fri, 02 Jan 2015 10:28:45 +0100 + +sane-backends (1.0.24-9) UNRELEASED; urgency=medium + + * Correct typo and add missing "-q" to line 33 of + debian/sane-utils.postinst (Closes: #773826). + - Thanks to "Nelson A. de Oliveira" + + -- Jörg Frings-Fürst Fri, 02 Jan 2015 10:28:33 +0100 + sane-backends (1.0.24-8) unstable; urgency=medium * New debian/patches/0100-usb3-corrections.patch: diff --git a/debian/patches/0500-systemd_configure.patch b/debian/patches/0500-systemd_configure.patch index 27121e6..440bf02 100644 --- a/debian/patches/0500-systemd_configure.patch +++ b/debian/patches/0500-systemd_configure.patch @@ -5,13 +5,13 @@ Forwarded: https://alioth.debian.org/tracker/index.php?func=detail&aid=314906&gr Last-Update: 2014-12-11 --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ -Index: trunk/configure.in +Index: experimental/configure.in =================================================================== ---- trunk.orig/configure.in -+++ trunk/configure.in -@@ -344,17 +344,40 @@ else - with_cups="no" - fi +--- experimental.orig/configure.in ++++ experimental/configure.in +@@ -344,17 +344,40 @@ dnl $as_echo "in order to autodetect ne + dnl with_cups="no" + dnl fi +dnl dnl added by llagendijk 12/7/2012 to detect systemd for saned diff --git a/debian/patches/sane-desc.c_debian_mods.patch b/debian/patches/sane-desc.c_debian_mods.patch index 27520ce..4b9faec 100644 --- a/debian/patches/sane-desc.c_debian_mods.patch +++ b/debian/patches/sane-desc.c_debian_mods.patch @@ -859,19 +859,6 @@ Index: sane-backends-1.0.24/testsuite/tools/data/html-backends-split.ref Description: Network access to saned servers
Comment: Can be used to access any scanner supported by SANE over the net. Supports IPv4 and IPv6.

-Index: sane-backends-1.0.24/testsuite/tools/Makefile.in -=================================================================== ---- sane-backends-1.0.24.orig/testsuite/tools/Makefile.in 2013-10-05 16:41:07.991355170 -0400 -+++ sane-backends-1.0.24/testsuite/tools/Makefile.in 2013-10-05 16:47:36.395343694 -0400 -@@ -503,7 +503,7 @@ - do \ - echo "PASS: sane-desc -m $$mode -s $(srcdir)/data"; \ - $(SANEDESC) -m $$mode -s $(srcdir)/data >$$mode.res ;\ -- if ! diff --ignore-matching-lines="..:..:.. 20[0-9][0-9]" $(srcdir)/data/$$mode.ref $$mode.res ; \ -+ if ! diff --ignore-matching-lines="by sane-desc .* from sane-backends\|..:..:.. 20[0-9][0-9]" $(srcdir)/data/$$mode.ref $$mode.res ; \ - then \ - echo "**** File generated for $$mode mode is different from reference" ;\ - exit 1 ;\ Index: sane-backends-1.0.24/testsuite/tools/data/html-mfgs.ref =================================================================== --- sane-backends-1.0.24.orig/testsuite/tools/data/html-mfgs.ref 2013-08-25 17:23:27.000000000 -0400 diff --git a/debian/patches/series b/debian/patches/series index 5586d9d..53b3757 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -6,19 +6,19 @@ dll_backend_conf.patch multiarch_dll_search_path.patch multiarch_manpages_libdir.patch kfreebsd.patch -fix-FTBFS-format-not-a-string-literal-error.patch +#fix-FTBFS-format-not-a-string-literal-error.patch frontend_libs.patch libsane_deps.patch trim-libraries-in-sane-backends.pc.in.patch unneeded_doc.patch sane-desc.c_debian_mods.patch -kodakaio.patch -saned.man.patch +#kodakaio.patch +#saned.man.patch nousbtest.patch -man-page-spelling.patch -source-spelling.patch +#man-page-spelling.patch +#source-spelling.patch ppc64el.patch -hp5370c.patch -out_of_bounds.patch +#hp5370c.patch +#out_of_bounds.patch 0500-systemd_configure.patch -0100-usb3-corrections.patch +#0100-usb3-corrections.patch diff --git a/debian/rules b/debian/rules index 5fc4afb..846dcad 100755 --- a/debian/rules +++ b/debian/rules @@ -10,6 +10,7 @@ DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS) + ifeq ($(DEB_HOST_ARCH_OS),) DEB_HOST_ARCH_OS := $(subst -gnu,,$(shell dpkg-architecture -qDEB_HOST_GNU_SYSTEM)) ifeq ($(DEB_HOST_ARCH_OS),gnu) @@ -26,6 +27,8 @@ ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) STRIP = "" endif +VERSION = $(shell head -n1 debian/changelog | sed -e 's/.*(//;s/+.*).*//;s/\+/\-/') + %: dh $@ --parallel --with autotools_dev,systemd @@ -137,5 +140,5 @@ override_dh_builddeb: dh_builddeb -- -Zxz override_dh_makeshlibs: - dpkg-gensymbols -plibsane + dpkg-gensymbols -v$(VERSION) -plibsane dh_makeshlibs diff --git a/debian/sane-utils.postinst b/debian/sane-utils.postinst index 4f16f0a..c29b29c 100644 --- a/debian/sane-utils.postinst +++ b/debian/sane-utils.postinst @@ -30,8 +30,8 @@ if [ "$1" = "configure" ] || [ "$1" = "reconfigure" ]; then fi # Move home from /home/saned to /var/lib/saned - if getent passwd | grep "^saned:" | grep "/home/saned"; then - echo "Moveing homedir from /home/saned to /var/lib/saned" + if getent passwd | grep -q "^saned:" | grep "/home/saned"; then + echo "Moving homedir from /home/saned to /var/lib/saned" usermod -d /var/lib/saned saned fi if [ "$SANED_IN_SCANNER" = "true" ]; then diff --git a/debian/watch b/debian/watch index ed24163..5a03f64 100644 --- a/debian/watch +++ b/debian/watch @@ -2,4 +2,7 @@ # watch file for sane-backends # version=3 -https://alioth.debian.org/frs/?group_id=30186 .*/sane-backends-(.*).(?:tar\.xz|txz|tar\.bz2|tbz2|tar\.gz|tgz) +# +# disabled in experimental +# +#https://alioth.debian.org/frs/?group_id=30186 .*/sane-backends-(.*).(?:tar\.xz|txz|tar\.bz2|tbz2|tar\.gz|tgz) diff --git a/doc/descriptions/canon_dr.desc b/doc/descriptions/canon_dr.desc index b69bdcc..406bbfb 100644 --- a/doc/descriptions/canon_dr.desc +++ b/doc/descriptions/canon_dr.desc @@ -11,9 +11,9 @@ :backend "canon_dr" ; name of backend :url "http://www.thebility.com/canon/" -:version "41" ; version of backend +:version "47" ; version of backend :manpage "sane-canon_dr" ; name of manpage (if it exists) -:comment "Backend updated for SANE release 1.0.24, see sane-canon_dr manpage" +:comment "Backend updated for SANE release 1.0.25, see sane-canon_dr manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api @@ -226,8 +226,8 @@ :model "DR-7080C" :interface "USB SCSI" :usbid "0x04a9" "0x1604" -:status :untested -:comment "Please test!" +:status :good +:comment "ADF and flatbed work" :model "DR-7090C" :interface "USB SCSI" @@ -265,37 +265,62 @@ :status :untested :comment "Please test!" +:model "DR-C120" +:interface "USB" +:usbid "0x1083" "0x1651" +:status :untested + :model "DR-C125" :interface "USB" -;:usbid "0x1083" "0x" +:usbid "0x1083" "0x1640" :status :untested :comment "Similar protocol to other canon_dr machines, but unsupported image format." :model "DR-C130" :interface "USB" -;:usbid "0x1083" "0x" +:usbid "0x1083" "0x164a" :status :untested -:model "DR-G1100" +:model "DR-C225" :interface "USB" -;:usbid "0x1083" "0x" +:usbid "0x1083" "0x1658" +:status :untested + +:model "DR-F120" +:interface "USB" +:usbid "0x1083" "0x1654" :status :untested +:model "DR-G1100" +:interface "USB" +:usbid "0x1083" "0x1650" +:status :good + :model "DR-G1130" :interface "USB" -;:usbid "0x1083" "0x" +:usbid "0x1083" "0x164f" :status :untested :model "DR-M140" :interface "USB" -;:usbid "0x1083" "0x" -:status :untested +:usbid "0x1083" "0x163f" +:status :good :model "DR-M160" :interface "USB" +:usbid "0x1083" "0x163e" +:status :good + +:model "DR-M160II" +:interface "USB" ;:usbid "0x1083" "0x" :status :untested +:model "DR-M1060" +:interface "USB" +:usbid "0x1083" "0x1657" +:status :untested + :model "P-150" :interface "USB" ;:usbid "0x1083" "0x" @@ -306,15 +331,63 @@ ;:usbid "0x1083" "0x" :status :untested +:model "P-201" +:interface "USB" +:usbid "0x1083" "0x1652" +:status :untested + +:model "DR-P208" +:interface "USB" +:usbid "0x1083" "0x164b" +:status :untested +:comment "Same as P-208?" + :model "P-208" :interface "USB" :usbid "0x1083" "0x164c" :status :basic :comment "All modes and resolutions working, but calibration is poor." +:model "DR-P208II" +:interface "USB" +:usbid "0x1083" "0x165d" +:status :untested + +:model "P-208II" +:interface "USB" +:usbid "0x1083" "0x165f" +:status :untested + +:model "DR-P215" +:interface "USB" +:usbid "0x1083" "0x1641" +:status :untested +:comment "Same as P-215?" + :model "P-215" :interface "USB" :usbid "0x1083" "0x1646" :status :basic :comment "All modes and resolutions working, but calibration is poor. Card reader slot not working." +:model "P-215" +:interface "USB" +:usbid "0x1083" "0x1647" +:status :basic +:comment "This is the same device as the 0x1646 P-215, but the mode switch on the scanner is in the wrong position, you must move the switch." + +:model "DR-P215II" +:interface "USB" +:usbid "0x1083" "0x1659" +:status :untested + +:model "P-215II" +:interface "USB" +:usbid "0x1083" "0x165b" +:status :untested + +:model "FSU-201" +:interface "USB" +:usbid "0x1083" "0x1648" +:status :untested + diff --git a/doc/descriptions/epjitsu.desc b/doc/descriptions/epjitsu.desc index 7c453df..630a1f7 100644 --- a/doc/descriptions/epjitsu.desc +++ b/doc/descriptions/epjitsu.desc @@ -11,9 +11,9 @@ :backend "epjitsu" ; name of backend :url "http://www.thebility.com/epjitsu/" -:version "20" ; version of backend +:version "25" ; version of backend :manpage "sane-epjitsu" ; name of manpage (if it exists) -:comment "Backend updated for SANE release 1.0.21, see sane-epjitsu manpage" +:comment "Backend updated for SANE release 1.0.25, see sane-epjitsu manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api @@ -42,9 +42,9 @@ :model "ScanSnap S1100" :interface "USB" -:status :unsupported +:status :good :usbid "0x04c5" "0x1200" -:comment "Beta version of backend source available, which works well, but breaks support for other epjitsu scanners. See http://ubuntuforums.org/showthread.php?t=1678335" +:comment "Hardware only supports 300 and 600 dpi simplex color. Backend manufactures gray and binary modes." :model "ScanSnap S1300" :interface "USB" @@ -52,3 +52,14 @@ :usbid "0x04c5" "0x11ed" :comment "Same as S300, with different usb id" +:model "ScanSnap S1300i" +:interface "USB" +:status :good +:usbid "0x04c5" "0x128d" +:comment "Similar to S1300." + +:model "fi-65F" +:interface "USB" +:status :basic +;:usbid "0x04c5" "0x10c7" +:comment "A6-size flatbed, 300/600 dpi, color/gray/binary." diff --git a/doc/descriptions/epson.desc b/doc/descriptions/epson.desc index a31fc84..d5fd896 100644 --- a/doc/descriptions/epson.desc +++ b/doc/descriptions/epson.desc @@ -176,6 +176,7 @@ :model "Expression 800" :interface "SCSI" :status :complete +:scsi "EPSON" "Expression800" "processor" :model "Expression 1600" :interface "SCSI USB IEEE-1394" diff --git a/doc/descriptions/epson2.desc b/doc/descriptions/epson2.desc index 9d9461d..82030b1 100644 --- a/doc/descriptions/epson2.desc +++ b/doc/descriptions/epson2.desc @@ -43,6 +43,30 @@ :status :good :comment "network interface probably supported" +:model "AcuLaser MX20DN" +:interface "USB" +:usbid "0x04b8" "0x0866" +:status :complete +:comment "network interface probably supported
business all-in-one" + +:model "AcuLaser MX20DNF" +:interface "USB" +:usbid "0x04b8" "0x0866" +:status :complete +:comment "network interface probably supported
business all-in-one" + +:model "AcuLaser MX21DNF" +:interface "USB" +:usbid "0x04b8" "0x0866" +:status :complete +:comment "network interface probably supported
business all-in-one" + +:model "Artisan 635" +:interface "USB" +:usbid "0x04b8" "0x0878" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-704A" + :model "Artisan 700" :interface "USB Network" :usbid "0x04b8" "0x0846" @@ -52,8 +76,20 @@ :model "Artisan 710 Series" :interface "USB" :usbid "0x04b8" "0x0852" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" + +:model "Artisan 725" +:interface "USB" +:usbid "0x04b8" "0x0861" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" + +:model "Artisan 730 Series" +:interface "USB" +:usbid "0x04b8" "0x087b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Artisan 800" :interface "USB" @@ -64,8 +100,20 @@ :model "Artisan 810 Series" :interface "USB" :usbid "0x04b8" "0x0853" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-902A" + +:model "Artisan 835" +:interface "USB" +:usbid "0x04b8" "0x0860" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" + +:model "Artisan 837" +:interface "USB" +:usbid "0x04b8" "0x0879" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-904F" :model "CC-500L" ; product spec (JP) :interface "USB" @@ -97,12 +145,54 @@ :status :unsupported :comment "all-in-one" -:model "EP-702A" +:model "DS-30" :interface "USB" -:usbid "0x04b8" "0x0850" +:usbid "0x04b8" "0x0147" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" +:model "EP-702A" +:interface "USB" +:usbid "0x04b8" "0x0850" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-703A" +:interface "USB" +:usbid "0x04b8" "0x0862" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-704A" +:interface "USB" +:usbid "0x04b8" "0x0878" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-705A" +:interface "USB" +:usbid "0x04b8" "0x089f" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-774A" +:interface "USB" +:usbid "0x04b8" "0x0893" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-775A" +:interface "USB" +:usbid "0x04b8" "0x089e" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-775AW" +:interface "USB" +:usbid "0x04b8" "0x089e" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "EP-801A" :interface "USB Network" :usbid "0x04b8" "0x0846" @@ -112,8 +202,56 @@ :model "EP-802A" :interface "USB" :usbid "0x04b8" "0x0852" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-803A" +:interface "USB" +:usbid "0x04b8" "0x0861" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-803AW" +:interface "USB" +:usbid "0x04b8" "0x0861" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-804A" +:interface "USB" +:usbid "0x04b8" "0x087b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-804AR" +:interface "USB" +:usbid "0x04b8" "0x087b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-804AW" +:interface "USB" +:usbid "0x04b8" "0x087b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-805A" +:interface "USB" +:usbid "0x04b8" "0x089c" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-805AR" +:interface "USB" +:usbid "0x04b8" "0x089c" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-805AW" +:interface "USB" +:usbid "0x04b8" "0x089c" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-901A" :interface "USB" @@ -130,8 +268,44 @@ :model "EP-902A" :interface "USB" :usbid "0x04b8" "0x0853" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-903A" +:interface "USB" +:usbid "0x04b8" "0x0860" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-903F" +:interface "USB" +:usbid "0x04b8" "0x0860" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-904A" +:interface "USB" +:usbid "0x04b8" "0x0879" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-904F" +:interface "USB" +:usbid "0x04b8" "0x0879" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-905A" +:interface "USB" +:usbid "0x04b8" "0x089b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "EP-905F" +:interface "USB" +:usbid "0x04b8" "0x089a" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ES-300C" :interface "SCSI parallel" @@ -214,12 +388,28 @@ :status :good :comment "network interface unsupported
IEEE1394 untested" +:model "ES-D200" +:interface "USB" +:usbid "0x04b8" "0x0137" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" + +:model "ES-D350" +:interface "USB" +:usbid "0x04b8" "0x0144" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" + :model "ES-D400" :interface "USB" :usbid "0x04b8" "0x0136" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" + +:model "ES-G11000" +:interface "USB" +:usbid "0x04b8" "0x014b" +:status :good :model "ES-H300" :interface "USB" @@ -230,8 +420,8 @@ :model "ES-H7200" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :good +:comment "network interface supported via DFSG non-free iscan-network-nt package" :model "Expression 636" :interface "SCSI" @@ -291,6 +481,12 @@ :status :untested :comment "network interface probably supported" +:model "Expression 11000XL" +:interface "USB" +:usbid "0x04b8" "0x014b" +:status :good +:comment "overseas version of the ES-G11000" + :model "F-3200" ; product spec (JP) :interface "USB IEEE1394" :usbid "0x04b8" "0x080a" @@ -311,7 +507,6 @@ :usbid "0x04b8" "0x0133" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-2200" :interface "USB" @@ -372,14 +567,12 @@ :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-7300U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-7400U" ; product spec (JP) :interface "USB" @@ -461,7 +654,6 @@ :usbid "0x04b8" "0x0116" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-9500" :interface "SCSI" @@ -472,16 +664,14 @@ :status :complete :model "GT-9700F" ; product spec (JP) -:interface "USB" +:interface "USB IEEE1394" :usbid "0x04b8" "0x0112" :status :complete -:comment "IEEE1394 untested" :model "GT-9800F" ; product spec (JP) -:interface "USB" +:interface "USB IEEE1394" :usbid "0x04b8" "0x011c" :status :complete -:comment "IEEE1394 untested" :model "GT-10000" :interface "SCSI" @@ -490,7 +680,6 @@ :model "GT-10000+" ; command spec :interface "SCSI" -:scsi "EPSON" "SCANNER GT-10000" "processor" :status :good :comment "IEEE1394 untested
overseas version of the ES-6000H" @@ -508,8 +697,8 @@ :model "GT-20000" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :good +:comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the ES-H7200" :model "GT-30000" ; command spec :interface "SCSI" @@ -521,98 +710,120 @@ :usbid "0x04b8" "0x0133" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F500" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F520" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F570" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F600" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0118" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F650" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F670" :interface "USB" :usbid "0x04b8" "0x012e" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F700" :interface "USB" :usbid "0x04b8" "0x012f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-F720" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" + +:model "GT-F730" +:interface "USB" +:usbid "0x04b8" "0x0142" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" + +:model "GT-F740" +:interface "USB" +:usbid "0x04b8" "0x014a" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S50" :interface "USB" :usbid "0x04b8" "0x0137" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" + +:model "GT-S55" +:interface "USB" +:usbid "0x04b8" "0x0143" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S80" :interface "USB" :usbid "0x04b8" "0x0136" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" + +:model "GT-S85" +:interface "USB" +:usbid "0x04b8" "0x0144" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S600" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-S620" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" + +:model "GT-S630" +:interface "USB" +:usbid "0x04b8" "0x0142" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" + +:model "GT-S640" +:interface "USB" +:usbid "0x04b8" "0x014a" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" :model "GT-X700" ; product spec (JP) :interface "USB" @@ -625,14 +836,12 @@ :usbid "0x04b8" "0x0119" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-X770" :interface "USB" :usbid "0x04b8" "0x0130" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-X800" ; product spec (JP) :interface "USB" @@ -645,7 +854,6 @@ :usbid "0x04b8" "0x013a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "GT-X900" :interface "USB" @@ -659,6 +867,60 @@ :status :good :comment "IEEE1394 untested" +:model "K200 Series" +:interface "USB" +:usbid "0x04b8" "0x0871" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "K300 Series" +:interface "USB" +:usbid "0x04b8" "0x0872" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "L200 Series" +:interface "USB" +:usbid "0x04b8" "0x0873" +:status :complete +:comment "all-in-one" + +:model "L210 Series" +:interface "USB" +:usbid "0x04b8" "0x08a1" +:status :complete +:comment "all-in-one" + +:model "L350" +:interface "USB" +:usbid "0x04b8" "0x08a1" +:status :complete +:comment "all-in-one" + +:model "L351" +:interface "USB" +:usbid "0x04b8" "0x08a1" +:status :complete +:comment "all-in-one" + +:model "L355" +:interface "USB" +:usbid "0x04b8" "0x08a8" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "L358" +:interface "USB" +:usbid "0x04b8" "0x08a8" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "L550" +:interface "USB" +:usbid "0x04b8" "0x08a9" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "LP-7900CS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" @@ -711,6 +973,12 @@ :status :good :comment "network interface probably supported
business all-in-one" +:model "LP-M5300 Series" +:interface "USB" +:usbid "0x04b8" "0x0894" +:status :good +:comment "network interface probably supported
business all-in-one" + :model "LP-M5500" :interface "USB" :usbid "0x04b8" "0x0817" @@ -735,6 +1003,12 @@ :status :good :comment "network interface probably supported
business all-in-one" +:model "M200 Series" +:interface "USB" +:usbid "0x04b8" "0x08aa" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "ME 200" :interface "USB" :usbid "0x04b8" "0x0830" @@ -747,17 +1021,65 @@ :status :good :comment "all-in-one
overseas version of the PX-401A" +:model "ME 320 Series" +:interface "USB" +:usbid "0x04b8" "0x085c" +:status :complete +:comment "all-in-one" + +:model "ME 330 Series" +:interface "USB" +:usbid "0x04b8" "0x085c" +:status :complete +:comment "all-in-one" + +:model "ME 340 Series" +:interface "USB" +:usbid "0x04b8" "0x0883" +:status :complete +:comment "all-in-one" + :model "ME OFFICE 510" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" +:model "ME OFFICE 520 Series" +:interface "USB" +:usbid "0x04b8" "0x0865" +:status :complete +:comment "all-in-one" + +:model "ME OFFICE 535" +:interface "USB" +:usbid "0x04b8" "0x0881" +:status :complete +:comment "all-in-one
overseas version of the PX-404A" + +:model "ME OFFICE 560W Series" +:interface "USB" +:usbid "0x04b8" "0x0864" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "ME OFFICE 570W Series" +:interface "USB" +:usbid "0x04b8" "0x0880" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-434A" + :model "ME Office 600F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "all-in-one" +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "ME OFFICE 620F Series" +:interface "USB" +:usbid "0x04b8" "0x0863" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 650FN Series" :interface "USB" @@ -771,6 +1093,48 @@ :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" +:model "ME OFFICE 900WD Series" +:interface "USB" +:usbid "0x04b8" "0x085e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" + +:model "ME OFFICE 940FW Series" +:interface "USB" +:usbid "0x04b8" "0x0890" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "ME OFFICE 960FWD Series" +:interface "USB" +:usbid "0x04b8" "0x085d" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "ME-101" +:interface "USB" +:usbid "0x04b8" "0x08a0" +:status :complete +:comment "all-in-one" + +:model "ME-301" +:interface "USB" +:usbid "0x04b8" "0x0896" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "ME-303" +:interface "USB" +:usbid "0x04b8" "0x0897" +:status :complete +:comment "all-in-one
overseas version of the PX-405A" + +:model "ME-401" +:interface "USB" +:usbid "0x04b8" "0x0898" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" + :model "PM-A700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0814" @@ -861,17 +1225,65 @@ :status :good :comment "all-in-one
PM-A970 with network interface" -:model "PX-401A" +:model "PX-045A" :interface "USB" -:usbid "0x04b8" "0x0841" -:status :good +:usbid "0x04b8" "0x0895" +:status :complete :comment "all-in-one" -:model "PX-402A" +:model "PX-1600F" :interface "USB" -:usbid "0x04b8" "0x084d" -:status :good -:comment "all-in-one" +:usbid "0x04b8" "0x0869" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-1700F" +:interface "USB" +:usbid "0x04b8" "0x087c" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-401A" +:interface "USB" +:usbid "0x04b8" "0x0841" +:status :good +:comment "all-in-one" + +:model "PX-402A" +:interface "USB" +:usbid "0x04b8" "0x084d" +:status :good +:comment "all-in-one" + +:model "PX-403A" +:interface "USB" +:usbid "0x04b8" "0x087f" +:status :complete +:comment "all-in-one" + +:model "PX-404A" +:interface "USB" +:usbid "0x04b8" "0x0881" +:status :complete +:comment "all-in-one" + +:model "PX-405A" +:interface "USB" +:usbid "0x04b8" "0x0897" +:status :complete +:comment "all-in-one" + +:model "PX-434A" +:interface "USB" +:usbid "0x04b8" "0x0880" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-435A" +:interface "USB" +:usbid "0x04b8" "0x0898" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-501A" :interface "USB" @@ -885,12 +1297,66 @@ :status :good :comment "all-in-one" +:model "PX-503A" +:interface "USB" +:usbid "0x04b8" "0x085e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-504A" +:interface "USB" +:usbid "0x04b8" "0x0891" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-505F" +:interface "USB" +:usbid "0x04b8" "0x08a5" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-535F" +:interface "USB" +:usbid "0x04b8" "0x08a6" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "PX-601F" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported" +:model "PX-602F" +:interface "USB" +:usbid "0x04b8" "0x0855" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-603F" +:interface "USB" +:usbid "0x04b8" "0x085d" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-605F" +:interface "USB" +:usbid "0x04b8" "0x0899" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-673F" +:interface "USB" +:usbid "0x04b8" "0x086a" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "PX-675F" +:interface "USB" +:usbid "0x04b8" "0x0899" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "PX-A550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x080e" @@ -927,6 +1393,12 @@ :status :good :comment "all-in-one" +:model "PX-B750F" +:interface "USB" +:usbid "0x04b8" "0x087d" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "PX-FA700" :interface "USB" :usbid "0x04b8" "0x083a" @@ -995,28 +1467,24 @@ :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 1250 PHOTO" :interface "USB" :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 1260" :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 1260 PHOTO" :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 1270" :interface "USB" @@ -1077,9 +1545,8 @@ :comment "overseas version of the GT-9300UF" :model "Perfection 2450 PHOTO" ; command spec -:interface "USB IEEE-1394" +:interface "USB IEEE1394" :usbid "0x04b8" "0x0112" -:scsi "EPSON" "GT-9700" "processor" :status :complete :comment "overseas version of the GT-9700F" @@ -1088,26 +1555,22 @@ :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 2580 PHOTO" :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 3170 PHOTO" :interface "USB" :usbid "0x04b8" "0x0116" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 3200 PHOTO" ; command spec -:interface "USB IEEE-1394" +:interface "USB IEEE1394" :usbid "0x04b8" "0x011c" -:scsi "EPSON" "GT-9800" "processor" :status :complete :comment "overseas version of the GT-9800F" @@ -1116,28 +1579,24 @@ :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 3590 PHOTO" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 4180 PHOTO" :interface "USB" :usbid "0x04b8" "0x0118" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 4490 PHOTO" :interface "USB" :usbid "0x04b8" "0x0119" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection 4870 PHOTO" ; command spec :interface "USB" @@ -1161,56 +1620,72 @@ :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection V30" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" + +:model "Perfection V33" +:interface "USB" +:usbid "0x04b8" "0x0142" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" + +:model "Perfection V37" +:interface "USB" +:usbid "0x04b8" "0x014a" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V100 Photo" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection V200 Photo" :interface "USB" :usbid "0x04b8" "0x012e" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection V300 Photo" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" + +:model "Perfection V330 Photo" +:interface "USB" +:usbid "0x04b8" "0x0142" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" + +:model "Perfection V370 Photo" +:interface "USB" +:usbid "0x04b8" "0x014a" +:status :unsupported +:comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V350 Photo" :interface "USB" :usbid "0x04b8" "0x012f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection V500 Photo" :interface "USB" :usbid "0x04b8" "0x0130" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection V600 Photo" :interface "USB" :usbid "0x04b8" "0x013a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Perfection V700 Photo" :interface "USB" @@ -1312,14 +1787,12 @@ :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Stylus CX4400" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Stylus CX4500" :interface "USB" @@ -1386,14 +1859,12 @@ :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Stylus CX5600" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Stylus CX5700F" :interface "USB" @@ -1531,7 +2002,6 @@ :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" -:url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" :model "Stylus DX4800" :interface "USB" @@ -1585,7 +2055,25 @@ :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "all-in-one" +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office BX305F" +:interface "USB" +:usbid "0x04b8" "0x0863" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office BX305FW" +:interface "USB" +:usbid "0x04b8" "0x0863" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office BX305FW Plus" +:interface "USB" +:usbid "0x04b8" "0x0870" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX310FN Series" :interface "USB" @@ -1593,6 +2081,30 @@ :status :good :comment "all-in-one" +:model "Stylus Office BX320FW Series" +:interface "USB" +:usbid "0x04b8" "0x085f" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office BX535WD" +:interface "USB" +:usbid "0x04b8" "0x0891" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" + +:model "Stylus Office BX630FW Series" +:interface "USB" +:usbid "0x04b8" "0x0890" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office BX525WD" +:interface "USB" +:usbid "0x04b8" "0x085e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" + :model "Stylus Office BX600FW" :interface "USB" :usbid "0x04b8" "0x0847" @@ -1602,14 +2114,44 @@ :model "Stylus Office BX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" + +:model "Stylus Office BX625FWD" +:interface "USB" +:usbid "0x04b8" "0x085d" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office BX635FWD" +:interface "USB" +:usbid "0x04b8" "0x088f" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office BX925FWD" +:interface "USB" +:usbid "0x04b8" "0x086a" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-673F" + +:model "Stylus Office BX935FWD" +:interface "USB" +:usbid "0x04b8" "0x0892" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX300F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "all-in-one" +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus Office TX320F Series" +:interface "USB" +:usbid "0x04b8" "0x0863" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX510FN Series" :interface "USB" @@ -1617,6 +2159,12 @@ :status :good :comment "all-in-one" +:model "Stylus Office TX525FW" +:interface "USB" +:usbid "0x04b8" "0x085f" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "Stylus Office TX600FW" :interface "USB" :usbid "0x04b8" "0x0847" @@ -1626,14 +2174,26 @@ :model "Stylus Office TX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" + +:model "Stylus Office TX620FWD Series" +:interface "USB" +:usbid "0x04b8" "0x085d" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Photo PX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-702A" + +:model "Stylus Photo PX660 Series" +:interface "USB" +:usbid "0x04b8" "0x0862" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-703A" :model "Stylus Photo PX700W" :interface "USB Network" @@ -1644,8 +2204,20 @@ :model "Stylus Photo PX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" + +:model "Stylus Photo PX720WD Series" +:interface "USB" +:usbid "0x04b8" "0x0861" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" + +:model "Stylus Photo PX730WD Series" +:interface "USB" +:usbid "0x04b8" "0x087b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Stylus Photo PX800FW" :interface "USB" @@ -1656,8 +2228,20 @@ :model "Stylus Photo PX810FW Series" :interface "USB" :usbid "0x04b8" "0x0853" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-902A" + +:model "Stylus Photo PX820FWD Series" +:interface "USB" +:usbid "0x04b8" "0x0860" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" + +:model "Stylus Photo PX830FWD Series" +:interface "USB" +:usbid "0x04b8" "0x0879" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-904F" :model "Stylus Photo RX420" :interface "USB" @@ -1794,8 +2378,8 @@ :model "Stylus Photo TX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-702A" :model "Stylus Photo TX700W" :interface "USB" @@ -1806,8 +2390,20 @@ :model "Stylus Photo TX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" + +:model "Stylus Photo TX720WD Series" +:interface "USB" +:usbid "0x04b8" "0x0861" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" + +:model "Stylus Photo TX730WD Series" +:interface "USB" +:usbid "0x04b8" "0x087b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Stylus Photo TX800FW" :interface "USB" @@ -1815,6 +2411,12 @@ :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-901A" +:model "Stylus Photo TX820FWD Series" +:interface "USB" +:usbid "0x04b8" "0x0860" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" + :model "Stylus NX100" :interface "USB" :usbid "0x04b8" "0x0841" @@ -1827,6 +2429,24 @@ :status :good :comment "all-in-one
overseas version of the PX-402A" +:model "Stylus NX125" +:interface "USB" +:usbid "0x04b8" "0x085c" +:status :complete +:comment "all-in-one" + +:model "Stylus NX127" +:interface "USB" +:usbid "0x04b8" "0x085c" +:status :complete +:comment "all-in-one" + +:model "Stylus NX130 Series" +:interface "USB" +:usbid "0x04b8" "0x0883" +:status :complete +:comment "all-in-one" + :model "Stylus NX200" :interface "USB" :usbid "0x04b8" "0x0849" @@ -1839,11 +2459,29 @@ :status :good :comment "all-in-one" -:model "Stylus NX300" +:model "Stylus NX220 Series" +:interface "USB" +:usbid "0x04b8" "0x0865" +:status :complete +:comment "all-in-one" + +:model "Stylus NX230 Series" +:interface "USB" +:usbid "0x04b8" "0x0885" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus NX300 Series" :interface "USB" :usbid "0x04b8" "0x0848" :status :good -:comment "all-in-one" +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus NX330 Series" +:interface "USB" +:usbid "0x04b8" "0x0880" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX400" :interface "USB" @@ -1857,12 +2495,42 @@ :status :good :comment "network interface probably supported
all-in-one" +:model "Stylus NX420 Series" +:interface "USB" +:usbid "0x04b8" "0x0864" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus NX430W Series" +:interface "USB" +:usbid "0x04b8" "0x0884" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "Stylus NX510 Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" +:model "Stylus NX530 Series" +:interface "USB" +:usbid "0x04b8" "0x0891" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-504A" + +:model "Stylus NX625" +:interface "USB" +:usbid "0x04b8" "0x085e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" + +:model "Stylus NX635" +:interface "USB" +:usbid "0x04b8" "0x0891" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" + :model "Stylus SX100" :interface "USB" :usbid "0x04b8" "0x0841" @@ -1878,7 +2546,13 @@ :model "Stylus SX125" :interface "USB" :usbid "0x04b8" "0x085c" -:status :untested +:status :complete +:comment "all-in-one" + +:model "Stylus SX130 Series" +:interface "USB" +:usbid "0x04b8" "0x0883" +:status :complete :comment "all-in-one" :model "Stylus SX200" @@ -1899,6 +2573,24 @@ :status :good :comment "all-in-one" +:model "Stylus SX218" +:interface "USB" +:usbid "0x04b8" "0x0865" +:status :complete +:comment "all-in-one" + +:model "Stylus SX230 Series" +:interface "USB" +:usbid "0x04b8" "0x0881" +:status :complete +:comment "all-in-one
overseas version of the PX-404A" + +:model "Stylus SX235W" +:interface "USB" +:usbid "0x04b8" "0x0885" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "Stylus SX400" :interface "USB" :usbid "0x04b8" "0x084a" @@ -1917,12 +2609,42 @@ :status :good :comment "network interface probably supported
all-in-one" +:model "Stylus SX420W Series" +:interface "USB" +:usbid "0x04b8" "0x0864" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus SX430W Series" +:interface "USB" +:usbid "0x04b8" "0x0880" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus SX440W Series" +:interface "USB" +:usbid "0x04b8" "0x0884" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "Stylus SX510W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" +:model "Stylus SX525WD" +:interface "USB" +:usbid "0x04b8" "0x085e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" + +:model "Stylus SX535WD" +:interface "USB" +:usbid "0x04b8" "0x0891" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" + :model "Stylus SX600FW" :interface "USB" :usbid "0x04b8" "0x0847" @@ -1932,8 +2654,14 @@ :model "Stylus SX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" + +:model "Stylus SX620FW Series" +:interface "USB" +:usbid "0x04b8" "0x085d" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Scan 2000" :interface "USB" @@ -1959,6 +2687,18 @@ :status :good :comment "all-in-one
overseas version of the PX-402A" +:model "Stylus TX120 Series" +:interface "USB" +:usbid "0x04b8" "0x085c" +:status :complete +:comment "all-in-one" + +:model "Stylus TX130 Series" +:interface "USB" +:usbid "0x04b8" "0x0883" +:status :complete +:comment "all-in-one" + :model "Stylus TX200" :interface "USB" :usbid "0x04b8" "0x0849" @@ -1983,6 +2723,24 @@ :status :good :comment "all-in-one" +:model "Stylus TX220 Series" +:interface "USB" +:usbid "0x04b8" "0x0865" +:status :complete +:comment "all-in-one" + +:model "Stylus TX230W Series" +:interface "USB" +:usbid "0x04b8" "0x0885" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus TX235" +:interface "USB" +:usbid "0x04b8" "0x0881" +:status :complete +:comment "all-in-one
overseas version of the PX-404A" + :model "Stylus TX400" :interface "USB" :usbid "0x04b8" "0x084a" @@ -1995,24 +2753,174 @@ :status :good :comment "network interface probably supported
all-in-one" +:model "Stylus TX420W Series" +:interface "USB" +:usbid "0x04b8" "0x0864" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus TX430W Series" +:interface "USB" +:usbid "0x04b8" "0x0880" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "Stylus TX435W" +:interface "USB" +:usbid "0x04b8" "0x0884" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "Stylus TX550W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" +:model "Stylus TX560WD Series" +:interface "USB" +:usbid "0x04b8" "0x085e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" + +:model "WF-2510 Series" +:interface "USB" +:usbid "0x04b8" "0x08a5" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-505F" + +:model "WF-2520 Series" +:interface "USB" +:usbid "0x04b8" "0x08a6" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" + +:model "WF-2530 Series" +:interface "USB" +:usbid "0x04b8" "0x08a6" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" + +:model "WF-2540 Series" +:interface "USB" +:usbid "0x04b8" "0x08a6" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" + +:model "WF-3520 Series" +:interface "USB" +:usbid "0x04b8" "0x0899" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-605F" + +:model "WF-3530 Series" +:interface "USB" +:usbid "0x04b8" "0x0899" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-675F" + +:model "WF-3540 Series" +:interface "USB" +:usbid "0x04b8" "0x0899" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "WF-7510 Series" +:interface "USB" +:usbid "0x04b8" "0x0869" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-1600F" + +:model "WF-7520 Series" +:interface "USB" +:usbid "0x04b8" "0x087c" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-1700F" + +:model "WF-M1560 Series" +:interface "USB" +:usbid "0x04b8" "0x08ab" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "WP-4511" +:interface "USB" +:usbid "0x04b8" "0x087d" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" + +:model "WP-4515" +:interface "USB" +:usbid "0x04b8" "0x087d" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "WP-4521" +:interface "USB" +:usbid "0x04b8" "0x087d" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" + +:model "WP-4525" +:interface "USB" +:usbid "0x04b8" "0x087d" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" + +:model "WP-4530 Series" +:interface "USB" +:usbid "0x04b8" "0x087d" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" + +:model "WP-4540 Series" +:interface "USB" +:usbid "0x04b8" "0x087d" +:status :complete +:comment "network interface option supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" + +:model "WP-4590 Series" +:interface "USB" +:usbid "0x04b8" "0x087e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "WorkForce 310 Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" +:model "WorkForce 320 Series" +:interface "USB" +:usbid "0x04b8" "0x0863" +:status :complete +:comment "network interface (option) supported via DFSG non-free iscan-network-nt package
some models in the series have a built-in network interface
all-in-one" + +:model "WorkForce 435" +:interface "USB" +:usbid "0x04b8" "0x0870" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "WorkForce 500" :interface "USB" :usbid "0x04b8" "0x084c" :status :good :comment "all-in-one" +:model "WorkForce 520 Series" +:interface "USB" +:usbid "0x04b8" "0x085f" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "WorkForce 545" +:interface "USB" +:usbid "0x04b8" "0x0890" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + :model "WorkForce 600" :interface "USB" :usbid "0x04b8" "0x0847" @@ -2022,6 +2930,166 @@ :model "WorkForce 610 Series" :interface "USB" :usbid "0x04b8" "0x0855" -:status :unsupported -:comment "supported by the epkowa backend plus non-free interpreter" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" + +:model "WorkForce 625" +:interface "USB" +:usbid "0x04b8" "0x085e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" + +:model "WorkForce 630 Series" +:interface "USB" +:usbid "0x04b8" "0x085d" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "WorkForce 645" +:interface "USB" +:usbid "0x04b8" "0x088f" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "WorkForce 840 Series" +:interface "USB" +:usbid "0x04b8" "0x086a" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-673F" + +:model "WorkForce 845" +:interface "USB" +:usbid "0x04b8" "0x0892" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "WorkForce K301" +:interface "USB" +:usbid "0x04b8" "0x0872" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "XP-100 Series" +:interface "USB" +:usbid "0x04b8" "0x0895" +:status :complete +:comment "all-in-one
overseas version of the PX-045A" + +:model "XP-200 Series" +:interface "USB" +:usbid "0x04b8" "0x0896" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "XP-211" +:interface "USB" +:usbid "0x04b8" "0x08ae" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "XP-212" +:interface "USB" +:usbid "0x04b8" "0x08ae" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "XP-215" +:interface "USB" +:usbid "0x04b8" "0x08ae" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "XP-300 Series" +:interface "USB" +:usbid "0x04b8" "0x0898" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" + +:model "XP-310 Series" +:interface "USB" +:usbid "0x04b8" "0x08af" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package" + +:model "XP-400 Series" +:interface "USB" +:usbid "0x04b8" "0x0898" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" + +:model "XP-410 Series" +:interface "USB" +:usbid "0x04b8" "0x08b0" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "XP-600 Series" +:interface "USB" +:usbid "0x04b8" "0x089e" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-775A" + +:model "XP-700 Series" +:interface "USB" +:usbid "0x04b8" "0x089d" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" + +:model "XP-750 Series" +:interface "USB" +:usbid "0x04b8" "0x089c" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-805A/EP-805AR/EP-805AW" + +:model "XP-800 Series" +:interface "USB" +:usbid "0x04b8" "0x089b" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-905A" + +:model "XP-850 Series" +:interface "USB" +:usbid "0x04b8" "0x089a" +:status :complete +:comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-905F" + +:model "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 diff --git a/doc/descriptions/fujitsu.desc b/doc/descriptions/fujitsu.desc index 1691ad5..e74a7f6 100644 --- a/doc/descriptions/fujitsu.desc +++ b/doc/descriptions/fujitsu.desc @@ -12,9 +12,9 @@ :backend "fujitsu" ; name of backend :url "http://www.thebility.com/fujitsu/" -:version "117" ; version of backend +:version "118" ; version of backend :manpage "sane-fujitsu" ; name of manpage (if it exists) -:comment "Backend updated for SANE release 1.0.24, see sane-fujitsu manpage" +:comment "Backend updated for SANE release 1.0.25, see sane-fujitsu manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api @@ -143,6 +143,18 @@ :usbid "0x04c5" "0x1150" :comment "small, recent, discontinued" +:model "fi-6130Z" +:interface "USB" +:status :complete +:usbid "0x04c5" "0x11f3" +:comment "small, recent, discontinued" + +:model "fi-6230Z" +:interface "USB" +:status :complete +:usbid "0x04c5" "0x11f4" +:comment "small, recent, discontinued" + :model "ScanSnap S1500" :interface "USB" :status :complete @@ -173,16 +185,16 @@ :usbid "0x04c5" "0x11fc" :comment "small, current" -:model "fi-6130Z" +:model "fi-7160" :interface "USB" :status :complete -:usbid "0x04c5" "0x11f3" +:usbid "0x04c5" "0x132e" :comment "small, current" -:model "fi-6230Z" +:model "fi-7260" :interface "USB" :status :complete -:usbid "0x04c5" "0x11f4" +:usbid "0x04c5" "0x132f" :comment "small, current" :model "ScanSnap iX500" @@ -311,6 +323,18 @@ :usbid "0x04c5" "0x11f2" :comment "medium, current" +:model "fi-7180" +:interface "USB" +:status :complete +:usbid "0x04c5" "0x132c" +:comment "medium, current" + +:model "fi-7280" +:interface "USB" +:status :complete +:usbid "0x04c5" "0x132d" +:comment "medium, current" + ;================================================== ; DISCONTINUED OLDER MODELS, BIG :model "M3099A" diff --git a/doc/descriptions/genesys.desc b/doc/descriptions/genesys.desc index 4cb2fc0..eb060f6 100644 --- a/doc/descriptions/genesys.desc +++ b/doc/descriptions/genesys.desc @@ -79,7 +79,7 @@ :model "ScanJet 4850C" :interface "USB" :usbid "0x03f0" "0x1b05" -:status :untested +:status :good :comment "resolution from 100 to 2400 supported, UTA not supported yet" :model "ScanJet G4010" @@ -127,6 +127,12 @@ :usbid "0x04a9" "0x221c" :status :good +:model "CanoScan LiDE 80" +:interface "USB" +:usbid "0x04a9" "0x2214" +:status :basic +:comment "No 2400 dpi support, slow speed at lower resolution" + :model "CanoScan LiDE 100" :interface "USB" :usbid "0x04a9" "0x1904" diff --git a/doc/descriptions/kodakaio.desc b/doc/descriptions/kodakaio.desc index 7882513..5fb18ed 100644 --- a/doc/descriptions/kodakaio.desc +++ b/doc/descriptions/kodakaio.desc @@ -1,6 +1,6 @@ :backend "kodakaio" :url "http://sourceforge.net/projects/cupsdriverkodak/" -:version "2.4.6" +:version "2.4.7" :manpage "sane-kodakaio" :comment "Backend for Kodak AiO ESP and Hero printers. Also possibly Advent AWL10" :devicetype :scanner diff --git a/doc/descriptions/pixma.desc b/doc/descriptions/pixma.desc index 5983b0a..f354ada 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.4" ; version of backend (or "unmaintained") +:version "0.17.14" ; version of backend (or "unmaintained") :manpage "sane-pixma" ; name of manpage (if it exists) :url "http://home.arcor.de/wittawat/pixma/" ; 0.13.2 backend's web page :url "http://mp610.blogspot.com/" ; the pixma backend blog @@ -24,6 +24,18 @@ :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" +:model "PIXMA E400" +:interface "USB" +:usbid "0x04a9" "0x177a" +:status :untested +:comment "Testers needed!" + +:model "PIXMA E460 Series" +:interface "USB" +:usbid "0x04a9" "0x1788" +:status :untested +:comment "Testers needed!" + :model "PIXMA E500" :interface "USB" :usbid "0x04a9" "0x1758" @@ -36,6 +48,12 @@ :status :untested :comment "Testers needed!" +:model "PIXMA E560" +:interface "USB" +:usbid "0x04a9" "0x177b" +:status :untested +:comment "Testers needed!" + :model "PIXMA E600" :interface "USB" :usbid "0x04a9" "0x175a" @@ -63,8 +81,8 @@ :model "PIXMA MG2400 Series" :interface "USB" :usbid "0x04a9" "0x176c" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "All resolutions supported (up to 600DPI)." :model "PIXMA MG2500 Series" :interface "USB" @@ -72,23 +90,29 @@ :status :untested :comment "Testers needed!" +:model "PIXMA MG2900 Series" +:interface "USB WiFi" +:usbid "0x04a9" "0x1780" +:status :complete +:comment "All resolutions supported (up to 600DPI)." + :model "PIXMA MG3100 Series" -:interface "USB WLAN" +:interface "USB WiFi" :usbid "0x04a9" "0x1752" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG3200 Series" -:interface "USB" +:interface "USB WiFi" :usbid "0x04a9" "0x1762" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG3500 Series" -:interface "USB" +:interface "USB WiFi" :usbid "0x04a9" "0x176e" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG4100 Series" :interface "USB" @@ -127,8 +151,14 @@ :comment "Testers needed!" :model "PIXMA MG5500 Series" -:interface "USB" +:interface "USB WiFi" :usbid "0x04a9" "0x1771" +:status :complete +:comment "All resolutions supported (up to 1200DPI)." + +:model "PIXMA MG5600 Series" +:interface "USB" +:usbid "0x04a9" "0x177f" :status :untested :comment "Testers needed!" @@ -162,9 +192,21 @@ :status :untested :comment "Testers needed!" +:model "PIXMA MG6600 Series" +:interface "USB" +:usbid "0x04a9" "0x177e" +:status :untested +:comment "Testers needed!" + :model "PIXMA MG7100 Series" :interface "USB" :usbid "0x04a9" "0x1772" +:status :complete +:comment "All resolutions supported (up to 2400DPI)." + +:model "PIXMA MG7500 Series" +:interface "USB" +:usbid "0x04a9" "0x177c" :status :untested :comment "Testers needed!" @@ -545,7 +587,7 @@ :interface "USB" :usbid "0x04a9" "0x174d" :status :complete -:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy." +:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX370 Series" :interface "USB" @@ -560,16 +602,16 @@ :comment "Testers needed!" :model "PIXMA MX410" -:interface "USB Ethernet" +:interface "USB Ethernet WiFi" :usbid "0x04a9" "0x174e" -:status :untested -:comment "Same protocol as Pixma MX420? Testers needed!" +:status :complete +:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX420" :interface "USB Ethernet" :usbid "0x04a9" "0x174f" :status :complete -:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy." +:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX430 Series" :interface "USB Ethernet" @@ -583,17 +625,29 @@ :status :untested :comment "Testers needed!" -:model "PIXMA MX510 Series" +:model "PIXMA MX470 Series" :interface "USB Ethernet" -:usbid "0x04a9" "0x175c" +:usbid "0x04a9" "0x1774" :status :untested :comment "Testers needed!" +:model "PIXMA MX510 Series" +:interface "USB Ethernet" +:usbid "0x04a9" "0x175c" +:status :complete +:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." + :model "PIXMA MX520 Series" -:interface "USB" +:interface "USB Ethernet WiFi" :usbid "0x04a9" "0x1769" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." + +:model "PIXMA MX530 Series" +:interface "USB WiFi" +:usbid "0x04a9" "0x1775" +:status :complete +:comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX700" :interface "USB Ethernet" @@ -608,10 +662,10 @@ :comment "Testers needed!" :model "PIXMA MX720 Series" -:interface "USB" +:interface "USB Ethernet WiFi" :usbid "0x04a9" "0x176a" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX850" :interface "USB Ethernet" @@ -629,37 +683,37 @@ :interface "USB Ethernet" :usbid "0x04a9" "0x1743" :status :complete -:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." +:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX880 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete -:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." +:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX882" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete -:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." +:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX885" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete -:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." +:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX890 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175e" :status :complete -:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." +:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX920 Series" :interface "USB" :usbid "0x04a9" "0x176b" -:status :untested -:comment "Testers needed!" +:status :good +:comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX7600" :interface "USB Ethernet" @@ -679,6 +733,12 @@ :status :complete :comment "All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported." +:model "imageCLASS D530" +:interface "USB" +:usbid "0x04a9" "0x2775" +:status :complete +:comment "All resolutions supported (up to 600DPI)" + :model "i-SENSYS MF3010" :interface "USB Ethernet" :usbid "0x04a9" "0x2759" @@ -781,23 +841,17 @@ :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF empty buggy." -:model "i-SENSYS MF4550d" +:model "i-SENSYS MF4500 Series" :interface "USB" :usbid "0x04a9" "0x2736" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)." -:model "imageCLASS MF4770n" -:interface "USB Ethernet" -:usbid "0x04a9" "0x2774" -:status :good -:comment "Flatbed scan. All resolutions supported (up to 600DPI). ADF buggy." - :model "imageCLASS MF4570dw" :interface "USB" :usbid "0x04a9" "0x275a" -:status :untested -:comment "Testers needed!" +:status :complete +:comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4660" :interface "USB" @@ -811,6 +865,18 @@ :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" +:model "i-SENSYS MF4700 Series" +:interface "USB Ethernet" +:usbid "0x04a9" "0x2774" +:status :good +:comment "Flatbed scan. All resolutions supported (up to 600DPI). ADF buggy." + +:model "i-SENSYS MF4800 Series" +:interface "USB Ethernet" +:usbid "0x04a9" "0x2773" +:status :complete +:comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Ethernet buggy." + :model "imageCLASS MF5630" :interface "USB" :usbid "0x04a9" "0x264e" @@ -877,6 +943,18 @@ :status :untested :comment "Testers needed!" +:model "i-SENSYS MF8200C Series" +:interface "USB Ethernet" +:usbid "0x04a9" "0x2779" +:status :complete +:comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Note: document feeder does not have 600DPI capability." + +:model "i-SENSYS MF8500C Series" +:interface "USB Ethernet" +:usbid "0x04a9" "0x277a" +:status :untested +:comment "Same protocol as MF8200C Series? Testers needed!" + :model "imageRUNNER 1020/1024/1025" :interface "USB" :usbid "0x04a9" "0x26e6" @@ -889,6 +967,30 @@ :status :untested :comment "Testers needed!" +:model "MAXIFY MB2000 Series" +:interface "USB" +:usbid "0x04a9" "0x1778" +:status :untested +:comment "Testers needed!" + +:model "MAXIFY MB2300 Series" +:interface "USB" +:usbid "0x04a9" "0x1779" +:status :untested +:comment "Testers needed!" + +:model "MAXIFY MB5000 Series" +:interface "USB" +:usbid "0x04a9" "0x1776" +:status :untested +:comment "Testers needed!" + +:model "MAXIFY MB5300 Series" +:interface "USB" +:usbid "0x04a9" "0x1777" +:status :untested +:comment "Testers needed!" + :model "CanoScan 8800F" :interface "USB" :usbid "0x04a9" "0x1901" diff --git a/doc/descriptions/unsupported.desc b/doc/descriptions/unsupported.desc index 4f59ebf..d7e4128 100644 --- a/doc/descriptions/unsupported.desc +++ b/doc/descriptions/unsupported.desc @@ -424,13 +424,6 @@ :status :unsupported :comment "Philips chip. Backend started, see link" -:model "CanoScan LiDE 80" -:url "/unsupported/canon-lide-80.html" -:interface "USB" -:usbid "0x04a9" "0x2214" -:status :unsupported -:comment "GL841 based, to be added to genesys backend" - :model "CanoScan LiDE 90" :url "/unsupported/canon-lide-90.html" :interface "USB" @@ -788,13 +781,6 @@ :status :unsupported :comment "Not supported yet by SANE. See link for details." -:model "ScanJet 2400c" -:url "/unsupported/hp-scanjet-2400c.html" -:interface "USB" -:usbid "0x03f0" "0x0a01" -:status :unsupported -:comment "GL646 based, to be added to genesys backend" - :model "Photosmart C3180" :url "/unsupported/hp-photosmart-3180.html" :interface "USB" @@ -821,13 +807,6 @@ :comment "Not supported. See ScanJet 4600 entry." :status :unsupported -:model "ScanJet 4850C" -:url "/unsupported/hp-scanjet-4850.html" -:interface "USB" -:usbid "0x03f0" "0x1b05" -:comment "GL841, maybe can be added to genesys backend " -:status :unsupported - :model "ScanJet 4890C" :url "/unsupported/hp-scanjet-4850.html" :interface "USB" diff --git a/doc/releases.txt b/doc/releases.txt index 320c8a0..a1b5478 100644 --- a/doc/releases.txt +++ b/doc/releases.txt @@ -38,14 +38,19 @@ Making the release: * unpack tar.gz in temporary directory * make diff from last release by unpacking it also in temporary directory and running e.g. - diff -uNr sane-backends-1.0.14 sane-backends-1.0.15 > sane-backends-1.0.14-1.0.15.diff + diff -uNr sane-backends-1.0.23 sane-backends-1.0.24 > sane-backends-1.0.23-1.0.24.diff * check that the diff applies cleanly to the old version * gzip the diff * install devel headers required to build optional backends (1284,gphoto,etc) * check that the new version .tar.gz can be compiled -* upload these files together with the .diff.gz to the FTP/HTTP servers +* upload the .tar.gz, tar.gz.md5 and .diff.gz to the FTP/HTTP servers (at the moment: alioth.debian.org, ftp files are in /srv/alioth.debian.org/chroot/ftproot/pub/sane/ ) + In the alioth web interface, you should upload the smallest file first, + since you don't get error messages until after an upload completes, + and you might need to change something. + You can add the larger files afterwards. You may have to split larger + files. Announcing the release: @@ -55,15 +60,15 @@ Announcing the release: * rebuild sane-backends.html and sane-mfgs.html (make -C doc html-pages) * use man2html from http://hydra.nac.uci.edu/indiv/ehood/man2html.html to rebuild html man pages (make -C doc html-man) (no other version works) -* add md5 sum to sane-md5sum.txt +* add md5 sum to sane-md5sums.txt * check and update platforms page (sane-support.html) * add announcement to index.html * git commit -a && git push * check that website was updated automatically. if not, see: - /org/alioth.debian.org/chroot/home/groups/sane/bin/update-htdocs.sh + /home/groups/sane/bin/update-htdocs.sh * rebuild descriptions.db (make -C doc descriptions.db) * scp doc/descriptions.db to alioth: - /org/alioth.debian.org/chroot/home/groups/sane/search/release + /home/groups/sane/search/release * write announcements sane-devel, maybe others (e.g. freshmeat), include the md5 hash diff --git a/doc/sane-cardscan.man b/doc/sane-cardscan.man index 75cd161..7c081af 100644 --- a/doc/sane-cardscan.man +++ b/doc/sane-cardscan.man @@ -53,7 +53,7 @@ used by the backend: .PP "lines_per_block 16" (or other number from 1 to 32) .RS -Controls the number of lines of image data which will be aquired in each pass. +Controls the number of lines of image data which will be acquired in each pass. Older scanners will require this number set lower, often 1. .RE .PP diff --git a/doc/sane-coolscan.man b/doc/sane-coolscan.man index bf83014..5952039 100644 --- a/doc/sane-coolscan.man +++ b/doc/sane-coolscan.man @@ -39,7 +39,7 @@ permissions of that device, have a look at sane\-scsi. Some SCSI-adapters and low-level SCSI drivers do not work correctly with this backend and the Coolscan scanners. These systems hang when the autofocus command is send to the Scanner. -To see a list of which card/driver combinations work or dont work have a look at: +To see a list of which card/driver combinations work or don't work have a look at: http://andreas.rick.free.fr/sane/autofocus.html. diff --git a/doc/sane-epjitsu.man b/doc/sane-epjitsu.man index 1e201c0..ebb87e1 100644 --- a/doc/sane-epjitsu.man +++ b/doc/sane-epjitsu.man @@ -1,4 +1,4 @@ -.TH sane\-epjitsu 5 "09 Feb 2010" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" +.TH sane\-epjitsu 5 "12 Jun 2014" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-epjitsu .SH NAME @@ -7,10 +7,10 @@ sane\-epjitsu \- SANE backend for Epson-based Fujitsu USB scanners. .SH DESCRIPTION The .B sane\-epjitsu -library implements a SANE (Scanner Access Now Easy) backend which provides basic access the Fujitsu fi\-60F and ScanSnap S300/S1300 scanners. +library implements a SANE (Scanner Access Now Easy) backend which provides basic access the Fujitsu fi\-60F/fi\-65F and ScanSnap S300/S1300/S1100 scanners. .SH HARDWARE SUPPORT -These scanners are fairly limited, only supporting a couple of modes and resolutions, and always scanning full width. The backend supports missing modes (binary, grayscale) in software, but makes no effort to offer intermediate resolutions or scan area controls. See +These scanners are fairly limited, only supporting a couple of modes and resolutions, and always scanning full width. The backend supports missing modes (binary, grayscale) in software, but makes no effort to offer intermediate resolutions and only minimal scan area controls. See .B KNOWN ISSUES. This backend may support other scanners. If physical inspection reveals an Epson chipset, please contact the author for instructions on collecting a USB trace under Windows to verify. @@ -84,13 +84,10 @@ The backend uses a single environment variable, SANE_DEBUG_EPJITSU, which enable .SH KNOWN ISSUES .PP .RS -No scan area options are exposed. +Only limited scan area options are exposed. .br .br -fi\-60F hardware grayscale mode is not used. -.br -.br -The S1100 is not currently supported, but a patch is available. +fi\-60F and fi\-65F hardware grayscale mode is not used. .RE .SH CREDITS diff --git a/doc/sane-epson.man b/doc/sane-epson.man index 3790df6..d474bb7 100644 --- a/doc/sane-epson.man +++ b/doc/sane-epson.man @@ -91,7 +91,7 @@ are "None", "Halftone A (Hard Tone)", "Halftone B (Soft Tone)", "Halftone C The .I \-\-dropout -switch selects the so called dropout color. Vald options are None, +switch selects the so called dropout color. Valid options are None, Red, Green and Blue. The default is None. The dropout color is used for monochrome scanning and selects the color that is not scanned. This can be used to e.g. scan an original with a colored background. @@ -269,7 +269,7 @@ environment variable controls the SCSI related debug level for this backend. Only a value of 2 is supported. .TP .B SANE_EPSON_CMD_LVL -This allows to override the function or command level that the backend +This allows one to override the function or command level that the backend uses to communicate with the scanner. The function level a scanner supports is determined during the initialization of the device. If the backend does not recognize the function level reported by the diff --git a/doc/sane-epson2.man b/doc/sane-epson2.man index 27ee34e..896b340 100644 --- a/doc/sane-epson2.man +++ b/doc/sane-epson2.man @@ -137,7 +137,7 @@ are "None", "Halftone A (Hard Tone)", "Halftone B (Soft Tone)", "Halftone C The .I \-\-dropout -switch selects the so called dropout color. Vald options are None, +switch selects the so called dropout color. Valid options are None, Red, Green and Blue. The default is None. The dropout color is used for monochrome scanning and selects the color that is not scanned. This can be used to e.g. scan an original with a colored background. @@ -323,7 +323,7 @@ backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .TP .B SANE_EPSON2_CMD_LVL -This allows to override the function or command level that the backend +This allows one to override the function or command level that the backend uses to communicate with the scanner. The function level a scanner supports is determined during the initialization of the device. If the backend does not recognize the function level reported by the diff --git a/doc/sane-genesys.man b/doc/sane-genesys.man index 0cd1ffb..2b96483 100644 --- a/doc/sane-genesys.man +++ b/doc/sane-genesys.man @@ -48,11 +48,17 @@ GL841, GL843, GL847 or GL124 chipset, you can try to add it to the backend. .SH "CALIBRATION" To give correct image quality, sheet fed scanners need to be calibrated using the calibration sheet sold with the scanner. To do calibration, you must insert this target -in the feeder then start calibration either by passing the --calibrate option to scanimage +in the feeder then start calibration either by passing the \-\-calibrate option to scanimage or by clicking on the available 'calibrate' button in the 'advanced options' in a graphical frontend. The result of the calibration is stored in a file in the home directory of the user doing it. If you plug the scanner in another machine or use it with another account, calibration -will have to be redone. +will have to be redone, unles you use the \-\-calibration\-file option. +If no home directory is defined, +USERAPPPROFILE will be used, then TMPDIR or TMP. If none of these directories exist, the backend will try +to write in the current working directory. Flatbed scanners alos make use of the calibration file as a cache +to avoid calibration before each scan. Calibration file name is the name of the scanner model if only +one scanner is detected. In the case of several identical model, the file name will be the name +of the logical USB device name. .SH EXTRAS SCAN OPTIONS @@ -69,13 +75,13 @@ whith brightness below that value will be scanned as black. .B \-\-brightness value .RS - -100..100 (in steps of 1). Set the brightness enhancement. 0 for no enhancement, negative + \-100..100 (in steps of 1). Set the brightness enhancement. 0 for no enhancement, negative values to decrease brigthness, and positive values to increase it. .RE .B \-\-contrast value .RS - -100..100 (in steps of 1). Set the contrast enhancement. 0 for no enhancement, negative + \-100..100 (in steps of 1). Set the contrast enhancement. 0 for no enhancement, negative values to decrease contrast, and positive values to increase it. .RE @@ -112,9 +118,9 @@ next scan will happen. .B \-\-calibration\-file .RS Specify the calibration file name to use. At least the directory containing the file -must exist, since it won't be created. This allow to handle the case of several identical devices -that would otherwise use the same calibration data. This option is disabled if the backend is ran -as root. +must exist, since it won't be created. This option is disabled if the backend is ran +as root. It maybe used in case of sheet-fed scanners to share a calibration file for several +users. .RE .PP @@ -295,7 +301,7 @@ Alexey Osipov for HP2400 final support Powersaving isn't implemented for gl646 based scanner. Dynamic (emulated from gray data and with dithering) isn't enabled for gl646 scanners. Hardware lineart is limited up to 600 dpi for gl847 based scanners, due to the way image sensors are built. .br .TP -This backend will be much slower if not using libusb-1.0. So be sure that sane-backends is built with the --enable-libusb_1_0 option. +This backend will be much slower if not using libusb\-1.0. So be sure that sane\-backends is built with the \-\-enable-libusb_1_0 option. .br .SH "BUGS" diff --git a/doc/sane-gt68xx.man b/doc/sane-gt68xx.man index 4296ed4..e3d29af 100644 --- a/doc/sane-gt68xx.man +++ b/doc/sane-gt68xx.man @@ -117,7 +117,7 @@ can set the "correct" name here. .PP The .B afe -option allows to set custom offset and gain values for the Analog FrontEnd of +option allows one to set custom offset and gain values for the Analog FrontEnd of the scanner. This option can be either used to select the AFE values if automatic coarse calibration is disabled, or to make automatic coarse calibration faster. For the latter usage, enable debug level 3 (see below), diff --git a/doc/sane-kodakaio.man b/doc/sane-kodakaio.man index e5303b6..40310ed 100644 --- a/doc/sane-kodakaio.man +++ b/doc/sane-kodakaio.man @@ -1,4 +1,4 @@ -.TH sane\-kodakaio 2.4 "17 Jun 2012" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" +.TH sane\-kodakaio 5 "17 Jun 2012" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-kodakaio .SH NAME diff --git a/doc/sane-pixma.man b/doc/sane-pixma.man index b108679..c780ba8 100644 --- a/doc/sane-pixma.man +++ b/doc/sane-pixma.man @@ -1,4 +1,4 @@ -.TH "sane\-pixma" "5" "24 Sep 2013" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" +.TH "sane\-pixma" "5" "29 Oct 2014" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-pixma .SH NAME sane\-pixma \- SANE backend for Canon Multi-Function Printers and CanoScan Scanners @@ -8,16 +8,18 @@ The library implements a SANE (Scanner Access Now Easy) backend that provides access to Canon PIXMA / i-SENSYS / imageCLASS / imageRUNNER multi-function devices (All-in-one printers) and the Canon CanoScan Flatbed/TPU scanners. -The backend implements both USB interface and network interface -using Canon's BJNP protocol. The network interface supports scanners over -IPv4 as well as IPv6. +The backend implements both the USB interface and network interface +(using Canon's BJNP and MFNP protocols). The network interface supports scanners +over IPv4 as well as IPv6 (MFNP over IPv6 is untested). .PP Currently, the following models work with this backend: .PP .RS -PIXMA MG2100, MG3100, MG4200, MG5100, MG5200, MG5300 +PIXMA MG2100, MG2400, MG2900, MG3100, MG3200, MG3500, MG4200 .br -PIXMA MG6100, MG6200, MG6300, MG8200 +PIXMA MG5100, MG5200, MG5300, MG5500, MG6100, MG6200, MG6300 +.br +PIXMA MG7100, MG8200 .br PIXMA MP140, MP150, MP160, MP170, MP180, MP190 .br @@ -39,9 +41,9 @@ PIXMA MP960, MP970, MP980, MP990 .br PIXMA MX300, MX310, MX330, MX340, MX350, MX360, MX370 .br -PIXMA MX420, MX700, MX7600 +PIXMA MX410, MX420, MX510, MX520, MX530, MX700, MX720, MX7600 .br -PIXMA MX850, MX860, MX870, MX882, MX885, MX890 +PIXMA MX850, MX860, MX870, MX882, MX885, MX890, MX920 .br imageCLASS MF3110, MF3240, MF4010, MF4018 .br @@ -49,11 +51,13 @@ imageCLASS MF4120, MF4122, MF4140, MF4150 .br imageCLASS MF4270, MF4350d, MF4370dn, MF4380dn .br -imageCLASS MF4410, MF4430, MF4660, MF4690, MF4770n +imageCLASS MF4410, MF4430, MF4570dw, MF4660, MF4690 +.br +imageCLASS MF5730, MF5770, MF6550, D420, D480, D530 .br -imageCLASS MF5730, MF5770, MF6550, D420, D480 +i-SENSYS MF3010, MF4320d, MF4330d, MF4500 Series .br -i-SENSYS MF3010, MF4320d, MF4330d, MF4550d +i-SENSYS MF4700 Series, MF4800 Series, MF8200C Series .br imageRUNNER 1020/1024/1025 .br @@ -65,8 +69,6 @@ and must be switched off and on. .PP .RS PIXMA MP760, MP770, MP780, MP790 -.br -PIXMA MX360 .RE .PP The following models may use the same Pixma protocol as those listed @@ -75,23 +77,23 @@ in the backend so that they get recognized and activated. Feedback in the sane\-devel mailing list welcome. .PP .RS -PIXMA E500, E510, E600, E610 +PIXMA E400, E460, E500, E510, E560, E600, E610 .br -PIXMA MG2200, MG2400, MG2500, MG3200, MG4100, MG5400, MG5500 +PIXMA MG2200, MG2500, MG4100, MG5400, MG5600 .br -PIXMA MG6400, MG6500, MG7100, MG8100 +PIXMA MG6400, MG6500, MG6600, MG7500, MG8100 .br PIXMA MP375R, MP493, MP495, MP740 .br -PIXMA MX320, MX390, MX410, MX430, MX450, MX510, MX520 +PIXMA MX320, MX390, MX430, MX450, MX470, MX710 .br -PIXMA MX710, MX720, MX920 -.br -imageCLASS MF4570dw, MF5630, MF5650, MF5750, MF8030, MF8170c +imageCLASS MF5630, MF5650, MF5750, MF8030, MF8170c .br imageRUNNER 1133 .br -i-SENSYS MF5880dn, MF6680dn +i-SENSYS MF5880dn, MF6680dn, MF8500C Series +.br +MAXIFY MB2000, MB2300, MB5000, MB5300 .RE .PP \#The following models may use partly the same Pixma protocol as other devices @@ -119,11 +121,14 @@ The backend supports: .PP The device name for USB devices is in the form pixma:xxxxyyyy_zzzzz where x, y and z are vendor ID, product ID and serial number respectively. +.PP Example: pixma:04A91709_123456 is a MP150. .PP -Device names for BJNP devices is in the form pixma:aaaa_bbbbb +Device names for BJNP/MFNP devices is in the form pixma:aaaa_bbbbb where aaaa is the scanners model and bbbb is the hostname or ip-adress. .PP +Example: pixma:MF4800_192.168.1.45 is a MF4800 Series multi-function peripheral. +.PP This backend, based on cloning original Canon drivers protocols, is in a production stage. Designed has been carried out without any applicable manufacturer documentation, probably never available. However, we have tested @@ -136,10 +141,10 @@ provides the following \#.B experimental options for button handling, i.e. the options might change in the future. .br -The button status can be polled i.e. with 'scanimage -A'. +The button status can be polled i.e. with 'scanimage \-A'. .br Button scan is disabled on MAC OS X due to darwin libusb not handling -timeouts in usb interrupt reads. +timeouts in usb interrupt reads, but may work when using the network protocol. .TP .I button\-controlled This option can be used by applications (like @@ -154,7 +159,7 @@ first page in the scanner, press the button, then the next page, press the button and so on. When you finished, press the gray-scan button. (For MP150 you have to stop the frontend by pressing Ctrl-C for example.) .TP -.I button\-update +.I button\-update (deprecated) (write only) In the past this option was required to be set to force reading of the button status for .I button\-1 @@ -202,25 +207,36 @@ support dynamic loading). .I @CONFIGDIR@/pixma.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR -below). The files contains an optional list of scanners. Normally only scanners -that can not be auto-detected because they are on a different subnet shall be -listed here. If your OS does not allow enumeration of interfaces (i.e. it does not -support the getifaddrs() function) you may need to add your scanner here as well. +below). The files contains an optional list of networked scanners. Normally +only scanners that can not be auto-detected because they are on a different +subnet shall be listed here. If your OS does not allow enumeration of +interfaces (i.e. it does not support the getifaddrs() function) you may need +to add your scanner here as well. +.PP Scanners shall be listed as: .PP .RS -.I bjnp:// +.I ://[:port] .RE .RS -where host is the hostname or IP address of the scanner, e.g. bjnp://10.0.1.4 +.PP +where method indicates the protocol used (bjnp is used for inkjet multi-functionals +and mfnp is used for laser multi-functionals). +.PP +host is the hostname or IP address of the scanner, e.g. bjnp://10.0.1.4 for IPv4, bjnp://[2001:888:118e:18e2:21e:8fff:fe36:b64a] for a literal -IPv6-address or bjnp://myscanner.mydomain.org. Define each scanner on a new -line. +IPv6-address or bjnp://myscanner.mydomain.org for a hostname. +.PP +The port number is optional and in normally implied by the method. +Port 8610 is the standard port for mfnp, 8612 for bjnp. +.PP +Define each scanner on a new line. .SH USB SUPPORT USB scanners will be auto-detected and require no configuration. .SH NETWORKING SUPPORT The pixma backend supports network scanners using the so called Canon BJNP -protocol. Both IPv4 and IPv6 are supported. +protocol and MFNP protocol. Both IPv4 and IPv6 are supported, but IPv6 is as +yet untested with MFNP. Please report your results on the mailing list. .PP Configuration is normally not required. The pixma backend will auto-detect your scanner if it is within @@ -229,24 +245,27 @@ the same subnet as your computer if your OS does support this. If your scanner can not be auto-detected, you can add it to the pixma configuration file (see above). .SH FIREWALLING FOR NETWORKED SCANNERS -The sane pixma backend communicates with port 8612 on the scanner. So -you will have to allow outgoing traffic TO port 8612 on the common subnet -for scanning. +The sane pixma backend communicates with port 8610 for MFNP or port 8612 +for BJNP on the scanner. So +you will have to allow outgoing traffic TO port 8610 or 8612 on the +common subnet for scanning. .PP Scanner detection is slightly more complicated. The pixma backend sends a broadcast on all direct connected subnets it can find (provided your OS allows for enumeration of all netowrk interfaces). The broadcast is sent FROM -port 8612 TO port 8612 on the broadcast address of each interface. +port 8612 TO port 8610 or 8612 on the broadcast address of each interface. The outgoing packets will be allowed by the rule described above. .PP Responses from the scanner are sent back to the computer TO port 8612. Connection tracking however does not see a match as the response does not come from the broadcast address but from the scanners own address. For automatic detection of your scanner, you will therefore have to allow -incoming packets TO port 8612 on your computer. +incoming packets TO port 8612 on your computer. This applies to both MFNP and +BJNP. .PP -So in short: open the firewall for all traffic from your computer to port 8612 -AND to port 8612 to your computer. +So in short: open the firewall for all traffic from your computer to port +8610 (for MFNP) or 8612 (for BJNP) +AND to port 8612 (for both BJNP and MFNP) to your computer. .PP With the firewall rules above there is no need to add the scanner to the pixma.conf file, unless the scanner is on a network that is not directly @@ -266,6 +285,8 @@ the verbosity and includes the information printed at the lower levels. .br 3 print debug-level messages .br +4 print verbose debug-level messages +.br 11 dump USB traffic .br 21 full dump USB traffic @@ -275,8 +296,8 @@ the verbosity and includes the information printed at the lower levels. .B SANE_DEBUG_BJNP If the library was compiled with debug support enabled, this environment variable controls the debug level for the -.B BJNP -network protocol for this backend. Higher value increases +.B BJNP and MFNP +network protocols for this backend. Higher value increases the verbosity and includes the information printed at the lower levels. .RS 0 print nothing (default) diff --git a/doc/sane-scsi.man b/doc/sane-scsi.man index c1032ee..bcb7d77 100644 --- a/doc/sane-scsi.man +++ b/doc/sane-scsi.man @@ -28,7 +28,7 @@ for Epson scanners, for HP scanners, etc.). .PP For some operating systems (e.g. Linux and OS/2), there is an alternate way of -specifying scanner devices. This alternate way allows to identify scanners by +specifying scanner devices. This alternate way allows one to identify scanners by the SCSI vendor and model string and/or by the SCSI device address (consisting of bus number, channel number, id, and logical unit number). The syntax for specifying a scanner in this way is: diff --git a/doc/sane-test.man b/doc/sane-test.man index 41b9aa4..e582895 100644 --- a/doc/sane-test.man +++ b/doc/sane-test.man @@ -40,7 +40,7 @@ Setting option .B hand\-scanner results in the test-backend behaving like a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of \-1. -Setting this option allows to test whether a frontend can handle this +Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm. .PP Setting option @@ -68,7 +68,7 @@ ADF will be "empty". .SH SPECIAL OPTIONS Option .B test\-picture -allows to set the image that's returned to the frontend. While "Solid white" +allows one to set the image that's returned to the frontend. While "Solid white" and "Solid black" are quite obvious, the other options need some more explanation. Color patterns are used to determine if all modes and their colors are represented correctly by the frontend. The grid should look like the @@ -76,10 +76,10 @@ same in every mode and resolution. A table of all the test pictures can be found at: http://www.meier\-geinitz.de/sane/test\-backend/test\-pictures.html. .PP If option -.B invert\-endianess +.B invert\-endianness is set, the upper and lower bytes of image data in 16 bit modes are exchanged. This option can be used to test the 16 bit modes of frontends, e.g. if the -frontend uses the correct endianess. +frontend uses the correct endianness. .PP If option .B read\-limit diff --git a/doc/sane-umax_pp.man b/doc/sane-umax_pp.man index 2a8349d..09e6ea0 100644 --- a/doc/sane-umax_pp.man +++ b/doc/sane-umax_pp.man @@ -58,7 +58,7 @@ needs to run as root. To allow user access to the scanner run the backend through the network interface (See saned(8) and sane\-net(5)). A more relaxed solution (security wise) is to add suid bit to the frontend (See chmod(1)). -The backend drop root priviledges as soon as it can, right after gaining direct +The backend drop root privileges as soon as it can, right after gaining direct access to IO ports, which lessen risks when being root. .SH "DEVICE NAMES" @@ -100,7 +100,7 @@ root (*BSD and linux), or with 'IOPL=yes' on OS/2 .PP .RE -\fBNOTE:\fR in all cases, you must have sufficient priviledges +\fBNOTE:\fR in all cases, you must have sufficient privileges to get access to the chosen device or address. Depending on the security settings, devices may not be available for all users. You have to change permissions on the dev/ppi* or /dev/parport* devices. diff --git a/doc/sane-usb.man b/doc/sane-usb.man index 5052e41..8237a8a 100644 --- a/doc/sane-usb.man +++ b/doc/sane-usb.man @@ -90,7 +90,7 @@ can be found on the SANE webpage and the individual backend manpages. .PP Most backends can detect USB scanners automatically using "usb" configuration -file lines. This method allows to identify scanners by the USB vendor and +file lines. This method allows one to identify scanners by the USB vendor and product numbers. The syntax for specifying a scanner this way is: .PP .RS diff --git a/doc/sane.man b/doc/sane.man index b062782..4fad9a9 100644 --- a/doc/sane.man +++ b/doc/sane.man @@ -429,7 +429,7 @@ for details. .TP .B plustek The SANE plustek backend supports USB flatbed scanners that use the National -Semiconductor LM983[1/2/3]-chipset aka Merlin. Scanners using this LM983x chips +Semiconductor LM983[1/2/3] chipset aka Merlin. Scanners using this LM983x chips include some models from Plustek, KYE/Genius, Hewlett-Packard, Mustek, Umax, Epson, and Canon. See .BR sane\-plustek (5) diff --git a/doc/saned.man b/doc/saned.man index d8e8983..8721b15 100644 --- a/doc/saned.man +++ b/doc/saned.man @@ -164,7 +164,7 @@ The configuration line normally looks like this: .PP .RS sane\-port stream tcp nowait saned.saned @SBINDIR@/saned saned -.E +.RE .PP However, if your system uses .BR tcpd (8) diff --git a/frontend/scanimage.c b/frontend/scanimage.c index d41c849..b1d2481 100644 --- a/frontend/scanimage.c +++ b/frontend/scanimage.c @@ -76,6 +76,7 @@ Image; #define OPTION_BATCH_DOUBLE 1005 #define OPTION_BATCH_INCREMENT 1006 #define OPTION_BATCH_PROMPT 1007 +#define OPTION_BATCH_PRINT 1008 #define BATCH_COUNT_UNLIMITED -1 @@ -95,6 +96,7 @@ static struct option basic_options[] = { {"batch-start", required_argument, NULL, OPTION_BATCH_START_AT}, {"batch-double", no_argument, NULL, OPTION_BATCH_DOUBLE}, {"batch-increment", required_argument, NULL, OPTION_BATCH_INCREMENT}, + {"batch-print", no_argument, NULL, OPTION_BATCH_PRINT}, {"batch-prompt", no_argument, NULL, OPTION_BATCH_PROMPT}, {"format", required_argument, NULL, OPTION_FORMAT}, {"accept-md5-only", no_argument, NULL, OPTION_MD5}, @@ -152,6 +154,7 @@ auth_callback (SANE_String_Const resource, int md5mode = 0, len, query_user = 1; FILE *pass_file; struct stat stat_buf; + char * uname = NULL; *tmp = 0; @@ -250,7 +253,7 @@ auth_callback (SANE_String_Const resource, md5mode = 1; len = (strstr (resource, "$MD5$") - resource); if (query_user == 1) - fprintf (stderr, "Authentification required for resource %*.*s. " + fprintf (stderr, "Authentication required for resource %*.*s. " "Enter username: ", len, len, resource); } else @@ -270,14 +273,14 @@ auth_callback (SANE_String_Const resource, if (query_user == 1) fprintf (stderr, - "Authentification required for resource %s. Enter username: ", + "Authentication required for resource %s. Enter username: ", resource); } if (query_user == 1) - fgets (username, SANE_MAX_USERNAME_LEN, stdin); + uname = fgets (username, SANE_MAX_USERNAME_LEN, stdin); - if ((strlen (username)) && (username[strlen (username) - 1] == '\n')) + if (uname != NULL && (strlen (username)) && (username[strlen (username) - 1] == '\n')) username[strlen (username) - 1] = 0; if (query_user == 1) @@ -1125,7 +1128,7 @@ process_backend_option (SANE_Handle device, int optnum, const char *optarg) } static void -write_pnm_header (SANE_Frame format, int width, int height, int depth) +write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp) { /* The netpbm-package does not define raw image data with maxval > 255. */ /* But writing maxval 65535 for 16bit data gives at least a chance */ @@ -1136,20 +1139,20 @@ write_pnm_header (SANE_Frame format, int width, int height, int depth) case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: case SANE_FRAME_RGB: - printf ("P6\n# SANE data follows\n%d %d\n%d\n", width, height, + fprintf (ofp, "P6\n# SANE data follows\n%d %d\n%d\n", width, height, (depth <= 8) ? 255 : 65535); break; default: if (depth == 1) - printf ("P4\n# SANE data follows\n%d %d\n", width, height); + fprintf (ofp, "P4\n# SANE data follows\n%d %d\n", width, height); else - printf ("P5\n# SANE data follows\n%d %d\n%d\n", width, height, + fprintf (ofp, "P5\n# SANE data follows\n%d %d\n%d\n", width, height, (depth <= 8) ? 255 : 65535); break; } #ifdef __EMX__ /* OS2 - write in binary mode. */ - _fsetmode (stdout, "b"); + _fsetmode (ofp, "b"); #endif } @@ -1184,7 +1187,7 @@ advance (Image * image) } static SANE_Status -scan_it (void) +scan_it (FILE *ofp) { int i, len, first_frame = 1, offset = 0, must_buffer = 0, hundred_percent; SANE_Byte min = 0xff, max = 0; @@ -1274,10 +1277,10 @@ scan_it (void) sanei_write_tiff_header (parm.format, parm.pixels_per_line, parm.lines, parm.depth, resolution_value, - icc_profile); + icc_profile, ofp); else write_pnm_header (parm.format, parm.pixels_per_line, - parm.lines, parm.depth); + parm.lines, parm.depth, ofp); } break; @@ -1398,7 +1401,7 @@ scan_it (void) else /* ! must_buffer */ { if ((output_format == OUTPUT_TIFF) || (parm.depth != 16)) - fwrite (buffer, 1, len, stdout); + fwrite (buffer, 1, len, ofp); else { #if !defined(WORDS_BIGENDIAN) @@ -1409,7 +1412,7 @@ scan_it (void) { if (len > 0) { - fwrite (buffer, 1, 1, stdout); + fwrite (buffer, 1, 1, ofp); buffer[0] = (SANE_Byte) hang_over; hang_over = -1; start = 1; @@ -1430,7 +1433,7 @@ scan_it (void) len--; } #endif - fwrite (buffer, 1, len, stdout); + fwrite (buffer, 1, len, ofp); } } @@ -1454,10 +1457,10 @@ scan_it (void) if (output_format == OUTPUT_TIFF) sanei_write_tiff_header (parm.format, parm.pixels_per_line, image.height, parm.depth, resolution_value, - icc_profile); + icc_profile, ofp); else write_pnm_header (parm.format, parm.pixels_per_line, - image.height, parm.depth); + image.height, parm.depth, ofp); #if !defined(WORDS_BIGENDIAN) /* multibyte pnm file may need byte swap to LE */ @@ -1475,11 +1478,11 @@ scan_it (void) } #endif - fwrite (image.data, 1, image.height * image.width, stdout); + fwrite (image.data, 1, image.height * image.width, ofp); } /* flush the output buffer */ - fflush( stdout ); + fflush( ofp ); cleanup: if (image.data) @@ -1708,6 +1711,7 @@ main (int argc, char **argv) char readbuf[2]; char *readbuf2; int batch = 0; + int batch_print = 0; int batch_prompt = 0; int batch_count = BATCH_COUNT_UNLIMITED; int batch_start_at = 1; @@ -1715,6 +1719,7 @@ main (int argc, char **argv) SANE_Status status; char *full_optstring; SANE_Int version_code; + FILE *ofp = NULL; atexit (scanimage_exit); @@ -1776,6 +1781,9 @@ main (int argc, char **argv) case 'n': dont_scan = 1; break; + case OPTION_BATCH_PRINT: + batch_print = 1; + break; case OPTION_BATCH_PROMPT: batch_prompt = 1; break; @@ -1826,23 +1834,16 @@ main (int argc, char **argv) else { int i = 0, int_arg = 0; - char *percent, *start, *fmt; + const char *percent, *start; const char *text_arg = 0; - char cc, ftype; - - fmt = malloc (strlen (optarg) + 1); - if (fmt == 0) - { - fprintf (stderr, "%s: not enough memory\n", prog_name); - exit (1); - } + char ftype; for (i = 0; device_list[i]; ++i) { - strcpy (fmt, optarg); - start = fmt; + start = optarg; while (*start && (percent = strchr (start, '%'))) { + int start_len = percent - start; percent++; if (*percent) { @@ -1850,19 +1851,19 @@ main (int argc, char **argv) { case 'd': text_arg = device_list[i]->name; - ftype = *percent = 's'; + ftype = 's'; break; case 'v': text_arg = device_list[i]->vendor; - ftype = *percent = 's'; + ftype = 's'; break; case 'm': text_arg = device_list[i]->model; - ftype = *percent = 's'; + ftype = 's'; break; case 't': text_arg = device_list[i]->type; - ftype = *percent = 's'; + ftype = 's'; break; case 'i': int_arg = i; @@ -1870,45 +1871,40 @@ main (int argc, char **argv) break; case 'n': text_arg = "\n"; - ftype = *percent = 's'; + ftype = 's'; break; case '%': - ftype = 0; + text_arg = "%"; + ftype = 's'; break; default: fprintf (stderr, "%s: unknown format specifier %%%c\n", prog_name, *percent); - *percent = '%'; - ftype = 0; + text_arg = "%"; + ftype = 's'; } - percent++; - cc = *percent; - *percent = 0; + printf ("%.*s", start_len, start); switch (ftype) { case 's': - printf (start, text_arg); + printf ("%s", text_arg); break; case 'i': - printf (start, int_arg); - break; - case 0: - printf (start); + printf ("%i", int_arg); break; } - *percent = cc; - start = percent; + start = percent + 1; } else { - /* last char of the string is a '%', suppress it */ - *start = 0; + /* last char of the string is a '%', ignore it */ + start++; break; } } if (*start) - printf (start); + printf ("%s", start); } } if (i == 0 && ch != 'f') @@ -1961,16 +1957,18 @@ Parameters are separated by a blank from single-character options (e.g.\n\ --batch-increment=# increase page number in filename by #\n\ --batch-double increment page number by two, same as\n\ --batch-increment=2\n\ - --batch-prompt ask for pressing a key before scanning a page\n\ - --accept-md5-only only accept authorization requests using md5\n"); + --batch-print print image filenames to stdout\n\ + --batch-prompt ask for pressing a key before scanning a page\n"); printf ("\ + --accept-md5-only only accept authorization requests using md5\n\ -p, --progress print progress messages\n\ -n, --dont-scan only set options, don't actually scan\n\ -T, --test test backend thoroughly\n\ -A, --all-options list all available backend options\n\ -h, --help display this help message and exit\n\ -v, --verbose give even more status messages\n\ --B, --buffer-size=# change input buffer size (in kB, default 32)\n\ +-B, --buffer-size=# change input buffer size (in kB, default 32)\n"); + printf ("\ -V, --version print version information\n"); } @@ -2237,12 +2235,15 @@ List of available devices:", prog_name); format = "out%d.pnm"; } + if (!batch) + ofp = stdout; + if (batch) fprintf (stderr, "Scanning %d pages, incrementing by %d, numbering from %d\n", batch_count, batch_increment, batch_start_at); - else if(isatty(fileno(stdout))){ + else if(isatty(fileno(ofp))){ fprintf (stderr,"%s: output is not a file, exiting\n", prog_name); exit (1); } @@ -2275,7 +2276,11 @@ List of available devices:", prog_name); { fprintf (stderr, "Batch terminated, %d pages scanned\n", (n - batch_increment)); - fclose (stdout); + if (ofp) + { + fclose (ofp); + ofp = NULL; + } break; /* get out of this loop */ } } @@ -2295,19 +2300,27 @@ List of available devices:", prog_name); { fprintf (stderr, "%s: sane_start: %s\n", prog_name, sane_strstatus (status)); - fclose (stdout); + if (ofp) + { + fclose (ofp); + ofp = NULL; + } break; } + /* write to .part file while scanning is in progress */ - if (batch && NULL == freopen (part_path, "w", stdout)) + if (batch) { - fprintf (stderr, "cannot open %s\n", part_path); - sane_cancel (device); - return SANE_STATUS_ACCESS_DENIED; + if (NULL == (ofp = fopen (part_path, "w"))) + { + fprintf (stderr, "cannot open %s\n", part_path); + sane_cancel (device); + return SANE_STATUS_ACCESS_DENIED; + } } - status = scan_it (); + status = scan_it (ofp); if (batch) { fprintf (stderr, "Scanned page %d.", n); @@ -2320,17 +2333,16 @@ List of available devices:", prog_name); case SANE_STATUS_EOF: status = SANE_STATUS_GOOD; if (batch) - { - /* close output file by redirecting, do not close - stdout here! */ - if (NULL == freopen ("/dev/null", "w", stdout)) + { + if (!ofp || 0 != fclose(ofp)) { - fprintf (stderr, "cannot open /dev/null\n"); + fprintf (stderr, "cannot close image file\n"); sane_cancel (device); return SANE_STATUS_ACCESS_DENIED; } else { + ofp = NULL; /* let the fully scanned file show up */ if (rename (part_path, path)) { @@ -2339,13 +2351,22 @@ List of available devices:", prog_name); sane_cancel (device); return SANE_STATUS_ACCESS_DENIED; } + if (batch_print) + { + fprintf (stdout, "%s\n", path); + fflush (stdout); + } } } break; default: if (batch) { - fclose (stdout); + if (ofp) + { + fclose (ofp); + ofp = NULL; + } unlink (part_path); } break; @@ -2356,6 +2377,12 @@ List of available devices:", prog_name); && (batch_count == BATCH_COUNT_UNLIMITED || --batch_count)) && SANE_STATUS_GOOD == status); + if (batch + && SANE_STATUS_NO_DOCS == status + && (batch_count == BATCH_COUNT_UNLIMITED) + && n > batch_start_at) + status = SANE_STATUS_GOOD; + sane_cancel (device); } else diff --git a/frontend/stiff.c b/frontend/stiff.c index 1107e09..01d845b 100644 --- a/frontend/stiff.c +++ b/frontend/stiff.c @@ -586,10 +586,10 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth, void sanei_write_tiff_header (SANE_Frame format, int width, int height, int depth, - int resolution, const char *icc_profile) + int resolution, const char *icc_profile, FILE *ofp) { #ifdef __EMX__ /* OS2 - write in binary mode. */ - _fsetmode(stdout, "b"); + _fsetmode(ofp, "b"); #endif switch (format) { @@ -597,14 +597,14 @@ sanei_write_tiff_header (SANE_Frame format, int width, int height, int depth, case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: case SANE_FRAME_RGB: - write_tiff_color_header (stdout, width, height, depth, resolution, icc_profile); + write_tiff_color_header (ofp, width, height, depth, resolution, icc_profile); break; default: if (depth == 1) - write_tiff_bw_header (stdout, width, height, resolution); + write_tiff_bw_header (ofp, width, height, resolution); else - write_tiff_grey_header (stdout, width, height, depth, resolution, icc_profile); + write_tiff_grey_header (ofp, width, height, depth, resolution, icc_profile); break; } } diff --git a/frontend/stiff.h b/frontend/stiff.h index 8583832..6560ef6 100644 --- a/frontend/stiff.h +++ b/frontend/stiff.h @@ -17,4 +17,4 @@ void sanei_write_tiff_header (SANE_Frame format, int width, int height, int depth, - int resolution, const char *icc_profile); + int resolution, const char *icc_profile, FILE *ofp); diff --git a/lib/snprintf.c b/lib/snprintf.c index aca8df9..cdf6513 100644 --- a/lib/snprintf.c +++ b/lib/snprintf.c @@ -2,180 +2,616 @@ #ifndef HAVE_SNPRINTF -/*************************************************************************** - * LPRng - An Extended Print Spooler System - * - * Copyright 1988-1997, Patrick Powell, San Diego, CA - * papowell@sdsu.edu - * See below for conditions of use. - * - *************************************************************************** - * MODULE: snprintf.c - * PURPOSE: LPRng version of printf - absolutely bombproof (hopefully!) +/************************************************************************** + * Copyright 1994-2003 Patrick Powell, San Diego, CA **************************************************************************/ -#if 0 - The "Artistic License" +/* + Overview: - Preamble + snprintf( char *buffer, int len, const char *format,...) + plp_unsafe_snprintf( char *buffer, int len, const char *format,...) + its horribly unsafe companion that does NOT protect you from + the printing of evil control characters, but may be necessary + See the man page documentation below -The intent of this document is to state the conditions under which a -Package may be copied, such that the Copyright Holder maintains some -semblance of artistic control over the development of the package, -while giving the users of the package the right to use and distribute -the Package in a more-or-less customary fashion, plus the right to make -reasonable modifications. + This version of snprintf was developed originally for printing + on a motley collection of specialized hardware that had NO IO + library. Due to contractual restrictions, a clean room implementation + of the printf() code had to be developed. -Definitions: + The method chosen for printf was to be as paranoid as possible, + as these platforms had NO memory protection, and very small + address spaces. This made it possible to try to print + very long strings, i.e. - all of memory, very easily. To guard + against this, all printing was done via a buffer, generous enough + to hold strings, but small enough to protect against overruns, + etc. - "Package" refers to the collection of files distributed by the - Copyright Holder, and derivatives of that collection of files - created through textual modification. + Strangely enough, this proved to be of immense importance when + SPRINTFing to a buffer on a stack... The rest, of course, is + well known, as buffer overruns in the stack are a common way to + do horrible things to operating systems, security, etc etc. - "Standard Version" refers to such a Package if it has not been - modified, or has been modified in accordance with the wishes - of the Copyright Holder as specified below. + This version of snprintf is VERY limited by modern standards. - "Copyright Holder" is whoever is named in the copyright or - copyrights for the package. + Revision History: + First Released Version - 1994. This version had NO comments. + First Released Version - 1994. This version had NO comments. + Second Major Released Version - Tue May 23 10:43:44 PDT 2000 + Configuration and other items changed. Read this doc. + Treat this as a new version. + Minor Revision - Mon Apr 1 09:41:28 PST 2002 + - fixed up some constants and casts - "You" is you, if you are thinking about copying or distributing - this Package. + COPYRIGHT AND TERMS OF USE: - "Reasonable copying fee" is whatever you can justify on the - basis of media cost, duplication charges, time of people involved, - and so on. (You will not be required to justify it to the - Copyright Holder, but only to the computing community at large - as a market that must bear the fee.) + You may use, copy, distribute, or otherwise incorporate this software + and documentation into any product or other item, provided that + the copyright in the documentation and source code as well as the + source code generated constant strings in the object, executable + or other code remain in place and are present in executable modules + or objects. - "Freely Available" means that no fee is charged for the item - itself, though there may be fees involved in handling the item. - It also means that recipients of the item may redistribute it - under the same conditions they received it. + You may modify this code as appropriate to your usage; however the + modified version must be identified by changing the various source + and object code identification strings as is appropriately noted + in the source code. -1. You may make and give away verbatim copies of the source form of the -Standard Version of this Package without restriction, provided that you -duplicate all of the original copyright notices and associated disclaimers. + You can use this with the GNU CONFIGURE utility. + This should define the following macros appropriately: -2. You may apply bug fixes, portability fixes and other modifications -derived from the Public Domain or from the Copyright Holder. A Package -modified in such a way shall still be considered the Standard Version. + HAVE_STDARG_H - if the include file is available + HAVE_VARARG_H - if the include file is available -3. You may otherwise modify your copy of this Package in any way, provided -that you insert a prominent notice in each changed file stating how and -when you changed that file, and provided that you do at least ONE of the -following: + HAVE_STRERROR - if the strerror() routine is available. + If it is not available, then examine the lines containing + the tests below. - a) place your modifications in the Public Domain or otherwise make them - Freely Available, such as by posting said modifications to Usenet or - an equivalent medium, or placing the modifications on a major archive - site such as uunet.uu.net, or by allowing the Copyright Holder to include - your modifications in the Standard Version of the Package. + HAVE_SYS_ERRLIST - have sys_errlist available + HAVE_DECL_SYS_ERRLIST - sys_errlist declaration in include files + HAVE_SYS_NERR - have sys_nerr available + HAVE_DECL_SYS_NERR - sys_nerr declaration in include files - b) use the modified Package only within your corporation or organization. + HAVE_QUAD_T - if the quad_t type is defined + HAVE_LONG_LONG - if the long long type is defined + HAVE_LONG_DOUBLE - if the long double type is defined - c) rename any non-standard executables so the names do not conflict - with standard executables, which must also be provided, and provide - a separate manual page for each non-standard executable that clearly - documents how it differs from the Standard Version. + If you are using the GNU configure (autoconf) facility, add the + following line to the configure.in file, to force checking for the + quad_t and long long data types: - d) make other distribution arrangements with the Copyright Holder. -4. You may distribute the programs of this Package in object code or -executable form, provided that you do at least ONE of the following: + AC_CHECK_HEADERS(stdlib.h,stdio.h,unistd.h,errno.h) + AC_CHECK_FUNCS(strerror) + AC_CACHE_CHECK(for errno, + ac_cv_errno, + [ + AC_TRY_LINK(,[extern int errno; return (errno);], + ac_cv_errno=yes, ac_cv_errno=no) + ]) + if test "$ac_cv_errno" = yes; then + AC_DEFINE(HAVE_ERRNO) + AC_CACHE_CHECK(for errno declaration, + ac_cv_decl_errno, + [ + AC_TRY_COMPILE([ + #include + #ifdef HAVE_STDLIB_H + #include + #endif + #ifdef HAVE_UNISTD_H + #include + #endif + #ifdef HAVE_ERRNO_H + #include + ],[return(sys_nerr);], + ac_cv_decl_errno=yes, ac_cv_decl_errno=no) + ]) + if test "$ac_cv_decl_errno" = yes; then + AC_DEFINE(HAVE_DECL_ERRNO) + fi; + fi - a) distribute a Standard Version of the executables and library files, - together with instructions (in the manual page or equivalent) on where - to get the Standard Version. + AC_CACHE_CHECK(for sys_nerr, + ac_cv_sys_nerr, + [ + AC_TRY_LINK(,[extern int sys_nerr; return (sys_nerr);], + ac_cv_sys_nerr=yes, ac_cv_sys_nerr=no) + ]) + if test "$ac_cv_sys_nerr" = yes; then + AC_DEFINE(HAVE_SYS_NERR) + AC_CACHE_CHECK(for sys_nerr declaration, + ac_cv_decl_sys_nerr, + [ + AC_TRY_COMPILE([ + #include + #ifdef HAVE_STDLIB_H + #include + #endif + #ifdef HAVE_UNISTD_H + #include + #endif],[return(sys_nerr);], + ac_cv_decl_sys_nerr_def=yes, ac_cv_decl_sys_nerr_def=no) + ]) + if test "$ac_cv_decl_sys_nerr" = yes; then + AC_DEFINE(HAVE_DECL_SYS_NERR) + fi + fi - b) accompany the distribution with the machine-readable source of - the Package with your modifications. - c) give non-standard executables non-standard names, and clearly - document the differences in manual pages (or equivalent), together - with instructions on where to get the Standard Version. + AC_CACHE_CHECK(for sys_errlist array, + ac_cv_sys_errlist, + [AC_TRY_LINK(,[extern char *sys_errlist[]; + sys_errlist[0];], + ac_cv_sys_errlist=yes, ac_cv_sys_errlist=no) + ]) + if test "$ac_cv_sys_errlist" = yes; then + AC_DEFINE(HAVE_SYS_ERRLIST) + AC_CACHE_CHECK(for sys_errlist declaration, + ac_cv_sys_errlist_def, + [AC_TRY_COMPILE([ + #include + #include + #ifdef HAVE_STDLIB_H + #include + #endif + #ifdef HAVE_UNISTD_H + #include + #endif],[char *s = sys_errlist[0]; return(*s);], + ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no) + ]) + if test "$ac_cv_decl_sys_errlist" = yes; then + AC_DEFINE(HAVE_DECL_SYS_ERRLIST) + fi + fi - d) make other distribution arrangements with the Copyright Holder. -5. You may charge a reasonable copying fee for any distribution of this -Package. You may charge any fee you choose for support of this -Package. You may not charge a fee for this Package itself. However, -you may distribute this Package in aggregate with other (possibly -commercial) programs as part of a larger (possibly commercial) software -distribution provided that you do not advertise this Package as a -product of your own. -6. The name of the Copyright Holder may not be used to endorse or promote -products derived from this software without specific prior written permission. + AC_CACHE_CHECK(checking for long long, + ac_cv_long_long, + [ + AC_TRY_COMPILE([ + #include + #include + ], [printf("%d",sizeof(long long));], + ac_cv_long_long=yes, ac_cv_long_long=no) + ]) + if test $ac_cv_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG) + fi -7. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + AC_CACHE_CHECK(checking for long double, + ac_cv_long_double, + [ + AC_TRY_COMPILE([ + #include + #include + ], [printf("%d",sizeof(long double));], + ac_cv_long_double=yes, ac_cv_long_double=no) + ]) + if test $ac_cv_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE) + fi - The End -#include "lp.h" -#endif + AC_CACHE_CHECK(checking for quad_t, + ac_cv_quad_t, + [ + AC_TRY_COMPILE([ + #include + #include + ], [printf("%d",sizeof(quad_t));], + ac_cv_quad_t=yes, ac_cv_quad_t=no) + ]) + if test $ac_cv_quad_t = yes; then + AC_DEFINE(HAVE_QUAD_T) + fi -#include -#include -#include -#define HAVE_STDARGS /* let's hope that works everywhere (mj) */ -#define VA_LOCAL_DECL va_list ap; -#define VA_START(f) va_start(ap, f) -#define VA_SHIFT(v,t) ; /* no-op for ANSI */ -#define VA_END va_end(ap) -/**** ENDINCLUDE ****/ -static char *const _id = "$Id$"; + NAME + snprintf, plp_vsnprintf - formatted output conversion + + SYNOPSIS + #include + #include + + int + snprintf(const char *format, size_t size, va_list ap); + int + plp_unsafe_snprintf(const char *format, size_t size, va_list ap); + + AKA snprintf and unsafe_snprintf in the documentation below + + int + vsnprintf(char *str, size_t size, const char *format, va_list ap); + int + unsafe_vsnprintf(char *str, size_t size, const char *format, va_list ap); + + AKA vsnprintf and unsafe_vsnprintf in the documentation below + + (Multithreaded Safe) + + DESCRIPTION + The printf() family of functions produces output according to + a format as described below. Snprintf(), and vsnprintf() + write to the character string str. These functions write the + output under the control of a format string that specifies + how subsequent arguments (or arguments accessed via the + variable-length argument facilities of stdarg(3)) are converted + for output. These functions return the number of characters + printed (not including the trailing `\0' used to end output + to strings). Snprintf() and vsnprintf() will write at most + size-1 of the characters printed into the output string (the + size'th character then gets the terminating `\0'); if the + return value is greater than or equal to the size argument, + the string was too short and some of the printed characters + were discarded. The size or str may be given as zero to find + out how many characters are needed; in this case, the str + argument is ignored. + + By default, the snprintf function will not format control + characters (except new line and tab) in strings. This is a + safety feature that has proven to be extremely critical when + using snprintf for secure applications and when debugging. + If you MUST have control characters formatted or printed, + then use the unsafe_snprintf() and unsafe_vsnprintf() and on + your own head be the consequences. You have been warned. + + There is one exception to the comments above, and that is + the "%c" (character) format. It brutally assumes that the + user will have performed the necessary 'isprint()' or other + checks and uses the integer value as a character. + + The format string is composed of zero or more directives: + ordinary characters (not %), which are copied unchanged to + the output stream; and conversion specifications, each + of which results in fetching zero or more subsequent arguments. + Each conversion specification is introduced by the character + %. The arguments must correspond properly (after type promotion) + with the conversion specifier. After the %, the following + appear in sequence: + + o Zero or more of the following flags: + + - A zero `0' character specifying zero padding. For + all conversions except n, the converted value is padded + on the left with zeros rather than blanks. If a + precision is given with a numeric conversion (d, i, + o, u, i, x, and X), the `0' flag is ignored. + + - A negative field width flag `-' indicates the converted + value is to be left adjusted on the field boundary. Except + for n conversions, the converted value is padded on + the right with blanks, rather than on the left with + blanks or zeros. A `-' overrides a `0' if both are + given. + + - A space, specifying that a blank should be left before + a positive number produced by a signed conversion (d, e, E, f, + g, G, or i). + + - A `+' character specifying that a sign always be placed + before a number produced by a signed conversion. A `+' overrides + a space if both are used. + + o An optional decimal digit string specifying a minimum + field width. If the converted value has fewer + characters than the field width, it will be padded + with spaces on the left (or right, if the + left-adjustment flag has been given) to fill out + the field width. + + o An optional precision, in the form of a period `.' followed + by an optional digit string. If the digit string + is omitted, the precision is taken as zero. This + gives the minimum number of digits to appear for + d, i, o, u, x, and X conversions, the number of + digits to appear after the decimal-point for e, + E, and f conversions, the maximum number of + significant digits for g and G conversions, or + the maximum number of characters to be printed + from a string for s conversions. + + o The optional character h, specifying that a following d, + i, o, u, x, or X conversion corresponds to a short + int or unsigned short int argument, or that a + following n conversion corresponds to a pointer + to a short int argument. + + o The optional character l (ell) specifying that a following + d, i, o, u, x, or X conversion applies to a pointer + to a long int or unsigned long int argument, or + that a following n conversion corresponds to a + pointer to a long int argument. + + o The optional character q, specifying that a following d, + i, o, u, x, or X conversion corresponds to a quad_t + or u_quad_t argument, or that a following n + conversion corresponds to a quad_t argument. + This value is always printed in HEX notation. Tough. + quad_t's are an OS system implementation, and should + not be allowed. + + o The character L specifying that a following e, E, f, g, + or G conversion corresponds to a long double + argument. + + o A character that specifies the type of conversion to be applied. + + + A field width or precision, or both, may be indicated by an asterisk `*' + instead of a digit string. In this case, an int argument supplies the + field width or precision. A negative field width is treated as a left + adjustment flag followed by a positive field width; a negative precision + is treated as though it were missing. + + The conversion specifiers and their meanings are: + + diouxX The int (or appropriate variant) argument is converted to signed + decimal (d and i), unsigned octal (o), unsigned decimal + (u), or unsigned hexadecimal (x and X) notation. The + letters abcdef are used for x conversions; the letters + ABCDEF are used for X conversions. The precision, if + any, gives the minimum number of digits that must + appear; if the converted value requires fewer digits, + it is padded on the left with zeros. + + eE The double argument is rounded and converted in the style + [-]d.ddde+-dd where there is one digit before the decimal-point + character and the number of digits after it is equal + to the precision; if the precision is missing, it is + taken as 6; if the precision is zero, no decimal-point + character appears. An E conversion uses the letter + E (rather than e) to introduce the exponent. + The exponent always contains at least two digits; if + the value is zero, the exponent is 00. + + f The double argument is rounded and converted to decimal notation + in the style [-]ddd.ddd, where the number of digits after the + decimal-point character is equal to the precision specification. + If the precision is missing, it is taken as 6; if the precision + is explicitly zero, no decimal-point character appears. If a + decimal point appears, at least one digit appears before it. + + g The double argument is converted in style f or e (or + E for G conversions). The precision specifies the + number of significant digits. If the precision is + missing, 6 digits are given; if the precision is zero, + it is treated as 1. Style e is used if the exponent + from its conversion is less than -4 or greater than + or equal to the precision. Trailing zeros are removed + from the fractional part of the result; a decimal + point appears only if it is followed by at least one + digit. + + c The int argument is converted to an unsigned char, + and the resulting character is written. + + s The ``char *'' argument is expected to be a pointer to an array + of character type (pointer to a string). Characters + from the array are written up to (but not including) + a terminating NUL character; if a precision is + specified, no more than the number specified are + written. If a precision is given, no null character + need be present; if the precision is not specified, + or is greater than the size of the array, the array + must contain a terminating NUL character. + + % A `%' is written. No argument is converted. The complete + conversion specification is `%%'. + + In no case does a non-existent or small field width cause truncation of a + field; if the result of a conversion is wider than the field width, the + field is expanded to contain the conversion result. + + EXAMPLES + To print a date and time in the form `Sunday, July 3, 10:02', where + weekday and month are pointers to strings: + + #include + fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", + weekday, month, day, hour, min); + + To print pi to five decimal places: + + #include + #include + fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0)); + + To allocate a 128 byte string and print into it: + + #include + #include + #include + char *newfmt(const char *fmt, ...) + { + char *p; + va_list ap; + if ((p = malloc(128)) == NULL) + return (NULL); + va_start(ap, fmt); + (void) vsnprintf(p, 128, fmt, ap); + va_end(ap); + return (p); + } + + SEE ALSO + printf(1), scanf(3) + + STANDARDS + Turkey C Standardization and wimpy POSIX folks did not define + snprintf or vsnprintf(). + + BUGS + The conversion formats %D, %O, and %U are not standard and are provided + only for backward compatibility. The effect of padding the %p format + with zeros (either by the `0' flag or by specifying a precision), and the + benign effect (i.e., none) of the `#' flag on %n and %p conversions, as + well as other nonsensical combinations such as %Ld, are not standard; + such combinations should be avoided. + + The typedef names quad_t and u_quad_t are infelicitous. + +*/ + + +#include +#include +#include +#include +#if defined(HAVE_STRING_H) +# include +#endif +#if defined(HAVE_STRINGS_H) +# include +#endif +#if defined(HAVE_ERRNO_H) +#include +#endif /* - * dopr(): poor man's version of doprintf + * For testing, define these values */ +#if 0 +#define HAVE_STDARG_H 1 +#define TEST 1 +#define HAVE_QUAD_T 1 +#endif + +/**** ENDINCLUDE ****/ + +/************************************************* + * KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS + * i.e. - the LOCAL REVISIONS part is for your use + *************************************************/ + + + static char *const _id = "plp_snprintf V2000.08.18 Copyright Patrick Powell 1988-2000 " + "$Id: plp_snprintf.c,v 1.4 2005/04/14 20:05:19 papowell Exp $" + " LOCAL REVISIONS: renamed plp_snprintf to snprintf, conditionalized everything on HAVE_SNPRINTF"; + +/* varargs declarations: */ + +# undef HAVE_STDARGS /* let's hope that works everywhere (mj) */ +# undef VA_LOCAL_DECL +# undef VA_START +# undef VA_SHIFT +# undef VA_END + +#if defined(HAVE_STDARG_H) +# include +# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ +# define VA_LOCAL_DECL va_list ap; +# define VA_START(f) va_start(ap, f) +# define VA_SHIFT(v,t) ; /* no-op for ANSI */ +# define VA_END va_end(ap) +#else +# if defined(HAVE_VARARGS_H) +# include +# undef HAVE_STDARGS +# define VA_LOCAL_DECL va_list ap; +# define VA_START(f) va_start(ap) /* f is ignored! */ +# define VA_SHIFT(v,t) v = va_arg(ap,t) +# define VA_END va_end(ap) +# else + XX ** NO VARARGS ** XX +# endif +#endif -static char * plp_Errormsg ( int err ); -static void dopr( char *buffer, const char *format, va_list args ); -static void fmtstr( char *value, int ljust, int len, int zpad, int precision ); -static void fmtnum( long value, int base, int dosign, + union value { +#if defined(HAVE_QUAD_T) + quad_t qvalue; +#endif +#if defined(HAVE_LONG_LONG) + long long value; +#else + long value; +#endif + double dvalue; +}; + +#undef CVAL +#define CVAL(s) (*((unsigned char *)s)) +#define safestrlen(s) ((s)?strlen(s):0) + + + static char * plp_Errormsg ( int err, char *buffer ); + static void dopr( int visible_control, char **buffer, int *left, + const char *format, va_list args ); + static void fmtstr( int visible_control, char **buffer, int *left, + char *value, int ljust, int len, int zpad, int precision ); + static void fmtnum( char **buffer, int *left, + union value *value, int base, int dosign, + int ljust, int len, int zpad, int precision ); +#if defined(HAVE_QUAD_T) + static void fmtquad( char **buffer, int *left, + union value *value, int base, int dosign, int ljust, int len, int zpad, int precision ); -static void fmtdouble( int fmt, double value, +#endif + static void fmtdouble( char **bufer, int *left, + int fmt, double value, int ljust, int len, int zpad, int precision ); -static void dostr( char * ); -static char *output; -static void dopr_outch( int c ); -static char *end; -int visible_control = 1; - -/************************************************************** - * Original: - * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 - * A bombproof version of doprnt (dopr) included. - * Sigh. This sort of thing is always nasty do deal with. Note that - * the version here does not include floating point... - * - * plp_snprintf() is used instead of sprintf() as it does limit checks - * for string length. This covers a nasty loophole. - * - * The other functions are there to prevent NULL pointers from - * causing nast effects. - **************************************************************/ - -int vsnprintf(char *str, size_t count, const char *fmt, va_list args) + static void dostr( char **buffer, int *left, char *str ); + static void dopr_outch( char **buffer, int *left, int c ); +/* VARARGS3 */ +#ifdef HAVE_STDARGS + int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args) +#else + int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args) +#endif + +{ + int left; + char *buffer; + if( (int)count < 0 ) count = 0; + left = count; + if( count == 0 ) str = 0; + buffer = str; + dopr( 1, &buffer, &left, fmt, args ); + /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n", + (int)str, (int)buffer, count, left ); */ + if( str && count > 0 ){ + if( left > 0 ){ + str[count-left] = 0; + } else { + str[count-1] = 0; + } + } + return(count - left); +} + +/* VARARGS3 */ +#ifdef HAVE_STDARGS + int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args) +#else + int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args) +#endif { - str[0] = 0; - end = str+count-1; - dopr( str, fmt, args ); - if( count>0 ){ - end[0] = 0; + int left; + char *buffer; + if( (int)count < 0 ) count = 0; + left = count; + if( count == 0 ) str = 0; + buffer = str; + dopr( 0, &buffer, &left, fmt, args ); + /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n", + (int)str, (int)buffer, count, left ); */ + if( str && count > 0 ){ + if( left > 0 ){ + str[count-left] = 0; + } else { + str[count-1] = 0; + } } - return(strlen(str)); + return(count - left); } /* VARARGS3 */ #ifdef HAVE_STDARGS -int snprintf (char *str,size_t count,const char *fmt,...) + int snprintf (char *str,size_t count,const char *fmt,...) #else -int snprintf (va_alist) va_dcl + int snprintf (va_alist) va_dcl #endif { #ifndef HAVE_STDARGS @@ -183,22 +619,48 @@ int snprintf (va_alist) va_dcl size_t count; char *fmt; #endif + int n = 0; VA_LOCAL_DECL VA_START (fmt); VA_SHIFT (str, char *); VA_SHIFT (count, size_t ); VA_SHIFT (fmt, char *); - (void) vsnprintf ( str, count, fmt, ap); + n = plp_vsnprintf ( str, count, fmt, ap); VA_END; - return( strlen( str ) ); + return( n ); } -static void dopr( char *buffer, const char *format, va_list args ) + +/* VARARGS3 */ +#ifdef HAVE_STDARGS + int plp_unsafe_snprintf (char *str,size_t count,const char *fmt,...) +#else + int plp_unsafe_snprintf (va_alist) va_dcl +#endif +{ +#ifndef HAVE_STDARGS + char *str; + size_t count; + char *fmt; +#endif + int n = 0; + VA_LOCAL_DECL + + VA_START (fmt); + VA_SHIFT (str, char *); + VA_SHIFT (count, size_t ); + VA_SHIFT (fmt, char *); + n = plp_unsafe_vsnprintf ( str, count, fmt, ap); + VA_END; + return( n ); +} + static void dopr( int visible_control, char **buffer, int *left, const char *format, va_list args ) { int ch; - long value; + union value value; int longflag = 0; + int quadflag = 0; char *strvalue; int ljust; int len; @@ -207,22 +669,30 @@ static void dopr( char *buffer, const char *format, va_list args ) int set_precision; double dval; int err = errno; + int base = 0; + int signed_val = 0; - output = buffer; while( (ch = *format++) ){ switch( ch ){ case '%': - ljust = len = zpad = 0; + longflag = quadflag = + ljust = len = zpad = base = signed_val = 0; precision = -1; set_precision = 0; - nextch: + nextch: ch = *format++; switch( ch ){ case 0: - dostr( "**end of format**" ); + dostr( buffer, left, "**end of format**" ); return; case '-': ljust = 1; goto nextch; case '.': set_precision = 1; precision = 0; goto nextch; - case '*': len = va_arg( args, int ); goto nextch; + case '*': + if( set_precision ){ + precision = va_arg( args, int ); + } else { + len = va_arg( args, int ); + } + goto nextch; case '0': /* set zero padding if len not set */ if(len==0 && set_precision == 0 ) zpad = '0'; case '1': case '2': case '3': @@ -234,76 +704,91 @@ static void dopr( char *buffer, const char *format, va_list args ) len = len*10 + ch - '0'; } goto nextch; - case 'l': longflag = 1; goto nextch; + case 'l': ++longflag; goto nextch; + case 'q': +#if !defined( HAVE_QUAD_T ) + dostr( buffer, left, "*no quad_t support *"); + return; +#endif + quadflag = 1; + goto nextch; case 'u': case 'U': - /*fmtnum(value,base,dosign,ljust,len, zpad, precision) */ - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 10,0, ljust, len, zpad, precision ); break; + if( base == 0 ){ base = 10; signed_val = 0; } case 'o': case 'O': - /*fmtnum(value,base,dosign,ljust,len, zpad, precision) */ - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 8,0, ljust, len, zpad, precision ); break; + if( base == 0 ){ base = 8; signed_val = 0; } case 'd': case 'D': - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 10,1, ljust, len, zpad, precision ); break; + if( base == 0 ){ base = 10; signed_val = 1; } case 'x': - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 16,0, ljust, len, zpad, precision ); break; + if( base == 0 ){ base = 16; signed_val = 0; } case 'X': - if( longflag ){ - value = va_arg( args, long ); + if( base == 0 ){ base = -16; signed_val = 0; } +#if defined( HAVE_QUAD_T ) + if( quadflag ){ + value.qvalue = va_arg( args, quad_t ); + fmtquad( buffer, left, &value,base,signed_val, ljust, len, zpad, precision ); + break; + } else +#endif + if( longflag > 1 ){ +#if defined(HAVE_LONG_LONG) + if( signed_val ){ + value.value = va_arg( args, long long ); + } else { + value.value = va_arg( args, unsigned long long ); + } +#else + if( signed_val ){ + value.value = va_arg( args, long ); + } else { + value.value = va_arg( args, unsigned long ); + } +#endif + } else if( longflag ){ + if( signed_val ){ + value.value = va_arg( args, long ); + } else { + value.value = va_arg( args, unsigned long ); + } } else { - value = va_arg( args, int ); + if( signed_val ){ + value.value = va_arg( args, int ); + } else { + value.value = va_arg( args, unsigned int ); + } } - fmtnum( value,-16,0, ljust, len, zpad, precision ); break; + fmtnum( buffer, left, &value,base,signed_val, ljust, len, zpad, precision ); break; case 's': strvalue = va_arg( args, char *); - fmtstr( strvalue,ljust,len, zpad, precision ); + fmtstr( visible_control, buffer, left, strvalue,ljust,len, zpad, precision ); break; case 'c': ch = va_arg( args, int ); { char b[2]; - int vsb = visible_control; b[0] = ch; b[1] = 0; - visible_control = 0; - fmtstr( b,ljust,len, zpad, precision ); - visible_control = vsb; + fmtstr( 0, buffer, left, b,ljust,len, zpad, precision ); } break; - case 'f': case 'g': + case 'f': case 'g': case 'e': dval = va_arg( args, double ); - fmtdouble( ch, dval,ljust,len, zpad, precision ); break; + fmtdouble( buffer, left, ch, dval,ljust,len, zpad, precision ); break; case 'm': - fmtstr( plp_Errormsg(err),ljust,len, zpad, precision ); break; - case '%': dopr_outch( ch ); continue; + { char shortbuffer[32]; + fmtstr( visible_control, buffer, left, + plp_Errormsg(err, shortbuffer),ljust,len, zpad, precision ); + } + break; + case '%': dopr_outch( buffer, left, ch ); continue; default: - dostr( "???????" ); + dostr( buffer, left, "???????" ); } longflag = 0; break; default: - dopr_outch( ch ); + dopr_outch( buffer, left, ch ); break; } } - *output = 0; } /* @@ -312,63 +797,69 @@ static void dopr( char *buffer, const char *format, va_list args ) * len = minimum length * precision = numbers of chars in string to use */ -static void -fmtstr( char *value, int ljust, int len, int zpad, int precision ) + static void + fmtstr( int visible_control, char **buffer, int *left, + char *value, int ljust, int len, int zpad, int precision ) { - int padlen, strlen, i, c; /* amount to pad */ + int padlen, strlenv, i, c; /* amount to pad */ if( value == 0 ){ value = ""; } - if( precision > 0 ){ - strlen = precision; - } else { - /* cheap strlen so you do not have library call */ - for( strlen = 0; (c=value[strlen]); ++ strlen ){ - if( visible_control && iscntrl( c ) && !isspace( c ) ){ - ++strlen; - } + /* cheap strlen so you do not have library call */ + for( strlenv = i = 0; (c=CVAL(value+i)); ++i ){ + if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){ + ++strlenv; } + ++strlenv; + } + if( precision > 0 && strlenv > precision ){ + strlenv = precision; } - padlen = len - strlen; + padlen = len - strlenv; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; while( padlen > 0 ) { - dopr_outch( ' ' ); + dopr_outch( buffer, left, ' ' ); --padlen; } /* output characters */ - for( i = 0; (c = value[i]); ++i ){ - if( visible_control && iscntrl( c ) && !isspace( c ) ){ - dopr_outch('^'); + for( i = 0; i < strlenv && (c = CVAL(value+i)); ++i ){ + if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){ + dopr_outch(buffer, left, '^'); c = ('@' | (c & 0x1F)); } - dopr_outch(c); + dopr_outch(buffer, left, c); } while( padlen < 0 ) { - dopr_outch( ' ' ); + dopr_outch( buffer, left, ' ' ); ++padlen; } } -static void -fmtnum( long value, int base, int dosign, int ljust, + static void + fmtnum( char **buffer, int *left, + union value *value, int base, int dosign, int ljust, int len, int zpad, int precision ) { int signvalue = 0; +#if defined(HAVE_LONG_LONG) + unsigned long long uvalue; +#else unsigned long uvalue; - char convert[20]; +#endif + char convert[sizeof( union value) * 8 + 16]; int place = 0; int padlen = 0; /* amount to pad */ int caps = 0; - /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", - value, base, dosign, ljust, len, zpad )); */ - uvalue = value; + /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", + value, base, dosign, ljust, len, zpad );/ **/ + uvalue = value->value; if( dosign ){ - if( value < 0 ) { + if( value->value < 0 ) { signvalue = '-'; - uvalue = -value; + uvalue = -value->value; } } if( base < 0 ){ @@ -385,71 +876,148 @@ fmtnum( long value, int base, int dosign, int ljust, padlen = len - place; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; - /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n", - convert,place,signvalue,padlen)); */ + /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n", + convert,place,signvalue,padlen); / **/ if( zpad && padlen > 0 ){ if( signvalue ){ - dopr_outch( signvalue ); + dopr_outch( buffer, left, signvalue ); --padlen; signvalue = 0; } while( padlen > 0 ){ - dopr_outch( zpad ); + dopr_outch( buffer, left, zpad ); --padlen; } } while( padlen > 0 ) { - dopr_outch( ' ' ); + dopr_outch( buffer, left, ' ' ); --padlen; } - if( signvalue ) dopr_outch( signvalue ); - while( place > 0 ) dopr_outch( convert[--place] ); + if( signvalue ) dopr_outch( buffer, left, signvalue ); + while( place > 0 ) dopr_outch( buffer, left, convert[--place] ); while( padlen < 0 ){ - dopr_outch( ' ' ); + dopr_outch( buffer, left, ' ' ); ++padlen; } } -static void -fmtdouble( int fmt, double value, int ljust, int len, int zpad, int precision ) +#if defined(HAVE_QUAD_T) + + static void + fmtquad( char **buffer, int *left, + union value *value, int base, int dosign, int ljust, + int len, int zpad, int precision ) { - char convert[128]; - char fmtstr[128]; - int l; + int signvalue = 0; + int place = 0; + int padlen = 0; /* amount to pad */ + int caps = 0; + int i, c; + union { + quad_t qvalue; + unsigned char qconvert[sizeof(quad_t)]; + } vvalue; + char convert[2*sizeof(quad_t)+1]; + + /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", + value, base, dosign, ljust, len, zpad );/ **/ + vvalue.qvalue = value->qvalue; + + if( base < 0 ){ + caps = 1; + } - if( len == 0 ) len = 10; - if( len > sizeof(convert) - 10 ){ - len = sizeof(convert) - 10; + for( i = 0; i < (int)sizeof(quad_t); ++i ){ + c = vvalue.qconvert[i]; + convert[2*i] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[ (c >> 4) & 0xF]; + convert[2*i+1] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[ c & 0xF]; } - if( precision > sizeof(convert) - 10 ){ - precision = sizeof(convert) - 10; + convert[2*i] = 0; + + place = strlen(convert); + padlen = len - place; + if( padlen < 0 ) padlen = 0; + if( ljust ) padlen = -padlen; + /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n", + convert,place,signvalue,padlen); / **/ + if( zpad && padlen > 0 ){ + if( signvalue ){ + dopr_outch( buffer, left, signvalue ); + --padlen; + signvalue = 0; + } + while( padlen > 0 ){ + dopr_outch( buffer, left, zpad ); + --padlen; + } } - if( precision > len ) precision = len; - strcpy( fmtstr, "%" ); - if( ljust ) strcat(fmtstr, "-" ); - if( len ){ - sprintf( fmtstr+strlen(fmtstr), "%d", len ); + while( padlen > 0 ) { + dopr_outch( buffer, left, ' ' ); + --padlen; } - if( precision > 0 ){ - sprintf( fmtstr+strlen(fmtstr), ".%d", precision ); + if( signvalue ) dopr_outch( buffer, left, signvalue ); + while( place > 0 ) dopr_outch( buffer, left, convert[--place] ); + while( padlen < 0 ){ + dopr_outch( buffer, left, ' ' ); + ++padlen; } - l = strlen( fmtstr ); - fmtstr[l] = fmt; - fmtstr[l+1] = 0; - sprintf( convert, fmtstr, value ); - dostr( convert ); } -static void dostr( char *str ) +#endif + + static void mystrcat(char *dest, char *src ) { - while(*str) dopr_outch(*str++); + if( dest && src ){ + dest += safestrlen(dest); + strcpy(dest,src); + } +} + + static void + fmtdouble( char **buffer, int *left, + int fmt, double value, int ljust, int len, int zpad, int precision ) +{ + char convert[sizeof( union value) * 8 + 512]; + char formatstr[128]; + + /* fprintf(stderr,"len %d, precision %d\n", len, precision ); */ + if( len > 255 ){ + len = 255; + } + if( precision > 255 ){ + precision = 255; + } + if( precision >= 0 && len > 0 && precision > len ) precision = len; + strcpy( formatstr, "%" ); /* 1 */ + if( ljust ) mystrcat(formatstr, "-" ); /* 1 */ + if( zpad ) mystrcat(formatstr, "0" ); /* 1 */ + if( len >= 0 ){ + sprintf( formatstr+strlen(formatstr), "%d", len ); /* 3 */ + } + if( precision >= 0 ){ + sprintf( formatstr+strlen(formatstr), ".%d", precision ); /* 3 */ + } + /* format string will be at most 10 chars long ... */ + sprintf( formatstr+strlen(formatstr), "%c", fmt ); + /* this is easier than trying to do the portable dtostr */ + /* fprintf(stderr,"format string '%s'\n", formatstr); */ + sprintf( convert, formatstr, value ); + dostr( buffer, left, convert ); +} + + static void dostr( char **buffer, int *left, char *str ) +{ + if(str)while(*str) dopr_outch( buffer, left, *str++ ); } -static void dopr_outch( int c ) + static void dopr_outch( char **buffer, int *left, int c ) { - if( end == 0 || output < end ){ - *output++ = c; + if( *left > 0 ){ + *(*buffer)++ = c; } + *left -= 1; } @@ -461,29 +1029,26 @@ static void dopr_outch( int c ) * Patrick Powell Tue Apr 11 08:05:05 PDT 1995 ****************************************************************************/ /****************************************************************************/ -#if !defined(HAVE_STRERROR) - -# if defined(HAVE_SYS_NERR) -# if !defined(HAVE_SYS_NERR_DEF) - extern int sys_nerr; -# endif -# define num_errors (sys_nerr) -# else -# define num_errors (-1) /* always use "errno=%d" */ -# endif +#if !defined(HAVE_STRERROR) +# undef num_errors # if defined(HAVE_SYS_ERRLIST) -# if !defined(HAVE_SYS_ERRLIST_DEF) +# if !defined(HAVE_DECL_SYS_ERRLIST) extern const char *const sys_errlist[]; # endif -# else -# undef num_errors -# define num_errors (-1) /* always use "errno=%d" */ +# if defined(HAVE_SYS_NERR) +# if !defined(HAVE_DECL_SYS_NERR) + extern int sys_nerr; +# endif +# define num_errors (sys_nerr) +# endif +# endif +# if !defined(num_errors) +# define num_errors (-1) /* always use "errno=%d" */ # endif - #endif -static char * plp_Errormsg ( int err ) + static char * plp_Errormsg ( int err, char *buffer /* int maxlen = 32 */) { char *cp; @@ -496,10 +1061,8 @@ static char * plp_Errormsg ( int err ) } else # endif { - static char msgbuf[32]; /* holds "errno=%d". */ - /* SAFE use of sprintf */ - (void) sprintf (msgbuf, "errno=%d", err); - cp = msgbuf; + (void) sprintf (buffer, "errno=%d", err); + cp = buffer; } #endif return (cp); @@ -507,23 +1070,47 @@ static char * plp_Errormsg ( int err ) #if defined(TEST) #include -int main( void ) + int main( void ) { char buffer[128]; char *t; char *test1 = "01234"; + int n; errno = 1; - plp_snprintf( buffer, sizeof(buffer), (t="errno '%m'")); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "%s = '%s'\n", t, buffer ); - plp_snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "%s = '%s'\n", t, buffer ); + buffer[0] = 0; + n = snprintf( buffer, 0, (t="test")); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t="errno '%m'")); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12.1g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12.3g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); +#if defined(HAVE_LONG_LONG) + n = snprintf( buffer, sizeof(buffer), (t = "%llx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%llx"), (long long)1, (long long)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%qx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%qx"), (quad_t)1, (quad_t)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); +#endif + n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0x89ABCDEF, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), t, 0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%12.2f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%0.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%1.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%1.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); + n = snprintf( buffer, sizeof(buffer), (t = "%5.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); return(0); } #endif diff --git a/po/bg.po b/po/bg.po index 8cef432..16676d0 100644 --- a/po/bg.po +++ b/po/bg.po @@ -4596,7 +4596,7 @@ msgstr "Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ръчен Ñкенер" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Симулира ръчен Ñкенер. Ръчните Ñкенери чеÑто не знаÑÑ‚ виÑочината на " "образа а приори. ВмеÑто това, те връщат ÑтойноÑÑ‚ от -1. ПуÑкането на " @@ -4938,7 +4938,7 @@ msgstr "Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ръчен Ñкенер" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Симулира ръчен Ñкенер. Ръчните Ñкенери не знаÑÑ‚ виÑочината на " diff --git a/po/cs.po b/po/cs.po index 20dd87a..2423fda 100644 --- a/po/cs.po +++ b/po/cs.po @@ -4584,7 +4584,7 @@ msgstr "Simulace ruÄního skeneru" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuluje ruÄní skener. RuÄní skenery obvykle neznají výšku obrázku " "pÅ™edem. Proto vracejí výšku 1. Tato volba umožnuje otestovat, jestli se " @@ -4925,7 +4925,7 @@ msgstr "Simulace ruÄního skeneru" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuluje ruÄní skener. RuÄní skenery obvykle neznají výšku obrázku " diff --git a/po/da.po b/po/da.po index 4eb40ea..c745aa1 100644 --- a/po/da.po +++ b/po/da.po @@ -4604,7 +4604,7 @@ msgstr "HÃ¥ndskanner simulering" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulerer en hÃ¥ndskanner. Oftest kender en hÃ¥ndskanner ikke billedhøjden " "i forvejen. I stedet for returnerer de en højde pÃ¥ -1. Sættes denne " @@ -4944,7 +4944,7 @@ msgstr "HÃ¥ndskanner simulering" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulerer en hÃ¥ndskanner. HÃ¥ndskannere kender ikke forud billedhøjden. I " diff --git a/po/de.po b/po/de.po index 77d2eec..84eb9c7 100644 --- a/po/de.po +++ b/po/de.po @@ -4758,7 +4758,7 @@ msgstr "Handscanner Simulation" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuliere einen Handscanner. Bei Handscannern steht meistens die " "Bildhöhe nicht von vornherein fest. Stattdessen geben sie eine Höhe von " @@ -5148,7 +5148,7 @@ msgstr "Handscanner-Simulation" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuliere einen Handscanner. Bei Handscannern steht meistens die " diff --git a/po/en_GB.po b/po/en_GB.po index e5548c3..1999263 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -4611,11 +4611,11 @@ msgstr "Hand-Scanner Simulation" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " -"option allows to test whether a frontend can handle this correctly." +"option allows one to test whether a frontend can handle this correctly." #: ../backend/pnm.c:283 #, no-c-format @@ -4952,12 +4952,12 @@ msgstr "Hand-scanner simulation" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " -"allows to test whether a frontend can handle this correctly. This " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." #: ../backend/test.c:366 diff --git a/po/eo.po b/po/eo.po index 13b536d..cff2397 100644 --- a/po/eo.po +++ b/po/eo.po @@ -4635,7 +4635,7 @@ msgstr "Simulado de mana skanilo" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Äœi simulas akiradon per mana skanilo. La manaj skaniloj ofte ne rekonas " "la alton de la bildon apriore, do ili revenigas alton kun valoro -1. Per " @@ -4977,7 +4977,7 @@ msgstr "Simulado de mana skanilo" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Äœi simulas akiradon per mana skanilo. La manaj skaniloj ofte ne rekonas " diff --git a/po/es.po b/po/es.po index b71b23f..5141379 100644 --- a/po/es.po +++ b/po/es.po @@ -4666,7 +4666,7 @@ msgstr "Simulación de escáner manual" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simula un escáner de mano. Los escáneres de mano a menudo no conocen a " "priori la distancia a la imagen. En su lugar utiliza una altura de " @@ -5011,7 +5011,7 @@ msgstr "Simulación de escaneo manual" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simula un escáner de mano. Los escáneres de mano a menudo no conocen a " diff --git a/po/fi.po b/po/fi.po index ecb51c4..b164f2b 100644 --- a/po/fi.po +++ b/po/fi.po @@ -4586,7 +4586,7 @@ msgstr "Käsikuvanlukijasimulaatio" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuloi käsiskanneria. Käsiskannerit eivät yleensä tiedä kuvan kokoa " "etukäteen. Sen sijaan, ne palauttavat kuvan korkeudeksi -1. Tällä " @@ -4926,7 +4926,7 @@ msgstr "Käsikuvanlukijasimulaatio" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuloi käsikuvnalukijaa. Käsikuvanlukijat eivät tiedä kuvan korkeutta " diff --git a/po/fr.po b/po/fr.po index 5fe9ed3..2dfcf61 100644 --- a/po/fr.po +++ b/po/fr.po @@ -4713,7 +4713,7 @@ msgstr "Simulation de scanner à main." 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simule une numérisation avec un scanner à main. Les scanners à main ne " "connaissent pas à priori la hauteur de l'image. A la place, ils " @@ -5057,7 +5057,7 @@ msgstr "Simulation de scanner à main" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simule un scanner à main. Les scanners à main ne connaissent pas à " diff --git a/po/gl.po b/po/gl.po index 7eb520a..f322936 100644 --- a/po/gl.po +++ b/po/gl.po @@ -4668,7 +4668,7 @@ msgstr "Simulación de escáner de man" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Semella un escáner de man. Os escáneres de man adoitan descoñecer a " "priori a distancia á imaxe. Na súa vez utiliza unha altura de retorno " @@ -5012,7 +5012,7 @@ msgstr "Simulación de escáner manual" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Semella un escáner de man. Os escáneres de man adoitan descoñecer a " diff --git a/po/it.po b/po/it.po index 06a693a..f244d16 100644 --- a/po/it.po +++ b/po/it.po @@ -4661,7 +4661,7 @@ msgstr "Simulazione di uno scanner manuale" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simula l'acquisizione mediante uno scanner manuale; questi scanner " "spesso non conoscono l'altezza dell'immagine a priori e restituiscono " @@ -5007,7 +5007,7 @@ msgstr "Simulazione di uno scanner manuale" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulazione di acquisizione mediante uno scanner manuale; questi scanner " diff --git a/po/ja.po b/po/ja.po index cb78847..1f4497e 100644 --- a/po/ja.po +++ b/po/ja.po @@ -4567,7 +4567,7 @@ msgstr "ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã€€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã‚’シミュレートã—ã¾ã™ã€‚ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã¯ã€ãŸã„ã¦ã„ã®å ´" "åˆã€ã‚¤ãƒ¡ãƒ¼ã‚¸ã®é«˜ã•ãŒäº‹å‰ã«ã¯ã‚ã‹ã‚Šã¾ã›ã‚“。ãã®ä»£ã‚ã‚Šã€é«˜ã•ã¨ã—ã¦ãƒ¼ï¼‘ã‚’è¿”" @@ -4891,7 +4891,7 @@ msgstr "ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã‚’シミュレート" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" diff --git a/po/nb.po b/po/nb.po index 7cff445..88880e7 100644 --- a/po/nb.po +++ b/po/nb.po @@ -4534,7 +4534,7 @@ msgstr "HÃ¥ndskanner simulering" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" #: ../backend/pnm.c:283 @@ -4846,7 +4846,7 @@ msgstr "" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" diff --git a/po/nl.po b/po/nl.po index a8df7d3..2cf9aa4 100644 --- a/po/nl.po +++ b/po/nl.po @@ -4745,7 +4745,7 @@ msgstr "Handscanner simulatie" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuleer een handscanner. Bij handscanners staat meestal de beeldhoogte " "van te voren niet vast. In plaats daarvan geven zij een hoogte van -1 " @@ -5132,7 +5132,7 @@ msgstr "Handscanner-simulatie" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuleer een handscanner. Bij handscanners staat tenminste de " diff --git a/po/pl.po b/po/pl.po index 1624c1f..42cdf0e 100644 --- a/po/pl.po +++ b/po/pl.po @@ -4652,7 +4652,7 @@ msgstr "Symulacja skanera rÄ™cznego" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Symuluje skaner rÄ™czny. Skanery rÄ™czne zwykle nie znajÄ… wysokoÅ›ci " "obrazka. Zamiast tego zwracajÄ… wysokość -1. Ustawienie tej opcji pozwala " @@ -4994,7 +4994,7 @@ msgstr "Symulacja skanera rÄ™cznego" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Symuluje skaner rÄ™czny. Skanery rÄ™czne zwykle nie znajÄ… wysokoÅ›ci " diff --git a/po/pt.po b/po/pt.po index 13e28e5..147df28 100644 --- a/po/pt.po +++ b/po/pt.po @@ -3979,7 +3979,7 @@ msgstr "" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" #: ../backend/pnm.c:283 @@ -4291,7 +4291,7 @@ msgstr "" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" diff --git a/po/ru.po b/po/ru.po index f99d27f..ffd47bd 100644 --- a/po/ru.po +++ b/po/ru.po @@ -4661,7 +4661,7 @@ msgstr "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Имитирует ручной Ñканер. Ручные Ñканеры чаÑто не имеют информации о " "длине изображениÑ. ВмеÑто Ñтого они возвращает длину -1. УÑтановка Ñтого " @@ -4992,7 +4992,7 @@ msgstr "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Имитировать ручной Ñканер. Ручные Ñканеры никогда не знают о выÑоте " diff --git a/po/sane-backends.pot b/po/sane-backends.pot deleted file mode 100644 index efb2b9f..0000000 --- a/po/sane-backends.pot +++ /dev/null @@ -1,5503 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-09-30 21:26-0400\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: ../include/sane/saneopts.h:154 -#, no-c-format -msgid "Number of options" -msgstr "" - -#: ../include/sane/saneopts.h:156 -#, no-c-format -msgid "Standard" -msgstr "" - -#: ../include/sane/saneopts.h:157 ../backend/artec_eplus48u.c:2884 -#: ../backend/epson.c:3284 ../backend/epson2.c:1281 ../backend/genesys.c:5472 -#: ../backend/gt68xx.c:703 ../backend/hp3500.c:1003 -#: ../backend/hp-option.c:3297 ../backend/kvs1025_opt.c:640 -#: ../backend/kvs20xx_opt.c:284 ../backend/kvs40xx_opt.c:505 -#: ../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:158 -#: ../backend/plustek.c:808 ../backend/plustek_pp.c:747 -#: ../backend/sceptre.c:702 ../backend/snapscan-options.c:550 -#: ../backend/teco1.c:1095 ../backend/teco2.c:1914 ../backend/teco3.c:920 -#: ../backend/test.c:647 ../backend/u12.c:546 ../backend/umax.c:5176 -#: ../backend/umax_pp.c:580 -#, no-c-format -msgid "Geometry" -msgstr "" - -#: ../include/sane/saneopts.h:158 ../backend/artec_eplus48u.c:2805 -#: ../backend/canon.c:1498 ../backend/genesys.c:5532 ../backend/gt68xx.c:672 -#: ../backend/hp-option.c:2953 ../backend/kvs1025_opt.c:704 -#: ../backend/leo.c:871 ../backend/ma1509.c:599 ../backend/matsushita.c:1189 -#: ../backend/microtek2.h:600 ../backend/mustek.c:4411 -#: ../backend/mustek_usb.c:353 ../backend/mustek_usb2.c:431 -#: ../backend/niash.c:756 ../backend/plustek.c:854 ../backend/plustek_pp.c:793 -#: ../backend/sceptre.c:750 ../backend/snapscan-options.c:617 -#: ../backend/stv680.c:1067 ../backend/teco1.c:1143 ../backend/teco2.c:1962 -#: ../backend/teco3.c:968 ../backend/u12.c:592 ../backend/umax.c:5226 -#: ../backend/umax_pp.c:629 -#, no-c-format -msgid "Enhancement" -msgstr "" - -#: ../include/sane/saneopts.h:159 ../backend/epson.c:3183 -#: ../backend/epson2.c:1206 ../backend/kvs20xx_opt.c:365 -#: ../backend/kvs40xx_opt.c:596 ../backend/rts8891.c:2825 -#: ../backend/snapscan-options.c:923 ../backend/umax.c:5565 -#, no-c-format -msgid "Advanced" -msgstr "" - -#: ../include/sane/saneopts.h:160 -#, no-c-format -msgid "Sensors" -msgstr "" - -#: ../include/sane/saneopts.h:162 -#, no-c-format -msgid "Preview" -msgstr "" - -#: ../include/sane/saneopts.h:163 -#, no-c-format -msgid "Force monochrome preview" -msgstr "" - -#: ../include/sane/saneopts.h:164 -#, no-c-format -msgid "Bit depth" -msgstr "" - -#: ../include/sane/saneopts.h:165 ../backend/canon.c:1145 ../backend/leo.c:781 -#: ../backend/pixma_sane_options.c:45 -#, no-c-format -msgid "Scan mode" -msgstr "" - -#: ../include/sane/saneopts.h:166 -#, no-c-format -msgid "Scan speed" -msgstr "" - -#: ../include/sane/saneopts.h:167 -#, no-c-format -msgid "Scan source" -msgstr "" - -#: ../include/sane/saneopts.h:168 -#, no-c-format -msgid "Force backtracking" -msgstr "" - -#: ../include/sane/saneopts.h:169 -#, no-c-format -msgid "Top-left x" -msgstr "" - -#: ../include/sane/saneopts.h:170 -#, no-c-format -msgid "Top-left y" -msgstr "" - -#: ../include/sane/saneopts.h:171 -#, no-c-format -msgid "Bottom-right x" -msgstr "" - -#: ../include/sane/saneopts.h:172 -#, no-c-format -msgid "Bottom-right y" -msgstr "" - -#: ../include/sane/saneopts.h:173 ../backend/canon.c:1221 -#: ../backend/pixma_sane_options.c:298 -#, no-c-format -msgid "Scan resolution" -msgstr "" - -#: ../include/sane/saneopts.h:174 -#, no-c-format -msgid "X-resolution" -msgstr "" - -#: ../include/sane/saneopts.h:175 -#, no-c-format -msgid "Y-resolution" -msgstr "" - -#: ../include/sane/saneopts.h:176 -#, no-c-format -msgid "Page width" -msgstr "" - -#: ../include/sane/saneopts.h:177 -#, no-c-format -msgid "Page height" -msgstr "" - -#: ../include/sane/saneopts.h:178 -#, no-c-format -msgid "Use custom gamma table" -msgstr "" - -#: ../include/sane/saneopts.h:179 -#, no-c-format -msgid "Image intensity" -msgstr "" - -#: ../include/sane/saneopts.h:180 -#, no-c-format -msgid "Red intensity" -msgstr "" - -#: ../include/sane/saneopts.h:181 -#, no-c-format -msgid "Green intensity" -msgstr "" - -#: ../include/sane/saneopts.h:182 -#, no-c-format -msgid "Blue intensity" -msgstr "" - -#: ../include/sane/saneopts.h:183 -#, no-c-format -msgid "Brightness" -msgstr "" - -#: ../include/sane/saneopts.h:184 -#, no-c-format -msgid "Contrast" -msgstr "" - -#: ../include/sane/saneopts.h:185 -#, no-c-format -msgid "Grain size" -msgstr "" - -#: ../include/sane/saneopts.h:186 -#, no-c-format -msgid "Halftoning" -msgstr "" - -#: ../include/sane/saneopts.h:187 -#, no-c-format -msgid "Black level" -msgstr "" - -#: ../include/sane/saneopts.h:188 -#, no-c-format -msgid "White level" -msgstr "" - -#: ../include/sane/saneopts.h:189 -#, no-c-format -msgid "White level for red" -msgstr "" - -#: ../include/sane/saneopts.h:190 -#, no-c-format -msgid "White level for green" -msgstr "" - -#: ../include/sane/saneopts.h:191 -#, no-c-format -msgid "White level for blue" -msgstr "" - -#: ../include/sane/saneopts.h:192 -#, no-c-format -msgid "Shadow" -msgstr "" - -#: ../include/sane/saneopts.h:193 -#, no-c-format -msgid "Shadow for red" -msgstr "" - -#: ../include/sane/saneopts.h:194 -#, no-c-format -msgid "Shadow for green" -msgstr "" - -#: ../include/sane/saneopts.h:195 -#, no-c-format -msgid "Shadow for blue" -msgstr "" - -#: ../include/sane/saneopts.h:196 -#, no-c-format -msgid "Highlight" -msgstr "" - -#: ../include/sane/saneopts.h:197 -#, no-c-format -msgid "Highlight for red" -msgstr "" - -#: ../include/sane/saneopts.h:198 -#, no-c-format -msgid "Highlight for green" -msgstr "" - -#: ../include/sane/saneopts.h:199 -#, no-c-format -msgid "Highlight for blue" -msgstr "" - -#: ../include/sane/saneopts.h:200 -#, no-c-format -msgid "Hue" -msgstr "" - -#: ../include/sane/saneopts.h:201 -#, no-c-format -msgid "Saturation" -msgstr "" - -#: ../include/sane/saneopts.h:202 -#, no-c-format -msgid "Filename" -msgstr "" - -#: ../include/sane/saneopts.h:203 -#, no-c-format -msgid "Halftone pattern size" -msgstr "" - -#: ../include/sane/saneopts.h:204 -#, no-c-format -msgid "Halftone pattern" -msgstr "" - -#: ../include/sane/saneopts.h:205 -#, no-c-format -msgid "Bind X and Y resolution" -msgstr "" - -#: ../include/sane/saneopts.h:206 ../backend/hp3900_sane.c:428 -#: ../backend/hp3900_sane.c:1021 ../backend/hp3900_sane.c:1421 -#: ../backend/hp-option.c:3235 ../backend/mustek_usb2.c:121 -#: ../backend/plustek.c:236 ../backend/plustek_pp.c:205 ../backend/u12.c:157 -#, no-c-format -msgid "Negative" -msgstr "" - -#: ../include/sane/saneopts.h:207 -#, no-c-format -msgid "Quality calibration" -msgstr "" - -#: ../include/sane/saneopts.h:208 -#, no-c-format -msgid "Double Optical Resolution" -msgstr "" - -#: ../include/sane/saneopts.h:209 -#, no-c-format -msgid "Bind RGB" -msgstr "" - -#: ../include/sane/saneopts.h:210 ../backend/sm3840.c:770 -#, no-c-format -msgid "Threshold" -msgstr "" - -#: ../include/sane/saneopts.h:211 -#, no-c-format -msgid "Analog gamma correction" -msgstr "" - -#: ../include/sane/saneopts.h:212 -#, no-c-format -msgid "Analog gamma red" -msgstr "" - -#: ../include/sane/saneopts.h:213 -#, no-c-format -msgid "Analog gamma green" -msgstr "" - -#: ../include/sane/saneopts.h:214 -#, no-c-format -msgid "Analog gamma blue" -msgstr "" - -#: ../include/sane/saneopts.h:215 -#, no-c-format -msgid "Bind analog gamma" -msgstr "" - -#: ../include/sane/saneopts.h:216 -#, no-c-format -msgid "Warmup lamp" -msgstr "" - -#: ../include/sane/saneopts.h:217 -#, no-c-format -msgid "Cal. exposure-time" -msgstr "" - -#: ../include/sane/saneopts.h:218 -#, no-c-format -msgid "Cal. exposure-time for red" -msgstr "" - -#: ../include/sane/saneopts.h:219 -#, no-c-format -msgid "Cal. exposure-time for green" -msgstr "" - -#: ../include/sane/saneopts.h:221 -#, no-c-format -msgid "Cal. exposure-time for blue" -msgstr "" - -#: ../include/sane/saneopts.h:222 -#, no-c-format -msgid "Scan exposure-time" -msgstr "" - -#: ../include/sane/saneopts.h:223 -#, no-c-format -msgid "Scan exposure-time for red" -msgstr "" - -#: ../include/sane/saneopts.h:224 -#, no-c-format -msgid "Scan exposure-time for green" -msgstr "" - -#: ../include/sane/saneopts.h:226 -#, no-c-format -msgid "Scan exposure-time for blue" -msgstr "" - -#: ../include/sane/saneopts.h:227 -#, no-c-format -msgid "Set exposure-time" -msgstr "" - -#: ../include/sane/saneopts.h:228 -#, no-c-format -msgid "Cal. lamp density" -msgstr "" - -#: ../include/sane/saneopts.h:229 -#, no-c-format -msgid "Scan lamp density" -msgstr "" - -#: ../include/sane/saneopts.h:230 -#, no-c-format -msgid "Set lamp density" -msgstr "" - -#: ../include/sane/saneopts.h:231 ../backend/umax.c:5829 -#, no-c-format -msgid "Lamp off at exit" -msgstr "" - -#: ../include/sane/saneopts.h:245 -#, no-c-format -msgid "" -"Read-only option that specifies how many options a specific devices supports." -msgstr "" - -#: ../include/sane/saneopts.h:248 -#, no-c-format -msgid "Source, mode and resolution options" -msgstr "" - -#: ../include/sane/saneopts.h:249 -#, no-c-format -msgid "Scan area and media size options" -msgstr "" - -#: ../include/sane/saneopts.h:250 -#, no-c-format -msgid "Image modification options" -msgstr "" - -#: ../include/sane/saneopts.h:251 -#, no-c-format -msgid "Hardware specific options" -msgstr "" - -#: ../include/sane/saneopts.h:252 -#, no-c-format -msgid "Scanner sensors and buttons" -msgstr "" - -#: ../include/sane/saneopts.h:255 -#, no-c-format -msgid "Request a preview-quality scan." -msgstr "" - -#: ../include/sane/saneopts.h:258 -#, no-c-format -msgid "" -"Request that all previews are done in monochrome mode. On a three-pass " -"scanner this cuts down the number of passes to one and on a one-pass " -"scanner, it reduces the memory requirements and scan-time of the preview." -msgstr "" - -#: ../include/sane/saneopts.h:264 -#, no-c-format -msgid "" -"Number of bits per sample, typical values are 1 for \"line-art\" and 8 for " -"multibit scans." -msgstr "" - -#: ../include/sane/saneopts.h:268 -#, no-c-format -msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." -msgstr "" - -#: ../include/sane/saneopts.h:271 -#, no-c-format -msgid "Determines the speed at which the scan proceeds." -msgstr "" - -#: ../include/sane/saneopts.h:274 -#, no-c-format -msgid "Selects the scan source (such as a document-feeder)." -msgstr "" - -#: ../include/sane/saneopts.h:277 -#, no-c-format -msgid "Controls whether backtracking is forced." -msgstr "" - -#: ../include/sane/saneopts.h:280 -#, no-c-format -msgid "Top-left x position of scan area." -msgstr "" - -#: ../include/sane/saneopts.h:283 -#, no-c-format -msgid "Top-left y position of scan area." -msgstr "" - -#: ../include/sane/saneopts.h:286 -#, no-c-format -msgid "Bottom-right x position of scan area." -msgstr "" - -#: ../include/sane/saneopts.h:289 -#, no-c-format -msgid "Bottom-right y position of scan area." -msgstr "" - -#: ../include/sane/saneopts.h:292 -#, no-c-format -msgid "Sets the resolution of the scanned image." -msgstr "" - -#: ../include/sane/saneopts.h:295 -#, no-c-format -msgid "Sets the horizontal resolution of the scanned image." -msgstr "" - -#: ../include/sane/saneopts.h:298 -#, no-c-format -msgid "Sets the vertical resolution of the scanned image." -msgstr "" - -#: ../include/sane/saneopts.h:301 -#, no-c-format -msgid "" -"Specifies the width of the media. Required for automatic centering of sheet-" -"fed scans." -msgstr "" - -#: ../include/sane/saneopts.h:305 -#, no-c-format -msgid "Specifies the height of the media." -msgstr "" - -#: ../include/sane/saneopts.h:308 -#, no-c-format -msgid "Determines whether a builtin or a custom gamma-table should be used." -msgstr "" - -#: ../include/sane/saneopts.h:312 -#, no-c-format -msgid "" -"Gamma-correction table. In color mode this option equally affects the red, " -"green, and blue channels simultaneously (i.e., it is an intensity gamma " -"table)." -msgstr "" - -#: ../include/sane/saneopts.h:317 -#, no-c-format -msgid "Gamma-correction table for the red band." -msgstr "" - -#: ../include/sane/saneopts.h:320 -#, no-c-format -msgid "Gamma-correction table for the green band." -msgstr "" - -#: ../include/sane/saneopts.h:323 -#, no-c-format -msgid "Gamma-correction table for the blue band." -msgstr "" - -#: ../include/sane/saneopts.h:326 -#, no-c-format -msgid "Controls the brightness of the acquired image." -msgstr "" - -#: ../include/sane/saneopts.h:329 -#, no-c-format -msgid "Controls the contrast of the acquired image." -msgstr "" - -#: ../include/sane/saneopts.h:332 -#, no-c-format -msgid "" -"Selects the \"graininess\" of the acquired image. Smaller values result in " -"sharper images." -msgstr "" - -#: ../include/sane/saneopts.h:336 -#, no-c-format -msgid "Selects whether the acquired image should be halftoned (dithered)." -msgstr "" - -#: ../include/sane/saneopts.h:339 ../include/sane/saneopts.h:354 -#, no-c-format -msgid "Selects what radiance level should be considered \"black\"." -msgstr "" - -#: ../include/sane/saneopts.h:342 ../include/sane/saneopts.h:363 -#, no-c-format -msgid "Selects what radiance level should be considered \"white\"." -msgstr "" - -#: ../include/sane/saneopts.h:345 -#, no-c-format -msgid "Selects what red radiance level should be considered \"white\"." -msgstr "" - -#: ../include/sane/saneopts.h:348 -#, no-c-format -msgid "Selects what green radiance level should be considered \"white\"." -msgstr "" - -#: ../include/sane/saneopts.h:351 -#, no-c-format -msgid "Selects what blue radiance level should be considered \"white\"." -msgstr "" - -#: ../include/sane/saneopts.h:356 -#, no-c-format -msgid "Selects what red radiance level should be considered \"black\"." -msgstr "" - -#: ../include/sane/saneopts.h:358 -#, no-c-format -msgid "Selects what green radiance level should be considered \"black\"." -msgstr "" - -#: ../include/sane/saneopts.h:360 -#, no-c-format -msgid "Selects what blue radiance level should be considered \"black\"." -msgstr "" - -#: ../include/sane/saneopts.h:365 -#, no-c-format -msgid "Selects what red radiance level should be considered \"full red\"." -msgstr "" - -#: ../include/sane/saneopts.h:367 -#, no-c-format -msgid "Selects what green radiance level should be considered \"full green\"." -msgstr "" - -#: ../include/sane/saneopts.h:370 -#, no-c-format -msgid "Selects what blue radiance level should be considered \"full blue\"." -msgstr "" - -#: ../include/sane/saneopts.h:374 -#, no-c-format -msgid "Controls the \"hue\" (blue-level) of the acquired image." -msgstr "" - -#: ../include/sane/saneopts.h:377 -#, no-c-format -msgid "" -"The saturation level controls the amount of \"blooming\" that occurs when " -"acquiring an image with a camera. Larger values cause more blooming." -msgstr "" - -#: ../include/sane/saneopts.h:382 -#, no-c-format -msgid "The filename of the image to be loaded." -msgstr "" - -#: ../include/sane/saneopts.h:385 -#, no-c-format -msgid "" -"Sets the size of the halftoning (dithering) pattern used when scanning " -"halftoned images." -msgstr "" - -#: ../include/sane/saneopts.h:389 -#, no-c-format -msgid "" -"Defines the halftoning (dithering) pattern for scanning halftoned images." -msgstr "" - -#: ../include/sane/saneopts.h:393 -#, no-c-format -msgid "Use same values for X and Y resolution" -msgstr "" - -#: ../include/sane/saneopts.h:395 -#, no-c-format -msgid "Swap black and white" -msgstr "" - -#: ../include/sane/saneopts.h:397 -#, no-c-format -msgid "Do a quality white-calibration" -msgstr "" - -#: ../include/sane/saneopts.h:399 -#, no-c-format -msgid "Use lens that doubles optical resolution" -msgstr "" - -#: ../include/sane/saneopts.h:401 ../include/sane/saneopts.h:413 -#, no-c-format -msgid "In RGB-mode use same values for each color" -msgstr "" - -#: ../include/sane/saneopts.h:403 -#, no-c-format -msgid "Select minimum-brightness to get a white point" -msgstr "" - -#: ../include/sane/saneopts.h:405 -#, no-c-format -msgid "Analog gamma-correction" -msgstr "" - -#: ../include/sane/saneopts.h:407 -#, no-c-format -msgid "Analog gamma-correction for red" -msgstr "" - -#: ../include/sane/saneopts.h:409 -#, no-c-format -msgid "Analog gamma-correction for green" -msgstr "" - -#: ../include/sane/saneopts.h:411 -#, no-c-format -msgid "Analog gamma-correction for blue" -msgstr "" - -#: ../include/sane/saneopts.h:415 -#, no-c-format -msgid "Warmup lamp before scanning" -msgstr "" - -#: ../include/sane/saneopts.h:417 -#, no-c-format -msgid "Define exposure-time for calibration" -msgstr "" - -#: ../include/sane/saneopts.h:419 -#, no-c-format -msgid "Define exposure-time for red calibration" -msgstr "" - -#: ../include/sane/saneopts.h:421 -#, no-c-format -msgid "Define exposure-time for green calibration" -msgstr "" - -#: ../include/sane/saneopts.h:423 -#, no-c-format -msgid "Define exposure-time for blue calibration" -msgstr "" - -#: ../include/sane/saneopts.h:425 -#, no-c-format -msgid "Define exposure-time for scan" -msgstr "" - -#: ../include/sane/saneopts.h:427 -#, no-c-format -msgid "Define exposure-time for red scan" -msgstr "" - -#: ../include/sane/saneopts.h:429 -#, no-c-format -msgid "Define exposure-time for green scan" -msgstr "" - -#: ../include/sane/saneopts.h:431 -#, no-c-format -msgid "Define exposure-time for blue scan" -msgstr "" - -#: ../include/sane/saneopts.h:433 -#, no-c-format -msgid "Enable selection of exposure-time" -msgstr "" - -#: ../include/sane/saneopts.h:435 -#, no-c-format -msgid "Define lamp density for calibration" -msgstr "" - -#: ../include/sane/saneopts.h:437 -#, no-c-format -msgid "Define lamp density for scan" -msgstr "" - -#: ../include/sane/saneopts.h:439 -#, no-c-format -msgid "Enable selection of lamp density" -msgstr "" - -#: ../include/sane/saneopts.h:441 ../backend/umax.c:5830 -#, no-c-format -msgid "Turn off lamp when program exits" -msgstr "" - -#: ../include/sane/saneopts.h:444 -#, no-c-format -msgid "Scan button" -msgstr "" - -#: ../include/sane/saneopts.h:445 -#, no-c-format -msgid "Email button" -msgstr "" - -#: ../include/sane/saneopts.h:446 -#, no-c-format -msgid "Fax button" -msgstr "" - -#: ../include/sane/saneopts.h:447 -#, no-c-format -msgid "Copy button" -msgstr "" - -#: ../include/sane/saneopts.h:448 -#, no-c-format -msgid "PDF button" -msgstr "" - -#: ../include/sane/saneopts.h:449 -#, no-c-format -msgid "Cancel button" -msgstr "" - -#: ../include/sane/saneopts.h:450 -#, no-c-format -msgid "Page loaded" -msgstr "" - -#: ../include/sane/saneopts.h:451 -#, no-c-format -msgid "Cover open" -msgstr "" - -#: ../include/sane/saneopts.h:454 -#, no-c-format -msgid "Color" -msgstr "" - -#: ../include/sane/saneopts.h:455 -#, no-c-format -msgid "Color Lineart" -msgstr "" - -#: ../include/sane/saneopts.h:456 -#, no-c-format -msgid "Color Halftone" -msgstr "" - -#: ../include/sane/saneopts.h:457 -#, no-c-format -msgid "Gray" -msgstr "" - -#: ../include/sane/saneopts.h:458 -#, no-c-format -msgid "Halftone" -msgstr "" - -#: ../include/sane/saneopts.h:459 -#, no-c-format -msgid "Lineart" -msgstr "" - -#: ../backend/sane_strstatus.c:59 -#, no-c-format -msgid "Success" -msgstr "" - -#: ../backend/sane_strstatus.c:62 -#, no-c-format -msgid "Operation not supported" -msgstr "" - -#: ../backend/sane_strstatus.c:65 -#, no-c-format -msgid "Operation was cancelled" -msgstr "" - -#: ../backend/sane_strstatus.c:68 -#, no-c-format -msgid "Device busy" -msgstr "" - -#: ../backend/sane_strstatus.c:71 -#, no-c-format -msgid "Invalid argument" -msgstr "" - -#: ../backend/sane_strstatus.c:74 -#, no-c-format -msgid "End of file reached" -msgstr "" - -#: ../backend/sane_strstatus.c:77 -#, no-c-format -msgid "Document feeder jammed" -msgstr "" - -#: ../backend/sane_strstatus.c:80 -#, no-c-format -msgid "Document feeder out of documents" -msgstr "" - -#: ../backend/sane_strstatus.c:83 -#, no-c-format -msgid "Scanner cover is open" -msgstr "" - -#: ../backend/sane_strstatus.c:86 -#, no-c-format -msgid "Error during device I/O" -msgstr "" - -#: ../backend/sane_strstatus.c:89 -#, no-c-format -msgid "Out of memory" -msgstr "" - -#: ../backend/sane_strstatus.c:92 -#, no-c-format -msgid "Access to resource has been denied" -msgstr "" - -#: ../backend/sane_strstatus.c:96 -#, no-c-format -msgid "Lamp not ready, please retry" -msgstr "" - -#: ../backend/sane_strstatus.c:101 -#, no-c-format -msgid "Scanner mechanism locked for transport" -msgstr "" - -#: ../backend/artec_eplus48u.c:2874 ../backend/pnm.c:282 -#, no-c-format -msgid "Defaults" -msgstr "" - -#: ../backend/artec_eplus48u.c:2876 -#, no-c-format -msgid "Set default values for enhancement controls." -msgstr "" - -#: ../backend/artec_eplus48u.c:2932 ../backend/canon.c:1616 -#, no-c-format -msgid "Calibration" -msgstr "" - -#: ../backend/artec_eplus48u.c:2941 -#, no-c-format -msgid "Calibrate before next scan" -msgstr "" - -#: ../backend/artec_eplus48u.c:2943 -#, no-c-format -msgid "" -"If enabled, the device will be calibrated before the next scan. Otherwise, " -"calibration is performed only before the first start." -msgstr "" - -#: ../backend/artec_eplus48u.c:2954 -#, no-c-format -msgid "Only perform shading-correction" -msgstr "" - -#: ../backend/artec_eplus48u.c:2956 -#, no-c-format -msgid "" -"If enabled, only the shading correction is performed during calibration. The " -"default values for gain, offset and exposure time, either build-in or from " -"the configuration file, are used." -msgstr "" - -#: ../backend/artec_eplus48u.c:2967 -#, no-c-format -msgid "Button state" -msgstr "" - -#: ../backend/avision.h: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 -#, no-c-format -msgid "Duplex scan" -msgstr "" - -#: ../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:159 -#, no-c-format -msgid "Calibrate Scanner" -msgstr "" - -#: ../backend/canon630u.c:160 -#, no-c-format -msgid "Force scanner calibration before scan" -msgstr "" - -#: ../backend/canon630u.c:259 ../backend/umax1220u.c:208 -#, no-c-format -msgid "Grayscale scan" -msgstr "" - -#: ../backend/canon630u.c:260 ../backend/umax1220u.c:209 -#, no-c-format -msgid "Do a grayscale rather than color scan" -msgstr "" - -#: ../backend/canon630u.c:306 -#, no-c-format -msgid "Analog Gain" -msgstr "" - -#: ../backend/canon630u.c:307 -#, no-c-format -msgid "Increase or decrease the analog gain of the CCD array" -msgstr "" - -#: ../backend/canon630u.c:347 ../backend/epson.h:68 ../backend/epson2.h:74 -#, no-c-format -msgid "Gamma Correction" -msgstr "" - -#: ../backend/canon630u.c:348 -#, no-c-format -msgid "Selects the gamma corrected transfer curve" -msgstr "" - -#: ../backend/canon.c:149 ../backend/canon-sane.c:1323 -#, no-c-format -msgid "Raw" -msgstr "" - -#: ../backend/canon.c:157 ../backend/canon-sane.c:732 -#: ../backend/canon-sane.c:940 ../backend/canon-sane.c:1076 -#: ../backend/canon-sane.c:1318 ../backend/canon-sane.c:1501 -#: ../backend/canon-sane.c:1650 -#, no-c-format -msgid "Fine color" -msgstr "" - -#: ../backend/canon.c:169 -#, no-c-format -msgid "No transparency correction" -msgstr "" - -#: ../backend/canon.c:170 ../backend/canon-sane.c:680 -#, no-c-format -msgid "Correction according to film type" -msgstr "" - -#: ../backend/canon.c:171 ../backend/canon-sane.c:674 -#, no-c-format -msgid "Correction according to transparency ratio" -msgstr "" - -#: ../backend/canon.c:176 ../backend/canon-sane.c:776 -#, no-c-format -msgid "Negatives" -msgstr "" - -#: ../backend/canon.c:176 -#, no-c-format -msgid "Slides" -msgstr "" - -#: ../backend/canon.c:186 ../backend/kvs1025_opt.c:181 -#: ../backend/kvs40xx_opt.c:272 ../backend/matsushita.c:178 -#, no-c-format -msgid "Automatic" -msgstr "" - -#: ../backend/canon.c:186 -#, no-c-format -msgid "Normal speed" -msgstr "" - -#: ../backend/canon.c:187 -#, no-c-format -msgid "1/2 normal speed" -msgstr "" - -#: ../backend/canon.c:187 -#, no-c-format -msgid "1/3 normal speed" -msgstr "" - -#: ../backend/canon.c:365 -#, no-c-format -msgid "rounded parameter" -msgstr "" - -#: ../backend/canon.c:368 ../backend/canon.c:384 ../backend/canon.c:419 -#: ../backend/canon.c:469 ../backend/canon.c:487 ../backend/canon.c:530 -#, no-c-format -msgid "unknown" -msgstr "" - -#: ../backend/canon.c:378 -#, no-c-format -msgid "ADF jam" -msgstr "" - -#: ../backend/canon.c:381 -#, no-c-format -msgid "ADF cover open" -msgstr "" - -#: ../backend/canon.c:394 -#, no-c-format -msgid "lamp failure" -msgstr "" - -#: ../backend/canon.c:397 -#, no-c-format -msgid "scan head positioning error" -msgstr "" - -#: ../backend/canon.c:400 -#, no-c-format -msgid "CPU check error" -msgstr "" - -#: ../backend/canon.c:403 -#, no-c-format -msgid "RAM check error" -msgstr "" - -#: ../backend/canon.c:406 -#, no-c-format -msgid "ROM check error" -msgstr "" - -#: ../backend/canon.c:409 -#, no-c-format -msgid "hardware check error" -msgstr "" - -#: ../backend/canon.c:412 -#, no-c-format -msgid "transparency unit lamp failure" -msgstr "" - -#: ../backend/canon.c:415 -#, no-c-format -msgid "transparency unit scan head positioning failure" -msgstr "" - -#: ../backend/canon.c:429 -#, no-c-format -msgid "parameter list length error" -msgstr "" - -#: ../backend/canon.c:433 -#, no-c-format -msgid "invalid command operation code" -msgstr "" - -#: ../backend/canon.c:437 -#, no-c-format -msgid "invalid field in CDB" -msgstr "" - -#: ../backend/canon.c:441 -#, no-c-format -msgid "unsupported LUN" -msgstr "" - -#: ../backend/canon.c:445 -#, no-c-format -msgid "invalid field in parameter list" -msgstr "" - -#: ../backend/canon.c:449 -#, no-c-format -msgid "command sequence error" -msgstr "" - -#: ../backend/canon.c:453 -#, no-c-format -msgid "too many windows specified" -msgstr "" - -#: ../backend/canon.c:457 -#, no-c-format -msgid "medium not present" -msgstr "" - -#: ../backend/canon.c:461 -#, no-c-format -msgid "invalid bit IDENTIFY message" -msgstr "" - -#: ../backend/canon.c:465 -#, no-c-format -msgid "option not connect" -msgstr "" - -#: ../backend/canon.c:479 -#, no-c-format -msgid "power on reset / bus device reset" -msgstr "" - -#: ../backend/canon.c:483 -#, no-c-format -msgid "parameter changed by another initiator" -msgstr "" - -#: ../backend/canon.c:497 -#, no-c-format -msgid "no additional sense information" -msgstr "" - -#: ../backend/canon.c:501 -#, no-c-format -msgid "reselect failure" -msgstr "" - -#: ../backend/canon.c:505 -#, no-c-format -msgid "SCSI parity error" -msgstr "" - -#: ../backend/canon.c:509 -#, no-c-format -msgid "initiator detected error message received" -msgstr "" - -#: ../backend/canon.c:514 -#, no-c-format -msgid "invalid message error" -msgstr "" - -#: ../backend/canon.c:518 -#, no-c-format -msgid "timeout error" -msgstr "" - -#: ../backend/canon.c:522 -#, no-c-format -msgid "transparency unit shading error" -msgstr "" - -#: ../backend/canon.c:526 -#, no-c-format -msgid "lamp not stabilized" -msgstr "" - -#: ../backend/canon.c:852 ../backend/canon.c:867 -#, no-c-format -msgid "film scanner" -msgstr "" - -#: ../backend/canon.c:882 ../backend/canon.c:897 ../backend/canon.c:912 -#: ../backend/canon.c:927 ../backend/hp3900_sane.c:1683 -#: ../backend/plustek.c:1335 ../backend/plustek_pp.c:1014 -#: ../backend/sceptre.c:593 ../backend/teco2.c:1836 ../backend/u12.c:851 -#, no-c-format -msgid "flatbed scanner" -msgstr "" - -#: ../backend/canon.c:1183 ../backend/epson.c:3372 ../backend/epson2.c:1355 -#, no-c-format -msgid "Film type" -msgstr "" - -#: ../backend/canon.c:1184 -#, no-c-format -msgid "Selects the film type, i.e. negatives or slides" -msgstr "" - -#: ../backend/canon.c:1196 -#, no-c-format -msgid "Negative film type" -msgstr "" - -#: ../backend/canon.c:1197 -#, no-c-format -msgid "Selects the negative film type" -msgstr "" - -#: ../backend/canon.c:1236 -#, no-c-format -msgid "Hardware resolution" -msgstr "" - -#: ../backend/canon.c:1237 -#, no-c-format -msgid "Use only hardware resolutions" -msgstr "" - -#: ../backend/canon.c:1318 -#, no-c-format -msgid "Focus" -msgstr "" - -#: ../backend/canon.c:1328 -#, no-c-format -msgid "Auto focus" -msgstr "" - -#: ../backend/canon.c:1329 -#, no-c-format -msgid "Enable/disable auto focus" -msgstr "" - -#: ../backend/canon.c:1336 -#, no-c-format -msgid "Auto focus only once" -msgstr "" - -#: ../backend/canon.c:1337 -#, no-c-format -msgid "Do auto focus only once between ejects" -msgstr "" - -#: ../backend/canon.c:1345 -#, no-c-format -msgid "Manual focus position" -msgstr "" - -#: ../backend/canon.c:1346 -#, no-c-format -msgid "Set the optical system's focus position by hand (default: 128)." -msgstr "" - -#: ../backend/canon.c:1356 -#, no-c-format -msgid "Scan margins" -msgstr "" - -#: ../backend/canon.c:1403 -#, no-c-format -msgid "Extra color adjustments" -msgstr "" - -#: ../backend/canon.c:1538 ../backend/epson.c:3191 ../backend/epson2.c:1245 -#: ../backend/kvs1025.h:55 ../backend/kvs40xx_opt.c:825 -#, no-c-format -msgid "Mirror image" -msgstr "" - -#: ../backend/canon.c:1539 -#, no-c-format -msgid "Mirror the image horizontally" -msgstr "" - -#: ../backend/canon.c:1608 -#, no-c-format -msgid "Auto exposure" -msgstr "" - -#: ../backend/canon.c:1609 -#, no-c-format -msgid "Enable/disable the auto exposure feature" -msgstr "" - -#: ../backend/canon.c:1625 -#, no-c-format -msgid "Calibration now" -msgstr "" - -#: ../backend/canon.c:1626 -#, no-c-format -msgid "Execute calibration *now*" -msgstr "" - -#: ../backend/canon.c:1636 -#, no-c-format -msgid "Self diagnosis" -msgstr "" - -#: ../backend/canon.c:1637 -#, no-c-format -msgid "Perform scanner self diagnosis" -msgstr "" - -#: ../backend/canon.c:1648 -#, no-c-format -msgid "Reset scanner" -msgstr "" - -#: ../backend/canon.c:1649 -#, no-c-format -msgid "Reset the scanner" -msgstr "" - -#: ../backend/canon.c:1659 -#, no-c-format -msgid "Medium handling" -msgstr "" - -#: ../backend/canon.c:1668 -#, no-c-format -msgid "Eject film after each scan" -msgstr "" - -#: ../backend/canon.c:1669 -#, no-c-format -msgid "Automatically eject the film from the device after each scan" -msgstr "" - -#: ../backend/canon.c:1680 -#, no-c-format -msgid "Eject film before exit" -msgstr "" - -#: ../backend/canon.c:1681 -#, no-c-format -msgid "Automatically eject the film from the device before exiting the program" -msgstr "" - -#: ../backend/canon.c:1690 -#, no-c-format -msgid "Eject film now" -msgstr "" - -#: ../backend/canon.c:1691 -#, no-c-format -msgid "Eject the film *now*" -msgstr "" - -#: ../backend/canon.c:1700 -#, no-c-format -msgid "Document feeder extras" -msgstr "" - -#: ../backend/canon.c:1707 -#, no-c-format -msgid "Flatbed only" -msgstr "" - -#: ../backend/canon.c:1708 -#, no-c-format -msgid "Disable auto document feeder and use flatbed only" -msgstr "" - -#: ../backend/canon.c:1718 ../backend/canon.c:1728 -#, no-c-format -msgid "Transparency unit" -msgstr "" - -#: ../backend/canon.c:1729 -#, no-c-format -msgid "Switch on/off the transparency unit (FAU, film adapter unit)" -msgstr "" - -#: ../backend/canon.c:1739 -#, no-c-format -msgid "Negative film" -msgstr "" - -#: ../backend/canon.c:1740 -#, no-c-format -msgid "Positive or negative film" -msgstr "" - -#: ../backend/canon.c:1749 -#, no-c-format -msgid "Density control" -msgstr "" - -#: ../backend/canon.c:1750 -#, no-c-format -msgid "Set density control mode" -msgstr "" - -#: ../backend/canon.c:1761 -#, no-c-format -msgid "Transparency ratio" -msgstr "" - -#: ../backend/canon.c:1775 -#, no-c-format -msgid "Select film type" -msgstr "" - -#: ../backend/canon.c:1776 -#, no-c-format -msgid "Select the film type" -msgstr "" - -#: ../backend/canon_dr.c:344 ../backend/epjitsu.c:203 ../backend/epson.c:501 -#: ../backend/epson2.c:114 ../backend/fujitsu.c:604 ../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:167 ../backend/mustek.c:156 -#: ../backend/mustek.c:160 ../backend/mustek.c:164 ../backend/pixma.c:891 -#: ../backend/pixma_sane_options.c:90 ../backend/snapscan-options.c:86 -#: ../backend/test.c:192 ../backend/umax.c:181 -#, no-c-format -msgid "Flatbed" -msgstr "" - -#: ../backend/canon_dr.c:345 ../backend/epjitsu.c:204 ../backend/fujitsu.c:605 -#: ../backend/kodak.c:135 -#, no-c-format -msgid "ADF Front" -msgstr "" - -#: ../backend/canon_dr.c:346 ../backend/epjitsu.c:205 ../backend/fujitsu.c:606 -#: ../backend/kodak.c:136 -#, no-c-format -msgid "ADF Back" -msgstr "" - -#: ../backend/canon_dr.c:347 ../backend/epjitsu.c:206 ../backend/fujitsu.c:607 -#: ../backend/hp5590.c:84 ../backend/kodak.c:137 ../backend/pixma.c:902 -#, no-c-format -msgid "ADF Duplex" -msgstr "" - -#: ../backend/canon_dr.c:354 ../backend/epson.c:599 ../backend/epson.c:3082 -#: ../backend/epson2.c:200 ../backend/fujitsu.c:624 ../backend/genesys.c:89 -#: ../backend/genesys.c:96 ../backend/gt68xx_low.h:136 -#: ../backend/hp-option.c:3093 -#, no-c-format -msgid "Red" -msgstr "" - -#: ../backend/canon_dr.c:355 ../backend/epson.c:600 ../backend/epson.c:3078 -#: ../backend/epson2.c:201 ../backend/fujitsu.c:625 ../backend/genesys.c:90 -#: ../backend/genesys.c:97 ../backend/gt68xx_low.h:137 -#: ../backend/hp-option.c:3094 -#, no-c-format -msgid "Green" -msgstr "" - -#: ../backend/canon_dr.c:356 ../backend/epson.c:601 ../backend/epson.c:3086 -#: ../backend/epson2.c:202 ../backend/fujitsu.c:626 ../backend/genesys.c:91 -#: ../backend/genesys.c:98 ../backend/gt68xx_low.h:138 -#: ../backend/hp-option.c:3095 -#, no-c-format -msgid "Blue" -msgstr "" - -#: ../backend/canon_dr.c:357 -#, no-c-format -msgid "Enhance Red" -msgstr "" - -#: ../backend/canon_dr.c:358 -#, no-c-format -msgid "Enhance Green" -msgstr "" - -#: ../backend/canon_dr.c:359 -#, no-c-format -msgid "Enhance Blue" -msgstr "" - -#: ../backend/canon_dr.c:361 ../backend/epson.c:556 ../backend/epson.c:564 -#: ../backend/epson.c:576 ../backend/epson.c:598 ../backend/epson2.c:164 -#: ../backend/epson2.c:172 ../backend/epson2.c:184 ../backend/epson2.c:199 -#: ../backend/epson2.c:213 ../backend/fujitsu.c:630 ../backend/genesys.c:99 -#: ../backend/leo.c:109 ../backend/matsushita.c:138 -#: ../backend/matsushita.c:159 ../backend/matsushita.c:191 -#: ../backend/matsushita.c:213 ../backend/snapscan-options.c:91 -#, no-c-format -msgid "None" -msgstr "" - -#: ../backend/canon_dr.c:362 ../backend/fujitsu.c:631 -#, no-c-format -msgid "JPEG" -msgstr "" - -#: ../backend/epson.c:491 ../backend/epson2.c:107 ../backend/magicolor.c:160 -#, no-c-format -msgid "Simplex" -msgstr "" - -#: ../backend/epson.c:492 ../backend/epson2.c:108 ../backend/kvs1025.h:50 -#: ../backend/kvs20xx_opt.c:203 ../backend/kvs40xx_opt.c:352 -#: ../backend/magicolor.c:161 ../backend/matsushita.h:218 -#, no-c-format -msgid "Duplex" -msgstr "" - -#: ../backend/epson.c:502 ../backend/epson2.c:115 ../backend/pixma.c:908 -#, no-c-format -msgid "Transparency Unit" -msgstr "" - -#: ../backend/epson.c:503 ../backend/epson2.c:117 ../backend/magicolor.c:168 -#: ../backend/mustek.c:160 ../backend/pixma.c:896 ../backend/test.c:192 -#: ../backend/umax.c:183 -#, no-c-format -msgid "Automatic Document Feeder" -msgstr "" - -#: ../backend/epson.c:523 ../backend/epson2.c:133 -#, no-c-format -msgid "Positive Film" -msgstr "" - -#: ../backend/epson.c:524 ../backend/epson2.c:134 -#, no-c-format -msgid "Negative Film" -msgstr "" - -#: ../backend/epson.c:529 ../backend/epson2.c:141 -#, no-c-format -msgid "Focus on glass" -msgstr "" - -#: ../backend/epson.c:530 ../backend/epson2.c:142 -#, no-c-format -msgid "Focus 2.5mm above glass" -msgstr "" - -#: ../backend/epson.c:557 ../backend/epson.c:565 ../backend/epson.c:577 -#: ../backend/epson2.c:165 ../backend/epson2.c:173 ../backend/epson2.c:185 -#, no-c-format -msgid "Halftone A (Hard Tone)" -msgstr "" - -#: ../backend/epson.c:558 ../backend/epson.c:566 ../backend/epson.c:578 -#: ../backend/epson2.c:166 ../backend/epson2.c:174 ../backend/epson2.c:186 -#, no-c-format -msgid "Halftone B (Soft Tone)" -msgstr "" - -#: ../backend/epson.c:559 ../backend/epson.c:567 ../backend/epson.c:579 -#: ../backend/epson2.c:167 ../backend/epson2.c:175 ../backend/epson2.c:187 -#, no-c-format -msgid "Halftone C (Net Screen)" -msgstr "" - -#: ../backend/epson.c:568 ../backend/epson.c:580 ../backend/epson2.c:176 -#: ../backend/epson2.c:188 -#, no-c-format -msgid "Dither A (4x4 Bayer)" -msgstr "" - -#: ../backend/epson.c:569 ../backend/epson.c:581 ../backend/epson2.c:177 -#: ../backend/epson2.c:189 -#, no-c-format -msgid "Dither B (4x4 Spiral)" -msgstr "" - -#: ../backend/epson.c:570 ../backend/epson.c:582 ../backend/epson2.c:178 -#: ../backend/epson2.c:190 -#, no-c-format -msgid "Dither C (4x4 Net Screen)" -msgstr "" - -#: ../backend/epson.c:571 ../backend/epson.c:583 ../backend/epson2.c:179 -#: ../backend/epson2.c:191 -#, no-c-format -msgid "Dither D (8x4 Net Screen)" -msgstr "" - -#: ../backend/epson.c:584 ../backend/epson2.c:192 -#, no-c-format -msgid "Text Enhanced Technology" -msgstr "" - -#: ../backend/epson.c:585 ../backend/epson2.c:193 -#, no-c-format -msgid "Download pattern A" -msgstr "" - -#: ../backend/epson.c:586 ../backend/epson2.c:194 -#, no-c-format -msgid "Download pattern B" -msgstr "" - -#: ../backend/epson.c:631 -#, no-c-format -msgid "No Correction" -msgstr "" - -#: ../backend/epson.c:632 ../backend/epson.c:657 ../backend/epson2.c:254 -#, no-c-format -msgid "User defined" -msgstr "" - -#: ../backend/epson.c:633 -#, no-c-format -msgid "Impact-dot printers" -msgstr "" - -#: ../backend/epson.c:634 -#, no-c-format -msgid "Thermal printers" -msgstr "" - -#: ../backend/epson.c:635 -#, no-c-format -msgid "Ink-jet printers" -msgstr "" - -#: ../backend/epson.c:636 -#, no-c-format -msgid "CRT monitors" -msgstr "" - -#: ../backend/epson.c:656 ../backend/epson2.c:253 ../backend/fujitsu.c:614 -#: ../backend/hp-option.c:3226 ../backend/test.c:143 -#, no-c-format -msgid "Default" -msgstr "" - -#: ../backend/epson.c:658 ../backend/epson2.c:255 -#, no-c-format -msgid "High density printing" -msgstr "" - -#: ../backend/epson.c:659 ../backend/epson2.c:256 -#, no-c-format -msgid "Low density printing" -msgstr "" - -#: ../backend/epson.c:660 ../backend/epson2.c:257 -#, no-c-format -msgid "High contrast printing" -msgstr "" - -#: ../backend/epson.c:678 ../backend/epson2.c:275 -#, no-c-format -msgid "User defined (Gamma=1.0)" -msgstr "" - -#: ../backend/epson.c:679 ../backend/epson2.c:276 -#, no-c-format -msgid "User defined (Gamma=1.8)" -msgstr "" - -#: ../backend/epson.c:757 -#, no-c-format -msgid "CD" -msgstr "" - -#: ../backend/epson.c:758 -#, no-c-format -msgid "A5 portrait" -msgstr "" - -#: ../backend/epson.c:759 -#, no-c-format -msgid "A5 landscape" -msgstr "" - -#: ../backend/epson.c:760 ../backend/kvs1025_opt.c:103 -#: ../backend/kvs20xx_opt.c:76 ../backend/kvs40xx_opt.c:130 -#: ../backend/kvs40xx_opt.c:147 -#, no-c-format -msgid "Letter" -msgstr "" - -#: ../backend/epson.c:761 ../backend/kvs1025_opt.c:100 -#: ../backend/kvs20xx_opt.c:73 ../backend/kvs20xx_opt.c:301 -#: ../backend/kvs40xx_opt.c:127 ../backend/kvs40xx_opt.c:144 -#: ../backend/kvs40xx_opt.c:525 -#, no-c-format -msgid "A4" -msgstr "" - -#: ../backend/epson.c:762 -#, no-c-format -msgid "Max" -msgstr "" - -#: ../backend/epson.c:2799 ../backend/epson2.c:966 ../backend/genesys.c:5389 -#: ../backend/gt68xx.c:458 ../backend/hp-option.c:2914 -#: ../backend/kvs1025_opt.c:522 ../backend/kvs20xx_opt.c:170 -#: ../backend/kvs40xx_opt.c:319 ../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:721 ../backend/plustek_pp.c:658 -#: ../backend/sceptre.c:673 ../backend/snapscan-options.c:354 -#: ../backend/stv680.c:1030 ../backend/teco2.c:1886 ../backend/test.c:306 -#: ../backend/u12.c:473 ../backend/umax.c:5054 -#, no-c-format -msgid "Scan Mode" -msgstr "" - -#: ../backend/epson.c:2831 ../backend/epson2.c:1002 -#, no-c-format -msgid "Selects the halftone." -msgstr "" - -#: ../backend/epson.c:2853 ../backend/epson2.c:1023 -#, no-c-format -msgid "Dropout" -msgstr "" - -#: ../backend/epson.c:2854 ../backend/epson2.c:1024 -#, no-c-format -msgid "Selects the dropout." -msgstr "" - -#: ../backend/epson.c:2866 ../backend/epson2.c:1036 -#, no-c-format -msgid "Selects the brightness." -msgstr "" - -#: ../backend/epson.c:2881 ../backend/epson2.c:1049 -#, no-c-format -msgid "Sharpness" -msgstr "" - -#: ../backend/epson.c:3017 ../backend/epson2.c:1165 ../backend/epson2.c:1212 -#, no-c-format -msgid "Color correction" -msgstr "" - -#: ../backend/epson.c:3020 ../backend/epson2.c:1167 -#, 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 -#, no-c-format -msgid "Controls blue level" -msgstr "" - -#: ../backend/epson.c:3192 ../backend/epson2.c:1246 -#, no-c-format -msgid "Mirror the image." -msgstr "" - -#: ../backend/epson.c:3218 ../backend/mustek.c:4334 -#, no-c-format -msgid "Fast preview" -msgstr "" - -#: ../backend/epson.c:3231 ../backend/epson2.c:1256 -#, 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 "" - -#: ../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:1331 -#, no-c-format -msgid "Optional equipment" -msgstr "" - -#: ../backend/epson.c:3417 ../backend/epson2.c:1384 -#, no-c-format -msgid "Eject" -msgstr "" - -#: ../backend/epson.c:3418 ../backend/epson2.c:1385 -#, no-c-format -msgid "Eject the sheet in the ADF" -msgstr "" - -#: ../backend/epson.c:3430 ../backend/epson2.c:1395 -#, no-c-format -msgid "Auto eject" -msgstr "" - -#: ../backend/epson.c:3431 ../backend/epson2.c:1397 -#, no-c-format -msgid "Eject document after scanning" -msgstr "" - -#: ../backend/epson.c:3443 ../backend/epson2.c:1407 -#: ../backend/magicolor.c:2399 -#, no-c-format -msgid "ADF Mode" -msgstr "" - -#: ../backend/epson.c:3445 ../backend/epson2.c:1409 -#: ../backend/magicolor.c:2401 -#, no-c-format -msgid "Selects the ADF mode (simplex/duplex)" -msgstr "" - -#: ../backend/epson.c:3459 ../backend/epson2.c:1421 -#, no-c-format -msgid "Bay" -msgstr "" - -#: ../backend/epson.c:3460 ../backend/epson2.c:1422 -#, no-c-format -msgid "Select bay to scan" -msgstr "" - -#: ../backend/epson.h:69 ../backend/epson2.h:75 -#, 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:78 -#, no-c-format -msgid "Focus Position" -msgstr "" - -#: ../backend/epson.h:73 ../backend/epson2.h:79 -#, 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:81 -#, no-c-format -msgid "Wait for Button" -msgstr "" - -#: ../backend/epson.h:76 ../backend/epson2.h:82 -#, 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:101 ../backend/pixma.c:390 -#, no-c-format -msgid "Infrared" -msgstr "" - -#: ../backend/epson2.c:116 -#, no-c-format -msgid "TPU8x10" -msgstr "" - -#: ../backend/epson2.c:135 -#, no-c-format -msgid "Positive Slide" -msgstr "" - -#: ../backend/epson2.c:136 -#, no-c-format -msgid "Negative Slide" -msgstr "" - -#: ../backend/epson2.c:214 -#, no-c-format -msgid "Built in CCT profile" -msgstr "" - -#: ../backend/epson2.c:215 -#, no-c-format -msgid "User defined CCT profile" -msgstr "" - -#: ../backend/fujitsu.c:615 ../backend/hp-option.c:3327 -#: ../backend/hp-option.c:3340 -#, no-c-format -msgid "On" -msgstr "" - -#: ../backend/fujitsu.c:616 ../backend/hp-option.c:3159 -#: ../backend/hp-option.c:3326 ../backend/hp-option.c:3339 -#, no-c-format -msgid "Off" -msgstr "" - -#: ../backend/fujitsu.c:618 -#, no-c-format -msgid "DTC" -msgstr "" - -#: ../backend/fujitsu.c:619 -#, no-c-format -msgid "SDTC" -msgstr "" - -#: ../backend/fujitsu.c:621 ../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:622 -#, no-c-format -msgid "Diffusion" -msgstr "" - -#: ../backend/fujitsu.c:627 -#, no-c-format -msgid "White" -msgstr "" - -#: ../backend/fujitsu.c:628 -#, no-c-format -msgid "Black" -msgstr "" - -#: ../backend/fujitsu.c:633 -#, no-c-format -msgid "Continue" -msgstr "" - -#: ../backend/fujitsu.c:634 -#, no-c-format -msgid "Stop" -msgstr "" - -#: ../backend/fujitsu.c:636 -#, no-c-format -msgid "10mm" -msgstr "" - -#: ../backend/fujitsu.c:637 -#, no-c-format -msgid "15mm" -msgstr "" - -#: ../backend/fujitsu.c:638 -#, no-c-format -msgid "20mm" -msgstr "" - -#: ../backend/fujitsu.c:640 ../backend/hp-option.c:3045 -#, no-c-format -msgid "Horizontal" -msgstr "" - -#: ../backend/fujitsu.c:641 -#, no-c-format -msgid "Horizontal bold" -msgstr "" - -#: ../backend/fujitsu.c:642 -#, no-c-format -msgid "Horizontal narrow" -msgstr "" - -#: ../backend/fujitsu.c:643 ../backend/hp-option.c:3044 -#, no-c-format -msgid "Vertical" -msgstr "" - -#: ../backend/fujitsu.c:644 -#, no-c-format -msgid "Vertical bold" -msgstr "" - -#: ../backend/fujitsu.c:646 -#, no-c-format -msgid "Top to bottom" -msgstr "" - -#: ../backend/fujitsu.c:647 -#, no-c-format -msgid "Bottom to top" -msgstr "" - -#: ../backend/fujitsu.c:649 -#, no-c-format -msgid "Front" -msgstr "" - -#: ../backend/fujitsu.c:650 -#, no-c-format -msgid "Back" -msgstr "" - -#: ../backend/fujitsu.c:3858 ../backend/genesys.c:5623 -#: ../backend/kvs1025_opt.c:911 -#, no-c-format -msgid "Software blank skip percentage" -msgstr "" - -#: ../backend/fujitsu.c:3859 -#, no-c-format -msgid "Request driver to discard pages with low percentage of dark pixels" -msgstr "" - -#: ../backend/genesys.c:5614 -#, no-c-format -msgid "Software crop" -msgstr "" - -#: ../backend/genesys.c:5615 -#, no-c-format -msgid "Request backend to remove border from pages digitally" -msgstr "" - -#: ../backend/genesys.c:5624 ../backend/kvs1025_opt.c:913 -#, no-c-format -msgid "Request driver to discard pages with low numbers of dark pixels" -msgstr "" - -#: ../backend/genesys.c:5635 ../backend/kvs1025_opt.c:893 -#, no-c-format -msgid "Software derotate" -msgstr "" - -#: ../backend/genesys.c:5636 ../backend/kvs1025_opt.c:895 -#, no-c-format -msgid "Request driver to detect and correct 90 degree image rotation" -msgstr "" - -#: ../backend/genesys.c:5667 ../backend/pixma_sane_options.c:312 -#, no-c-format -msgid "Extras" -msgstr "" - -#: ../backend/genesys.c:5686 ../backend/pixma_sane_options.c:333 -#, no-c-format -msgid "Threshold curve" -msgstr "" - -#: ../backend/genesys.c:5687 ../backend/pixma_sane_options.c:334 -#, no-c-format -msgid "Dynamic threshold curve, from light to dark, normally 50-65" -msgstr "" - -#: ../backend/genesys.c:5696 -#, no-c-format -msgid "Disable dynamic lineart" -msgstr "" - -#: ../backend/genesys.c:5698 -#, no-c-format -msgid "" -"Disable use of a software adaptive algorithm to generate lineart relying " -"instead on hardware lineart." -msgstr "" - -#: ../backend/genesys.c:5714 -#, no-c-format -msgid "Disable interpolation" -msgstr "" - -#: ../backend/genesys.c:5717 -#, 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:5726 -#, no-c-format -msgid "Color filter" -msgstr "" - -#: ../backend/genesys.c:5729 -#, no-c-format -msgid "When using gray or lineart this option selects the used color." -msgstr "" - -#: ../backend/genesys.c:5755 -#, no-c-format -msgid "Calibration file" -msgstr "" - -#: ../backend/genesys.c:5756 -#, no-c-format -msgid "Specify the calibration file to use" -msgstr "" - -#: ../backend/genesys.c:5773 -#, no-c-format -msgid "Lamp off time" -msgstr "" - -#: ../backend/genesys.c:5776 -#, 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:5786 -#, no-c-format -msgid "Lamp off during scan" -msgstr "" - -#: ../backend/genesys.c:5787 -#, no-c-format -msgid "The lamp will be turned off during scan. " -msgstr "" - -#: ../backend/genesys.c:5815 ../backend/genesys.c:5816 -#, no-c-format -msgid "File button" -msgstr "" - -#: ../backend/genesys.c:5868 ../backend/genesys.c:5869 -#, no-c-format -msgid "OCR button" -msgstr "" - -#: ../backend/genesys.c:5882 ../backend/genesys.c:5883 -#, no-c-format -msgid "Power button" -msgstr "" - -#: ../backend/genesys.c:5896 ../backend/genesys.c:5897 -#, no-c-format -msgid "Extra button" -msgstr "" - -#: ../backend/genesys.c:5910 ../backend/gt68xx.c:762 -#, no-c-format -msgid "Need calibration" -msgstr "" - -#: ../backend/genesys.c:5911 ../backend/gt68xx.c:763 -#, no-c-format -msgid "The scanner needs calibration for the current settings" -msgstr "" - -#: ../backend/genesys.c:5923 ../backend/gt68xx.c:787 ../backend/gt68xx.c:788 -#: ../backend/pixma_sane_options.c:224 ../backend/plustek.c:1080 -#, no-c-format -msgid "Buttons" -msgstr "" - -#: ../backend/genesys.c:5932 ../backend/gt68xx.c:794 -#: ../backend/hp5400_sane.c:392 ../backend/hp-option.h:97 -#: ../backend/niash.c:728 ../backend/plustek.c:941 -#, no-c-format -msgid "Calibrate" -msgstr "" - -#: ../backend/genesys.c:5934 ../backend/gt68xx.c:796 -#, no-c-format -msgid "Start calibration using special sheet" -msgstr "" - -#: ../backend/genesys.c:5948 ../backend/gt68xx.c:809 -#, no-c-format -msgid "Clear calibration" -msgstr "" - -#: ../backend/genesys.c:5949 ../backend/gt68xx.c:810 -#, no-c-format -msgid "Clear calibration cache" -msgstr "" - -#: ../backend/gt68xx.c:149 ../backend/ma1509.c:108 ../backend/mustek.c:164 -#: ../backend/snapscan-options.c:87 ../backend/umax.c:182 -#, no-c-format -msgid "Transparency Adapter" -msgstr "" - -#: ../backend/gt68xx.c:477 -#, no-c-format -msgid "Gray mode color" -msgstr "" - -#: ../backend/gt68xx.c:479 -#, no-c-format -msgid "Selects which scan color is used gray mode (default: green)." -msgstr "" - -#: ../backend/gt68xx.c:560 ../backend/hp3900_sane.c:1392 -#: ../backend/mustek_usb2.c:410 -#, no-c-format -msgid "Debugging Options" -msgstr "" - -#: ../backend/gt68xx.c:571 ../backend/mustek_usb2.c:419 -#, no-c-format -msgid "Automatic warmup" -msgstr "" - -#: ../backend/gt68xx.c:573 -#, no-c-format -msgid "" -"Warm-up until the lamp's brightness is constant instead of insisting on 60 " -"seconds warm-up time." -msgstr "" - -#: ../backend/gt68xx.c:585 -#, no-c-format -msgid "Full scan" -msgstr "" - -#: ../backend/gt68xx.c:587 -#, no-c-format -msgid "" -"Scan the complete scanning area including calibration strip. Be careful. " -"Don't select the full height. For testing only." -msgstr "" - -#: ../backend/gt68xx.c:598 -#, no-c-format -msgid "Coarse calibration" -msgstr "" - -#: ../backend/gt68xx.c:600 -#, no-c-format -msgid "" -"Setup gain and offset for scanning automatically. If this option is " -"disabled, options for setting the analog frontend parameters manually are " -"provided. This option is enabled by default. For testing only." -msgstr "" - -#: ../backend/gt68xx.c:619 -#, no-c-format -msgid "Coarse calibration for first scan only" -msgstr "" - -#: ../backend/gt68xx.c:621 -#, no-c-format -msgid "" -"Coarse calibration is only done for the first scan. Works with most scanners " -"and can save scanning time. If the image brightness is different with each " -"scan, disable this option. For testing only." -msgstr "" - -#: ../backend/gt68xx.c:654 -#, no-c-format -msgid "Backtrack lines" -msgstr "" - -#: ../backend/gt68xx.c:656 -#, no-c-format -msgid "" -"Number of lines the scan slider moves back when backtracking occurs. That " -"happens when the scanner scans faster than the computer can receive the " -"data. Low values cause faster scans but increase the risk of omitting lines." -msgstr "" - -#: ../backend/gt68xx.c:681 ../backend/mustek_usb2.c:452 -#, no-c-format -msgid "Gamma value" -msgstr "" - -#: ../backend/gt68xx.c:683 ../backend/mustek_usb2.c:454 -#, no-c-format -msgid "Sets the gamma value of all channels." -msgstr "" - -#: ../backend/hp3500.c:1004 -#, no-c-format -msgid "Geometry Group" -msgstr "" - -#: ../backend/hp3500.c:1057 ../backend/hp3500.c:1058 -#, no-c-format -msgid "Scan Mode Group" -msgstr "" - -#: ../backend/hp3900_sane.c:427 ../backend/hp3900_sane.c:1019 -#: ../backend/hp-option.c:3174 -#, no-c-format -msgid "Slide" -msgstr "" - -#: ../backend/hp3900_sane.c:1405 -#, no-c-format -msgid "Scanner model" -msgstr "" - -#: ../backend/hp3900_sane.c:1408 -#, no-c-format -msgid "Allows to test device behaviour with other supported models" -msgstr "" - -#: ../backend/hp3900_sane.c:1422 -#, no-c-format -msgid "Image colours will be inverted" -msgstr "" - -#: ../backend/hp3900_sane.c:1436 -#, no-c-format -msgid "Disable gamma correction" -msgstr "" - -#: ../backend/hp3900_sane.c:1437 -#, no-c-format -msgid "Gamma correction will be disabled" -msgstr "" - -#: ../backend/hp3900_sane.c:1451 -#, no-c-format -msgid "Disable white shading correction" -msgstr "" - -#: ../backend/hp3900_sane.c:1453 -#, no-c-format -msgid "White shading correction will be disabled" -msgstr "" - -#: ../backend/hp3900_sane.c:1467 -#, no-c-format -msgid "Skip warmup process" -msgstr "" - -#: ../backend/hp3900_sane.c:1468 -#, no-c-format -msgid "Warmup process will be disabled" -msgstr "" - -#: ../backend/hp3900_sane.c:1482 -#, no-c-format -msgid "Force real depth" -msgstr "" - -#: ../backend/hp3900_sane.c:1485 -#, no-c-format -msgid "" -"If gamma is enabled, scans are always made in 16 bits depth to improve image " -"quality and then converted to the selected depth. This option avoids depth " -"emulation." -msgstr "" - -#: ../backend/hp3900_sane.c:1499 -#, no-c-format -msgid "Emulate Grayscale" -msgstr "" - -#: ../backend/hp3900_sane.c:1502 -#, no-c-format -msgid "" -"If enabled, image will be scanned in color mode and then converted to " -"grayscale by software. This may improve image quality in some circumstances." -msgstr "" - -#: ../backend/hp3900_sane.c:1516 -#, no-c-format -msgid "Save debugging images" -msgstr "" - -#: ../backend/hp3900_sane.c:1519 -#, no-c-format -msgid "" -"If enabled, some images involved in scanner processing are saved to analyze " -"them." -msgstr "" - -#: ../backend/hp3900_sane.c:1533 -#, no-c-format -msgid "Reset chipset" -msgstr "" - -#: ../backend/hp3900_sane.c:1534 -#, no-c-format -msgid "Resets chipset data" -msgstr "" - -#: ../backend/hp3900_sane.c:1547 -#, no-c-format -msgid "Information" -msgstr "" - -#: ../backend/hp3900_sane.c:1560 -#, no-c-format -msgid "Chipset name" -msgstr "" - -#: ../backend/hp3900_sane.c:1561 -#, no-c-format -msgid "Shows chipset name used in device." -msgstr "" - -#: ../backend/hp3900_sane.c:1565 -#, no-c-format -msgid "Unknown" -msgstr "" - -#: ../backend/hp3900_sane.c:1571 -#, no-c-format -msgid "Chipset ID" -msgstr "" - -#: ../backend/hp3900_sane.c:1572 -#, no-c-format -msgid "Shows the chipset ID" -msgstr "" - -#: ../backend/hp3900_sane.c:1582 -#, no-c-format -msgid "Scan counter" -msgstr "" - -#: ../backend/hp3900_sane.c:1584 -#, no-c-format -msgid "Shows the number of scans made by scanner" -msgstr "" - -#: ../backend/hp3900_sane.c:1594 -#, no-c-format -msgid "Update information" -msgstr "" - -#: ../backend/hp3900_sane.c:1595 -#, no-c-format -msgid "Updates information about device" -msgstr "" - -#: ../backend/hp3900_sane.c:1635 -#, no-c-format -msgid "This option reflects a front panel scanner button" -msgstr "" - -#: ../backend/hp5400_sane.c:313 ../backend/niash.c:683 -#, no-c-format -msgid "Image" -msgstr "" - -#: ../backend/hp5400_sane.c:352 ../backend/niash.c:711 -#, no-c-format -msgid "Miscellaneous" -msgstr "" - -#: ../backend/hp5400_sane.c:358 -#, no-c-format -msgid "offset X" -msgstr "" - -#: ../backend/hp5400_sane.c:359 -#, no-c-format -msgid "Hardware internal X position of the scanning area." -msgstr "" - -#: ../backend/hp5400_sane.c:368 -#, no-c-format -msgid "offset Y" -msgstr "" - -#: ../backend/hp5400_sane.c:369 -#, no-c-format -msgid "Hardware internal Y position of the scanning area." -msgstr "" - -#: ../backend/hp5400_sane.c:381 ../backend/niash.c: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 "" - -#: ../backend/hp5590.c:85 -#, no-c-format -msgid "TMA Slides" -msgstr "" - -#: ../backend/hp5590.c:86 -#, no-c-format -msgid "TMA Negatives" -msgstr "" - -#: ../backend/hp5590.c:89 -#, no-c-format -msgid "Color (48 bits)" -msgstr "" - -#: ../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 -#, no-c-format -msgid "Advanced Options" -msgstr "" - -#: ../backend/hp-option.c:3041 -#, no-c-format -msgid "Coarse" -msgstr "" - -#: ../backend/hp-option.c:3042 -#, no-c-format -msgid "Fine" -msgstr "" - -#: ../backend/hp-option.c:3043 -#, no-c-format -msgid "Bayer" -msgstr "" - -#: ../backend/hp-option.c:3046 ../backend/hp-option.c:3097 -#, no-c-format -msgid "Custom" -msgstr "" - -#: ../backend/hp-option.c:3087 ../backend/hp-option.c:3143 -#: ../backend/hp-option.c:3158 -#, no-c-format -msgid "Auto" -msgstr "" - -#: ../backend/hp-option.c:3088 -#, no-c-format -msgid "NTSC RGB" -msgstr "" - -#: ../backend/hp-option.c:3089 -#, no-c-format -msgid "XPA RGB" -msgstr "" - -#: ../backend/hp-option.c:3090 -#, no-c-format -msgid "Pass-through" -msgstr "" - -#: ../backend/hp-option.c:3091 -#, no-c-format -msgid "NTSC Gray" -msgstr "" - -#: ../backend/hp-option.c:3092 -#, no-c-format -msgid "XPA Gray" -msgstr "" - -#: ../backend/hp-option.c:3144 -#, no-c-format -msgid "Slow" -msgstr "" - -#: ../backend/hp-option.c:3145 ../backend/hp-option.c:3252 -#: ../backend/kvs40xx_opt.c:229 ../backend/matsushita.c:244 -#: ../backend/mustek.c:149 ../backend/plustek.c:234 -#: ../backend/plustek_pp.c:203 ../backend/u12.c:155 -#, no-c-format -msgid "Normal" -msgstr "" - -#: ../backend/hp-option.c:3146 -#, no-c-format -msgid "Fast" -msgstr "" - -#: ../backend/hp-option.c:3147 -#, no-c-format -msgid "Extra Fast" -msgstr "" - -#: ../backend/hp-option.c:3160 -#, no-c-format -msgid "2-pixel" -msgstr "" - -#: ../backend/hp-option.c:3161 -#, no-c-format -msgid "4-pixel" -msgstr "" - -#: ../backend/hp-option.c:3162 -#, no-c-format -msgid "8-pixel" -msgstr "" - -#: ../backend/hp-option.c:3173 -#, no-c-format -msgid "Print" -msgstr "" - -#: ../backend/hp-option.c:3175 -#, no-c-format -msgid "Film-strip" -msgstr "" - -#: ../backend/hp-option.c:3254 -#, no-c-format -msgid "XPA" -msgstr "" - -#: ../backend/hp-option.c:3328 ../backend/hp-option.c:3341 -#, no-c-format -msgid "Conditional" -msgstr "" - -#: ../backend/hp-option.c:3414 -#, no-c-format -msgid "Experiment" -msgstr "" - -#: ../backend/hp-option.h:60 -#, no-c-format -msgid "Sharpening" -msgstr "" - -#: ../backend/hp-option.h:61 -#, no-c-format -msgid "Set sharpening value." -msgstr "" - -#: ../backend/hp-option.h:66 -#, no-c-format -msgid "Auto Threshold" -msgstr "" - -#: ../backend/hp-option.h:68 -#, no-c-format -msgid "Enable automatic determination of threshold for line-art scans." -msgstr "" - -#: ../backend/hp-option.h: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 "" - -#: ../backend/hp-option.h:103 -#, no-c-format -msgid "Media" -msgstr "" - -#: ../backend/hp-option.h:104 -#, no-c-format -msgid "Set type of media." -msgstr "" - -#: ../backend/hp-option.h:109 -#, no-c-format -msgid "Exposure time" -msgstr "" - -#: ../backend/hp-option.h:111 -#, no-c-format -msgid "" -"A longer exposure time lets the scanner collect more light. Suggested use is " -"175% for prints, 150% for normal slides and \"Negative\" for negative film. " -"For dark (underexposed) images you can increase this value." -msgstr "" - -#: ../backend/hp-option.h:119 ../backend/hp-option.h:126 -#, no-c-format -msgid "Color Matrix" -msgstr "" - -#: ../backend/hp-option.h:121 -#, no-c-format -msgid "Set the scanners color matrix." -msgstr "" - -#: ../backend/hp-option.h:127 -#, no-c-format -msgid "Custom color matrix." -msgstr "" - -#: ../backend/hp-option.h:132 -#, no-c-format -msgid "Mono Color Matrix" -msgstr "" - -#: ../backend/hp-option.h:133 -#, no-c-format -msgid "Custom color matrix for grayscale scans." -msgstr "" - -#: ../backend/hp-option.h:138 -#, no-c-format -msgid "Mirror horizontal" -msgstr "" - -#: ../backend/hp-option.h:139 -#, no-c-format -msgid "Mirror image horizontally." -msgstr "" - -#: ../backend/hp-option.h:144 -#, no-c-format -msgid "Mirror vertical" -msgstr "" - -#: ../backend/hp-option.h:145 -#, no-c-format -msgid "Mirror image vertically." -msgstr "" - -#: ../backend/hp-option.h:150 -#, no-c-format -msgid "Update options" -msgstr "" - -#: ../backend/hp-option.h:151 -#, no-c-format -msgid "Update options." -msgstr "" - -#: ../backend/hp-option.h:156 -#, no-c-format -msgid "8 bit output" -msgstr "" - -#: ../backend/hp-option.h:158 -#, no-c-format -msgid "Use bit depth greater eight internally, but output only eight bits." -msgstr "" - -#: ../backend/hp-option.h:164 -#, no-c-format -msgid "Front button wait" -msgstr "" - -#: ../backend/hp-option.h:165 -#, no-c-format -msgid "Wait to scan for front-panel button push." -msgstr "" - -#: ../backend/hp-option.h:172 -#, no-c-format -msgid "Shut off lamp" -msgstr "" - -#: ../backend/hp-option.h:173 -#, no-c-format -msgid "Shut off scanner lamp." -msgstr "" - -#: ../backend/kvs1025.h:51 ../backend/kvs20xx_opt.c:294 -#: ../backend/kvs40xx_opt.c:515 ../backend/matsushita.h:219 -#, no-c-format -msgid "Paper size" -msgstr "" - -#: ../backend/kvs1025.h:52 ../backend/kvs1025.h:67 ../backend/matsushita.h:220 -#: ../backend/matsushita.h:227 -#, no-c-format -msgid "Automatic separation" -msgstr "" - -#: ../backend/kvs1025.h:53 ../backend/kvs20xx_opt.c:306 -#: ../backend/kvs40xx_opt.c:530 -#, no-c-format -msgid "Landscape" -msgstr "" - -#: ../backend/kvs1025.h:54 ../backend/kvs40xx_opt.c:692 -#, no-c-format -msgid "Inverse Image" -msgstr "" - -#: ../backend/kvs1025.h:56 ../backend/kvs40xx_opt.c:403 -#, no-c-format -msgid "Long paper mode" -msgstr "" - -#: ../backend/kvs1025.h:57 ../backend/kvs20xx_opt.c:229 -#: ../backend/kvs40xx_opt.c:392 -#, no-c-format -msgid "Length control mode" -msgstr "" - -#: ../backend/kvs1025.h:58 ../backend/kvs20xx_opt.c:241 -#: ../backend/kvs40xx_opt.c:415 -#, no-c-format -msgid "Manual feed mode" -msgstr "" - -#: ../backend/kvs1025.h:59 ../backend/kvs20xx_opt.c:253 -#: ../backend/kvs40xx_opt.c:427 -#, no-c-format -msgid "Manual feed timeout" -msgstr "" - -#: ../backend/kvs1025.h:60 ../backend/kvs20xx_opt.c:266 -#: ../backend/kvs40xx_opt.c:440 -#, no-c-format -msgid "Double feed detection" -msgstr "" - -#: ../backend/kvs1025.h:63 ../backend/kvs20xx_opt.c:204 -#: ../backend/kvs40xx_opt.c:353 ../backend/matsushita.h:223 -#, no-c-format -msgid "Enable Duplex (Dual-Sided) Scanning" -msgstr "" - -#: ../backend/kvs1025.h:65 ../backend/kvs20xx_opt.c:295 -#: ../backend/kvs40xx_opt.c:516 ../backend/matsushita.h:225 -#, no-c-format -msgid "Physical size of the paper in the ADF" -msgstr "" - -#: ../backend/kvs1025_opt.c:39 -#, no-c-format -msgid "bw" -msgstr "" - -#: ../backend/kvs1025_opt.c:40 -#, no-c-format -msgid "halftone" -msgstr "" - -#: ../backend/kvs1025_opt.c:41 -#, no-c-format -msgid "gray" -msgstr "" - -#: ../backend/kvs1025_opt.c:42 -#, no-c-format -msgid "color" -msgstr "" - -#: ../backend/kvs1025_opt.c:61 ../backend/kvs40xx_opt.c:107 -#: ../backend/kvs40xx_opt.c:1046 -#, no-c-format -msgid "adf" -msgstr "" - -#: ../backend/kvs1025_opt.c:62 ../backend/kvs40xx_opt.c:49 -#: ../backend/kvs40xx_opt.c:108 -#, no-c-format -msgid "fb" -msgstr "" - -#: ../backend/kvs1025_opt.c:72 ../backend/kvs20xx_opt.c:54 -#: ../backend/kvs40xx_opt.c:100 -#, no-c-format -msgid "single" -msgstr "" - -#: ../backend/kvs1025_opt.c:73 ../backend/kvs20xx.c:455 -#: ../backend/kvs20xx_opt.c:55 ../backend/kvs40xx.c:704 -#: ../backend/kvs40xx.c:722 ../backend/kvs40xx_opt.c:101 -#: ../backend/kvs40xx_opt.c:1086 -#, no-c-format -msgid "continuous" -msgstr "" - -#: ../backend/kvs1025_opt.c:83 ../backend/kvs20xx_opt.c:61 -#: ../backend/kvs40xx_opt.c:114 -#, no-c-format -msgid "off" -msgstr "" - -#: ../backend/kvs1025_opt.c:84 ../backend/kvs20xx_opt.c:62 -#: ../backend/kvs40xx_opt.c:115 -#, no-c-format -msgid "wait_doc" -msgstr "" - -#: ../backend/kvs1025_opt.c:85 ../backend/kvs20xx_opt.c:63 -#: ../backend/kvs40xx_opt.c:117 -#, no-c-format -msgid "wait_key" -msgstr "" - -#: ../backend/kvs1025_opt.c:96 ../backend/kvs20xx_opt.c:69 -#: ../backend/kvs40xx_opt.c:123 ../backend/kvs40xx_opt.c:140 -#, no-c-format -msgid "user_def" -msgstr "" - -#: ../backend/kvs1025_opt.c:97 ../backend/kvs20xx_opt.c:70 -#: ../backend/kvs40xx_opt.c:124 ../backend/kvs40xx_opt.c:141 -#, no-c-format -msgid "business_card" -msgstr "" - -#: ../backend/kvs1025_opt.c:98 ../backend/kvs40xx_opt.c:125 -#: ../backend/kvs40xx_opt.c:142 -#, no-c-format -msgid "Check" -msgstr "" - -#: ../backend/kvs1025_opt.c:101 ../backend/kvs20xx_opt.c:74 -#: ../backend/kvs40xx_opt.c:128 ../backend/kvs40xx_opt.c:145 -#, no-c-format -msgid "A5" -msgstr "" - -#: ../backend/kvs1025_opt.c:102 ../backend/kvs20xx_opt.c:75 -#: ../backend/kvs40xx_opt.c:129 ../backend/kvs40xx_opt.c:146 -#, no-c-format -msgid "A6" -msgstr "" - -#: ../backend/kvs1025_opt.c:106 ../backend/kvs20xx_opt.c:79 -#: ../backend/kvs40xx_opt.c:133 ../backend/kvs40xx_opt.c:150 -#, no-c-format -msgid "B5" -msgstr "" - -#: ../backend/kvs1025_opt.c:107 ../backend/kvs20xx_opt.c:80 -#: ../backend/kvs40xx_opt.c:134 ../backend/kvs40xx_opt.c:151 -#, no-c-format -msgid "B6" -msgstr "" - -#: ../backend/kvs1025_opt.c:108 ../backend/kvs20xx_opt.c:81 -#: ../backend/kvs40xx_opt.c:135 ../backend/kvs40xx_opt.c:152 -#, no-c-format -msgid "Legal" -msgstr "" - -#: ../backend/kvs1025_opt.c:149 ../backend/kvs40xx_opt.c:238 -#, no-c-format -msgid "bayer_64" -msgstr "" - -#: ../backend/kvs1025_opt.c:150 ../backend/kvs40xx_opt.c:239 -#, no-c-format -msgid "bayer_16" -msgstr "" - -#: ../backend/kvs1025_opt.c:151 ../backend/kvs40xx_opt.c:240 -#, no-c-format -msgid "halftone_32" -msgstr "" - -#: ../backend/kvs1025_opt.c:152 ../backend/kvs40xx_opt.c:241 -#, no-c-format -msgid "halftone_64" -msgstr "" - -#: ../backend/kvs1025_opt.c:153 -#, no-c-format -msgid "diffusion" -msgstr "" - -#: ../backend/kvs1025_opt.c:166 ../backend/kvs1025_opt.c:228 -#: ../backend/kvs1025_opt.c:241 ../backend/kvs20xx_opt.c:128 -#: ../backend/kvs20xx_opt.c:136 ../backend/kvs40xx_opt.c:214 -#: ../backend/kvs40xx_opt.c:222 ../backend/kvs40xx_opt.c:257 -#, no-c-format -msgid "normal" -msgstr "" - -#: ../backend/kvs1025_opt.c:167 ../backend/kvs40xx_opt.c:258 -#, no-c-format -msgid "light" -msgstr "" - -#: ../backend/kvs1025_opt.c:168 ../backend/kvs40xx_opt.c:259 -#, no-c-format -msgid "dark" -msgstr "" - -#: ../backend/kvs1025_opt.c:179 ../backend/kvs40xx_opt.c:270 -#, no-c-format -msgid "From scanner" -msgstr "" - -#: ../backend/kvs1025_opt.c:180 ../backend/kvs40xx_opt.c:271 -#: ../backend/matsushita.c:177 -#, no-c-format -msgid "From paper" -msgstr "" - -#: ../backend/kvs1025_opt.c:192 ../backend/kvs40xx_opt.c:283 -#, no-c-format -msgid "default" -msgstr "" - -#: ../backend/kvs1025_opt.c:211 ../backend/kvs20xx_opt.c:122 -#: ../backend/kvs40xx_opt.c:208 -#, no-c-format -msgid "smooth" -msgstr "" - -#: ../backend/kvs1025_opt.c:212 ../backend/kvs20xx_opt.c:118 -#: ../backend/kvs40xx_opt.c:204 -#, no-c-format -msgid "none" -msgstr "" - -#: ../backend/kvs1025_opt.c:213 ../backend/kvs20xx_opt.c:119 -#: ../backend/kvs40xx_opt.c:205 -#, no-c-format -msgid "low" -msgstr "" - -#: ../backend/kvs1025_opt.c:214 ../backend/kvs1025_opt.c:804 -#: ../backend/kvs20xx_opt.c:120 ../backend/kvs40xx_opt.c:206 -#, no-c-format -msgid "medium" -msgstr "" - -#: ../backend/kvs1025_opt.c:215 ../backend/kvs20xx_opt.c:121 -#: ../backend/kvs40xx_opt.c:207 -#, no-c-format -msgid "high" -msgstr "" - -#: ../backend/kvs1025_opt.c:229 ../backend/kvs20xx_opt.c:129 -#: ../backend/kvs40xx_opt.c:215 -#, no-c-format -msgid "crt" -msgstr "" - -#: ../backend/kvs1025_opt.c:230 -#, no-c-format -msgid "linier" -msgstr "" - -#: ../backend/kvs1025_opt.c:242 ../backend/kvs20xx_opt.c:137 -#: ../backend/kvs40xx_opt.c:223 -#, no-c-format -msgid "red" -msgstr "" - -#: ../backend/kvs1025_opt.c:243 ../backend/kvs20xx_opt.c:138 -#: ../backend/kvs40xx_opt.c:224 -#, no-c-format -msgid "green" -msgstr "" - -#: ../backend/kvs1025_opt.c:244 ../backend/kvs20xx_opt.c:139 -#: ../backend/kvs40xx_opt.c:225 -#, no-c-format -msgid "blue" -msgstr "" - -#: ../backend/kvs1025_opt.c:562 -#, no-c-format -msgid "Sets the scan source" -msgstr "" - -#: ../backend/kvs1025_opt.c:573 ../backend/kvs20xx_opt.c:217 -#: ../backend/kvs40xx_opt.c:366 ../backend/matsushita.c:1126 -#, no-c-format -msgid "Feeder mode" -msgstr "" - -#: ../backend/kvs1025_opt.c:574 ../backend/kvs20xx_opt.c:218 -#: ../backend/kvs40xx_opt.c:367 ../backend/matsushita.c:1127 -#, no-c-format -msgid "Sets the feeding mode" -msgstr "" - -#: ../backend/kvs1025_opt.c:584 -#, no-c-format -msgid "Enable/Disable long paper mode" -msgstr "" - -#: ../backend/kvs1025_opt.c:593 -#, no-c-format -msgid "Enable/Disable length control mode" -msgstr "" - -#: ../backend/kvs1025_opt.c:601 ../backend/kvs20xx_opt.c:242 -#: ../backend/kvs40xx_opt.c:416 -#, no-c-format -msgid "Sets the manual feed mode" -msgstr "" - -#: ../backend/kvs1025_opt.c:612 ../backend/kvs20xx_opt.c:254 -#: ../backend/kvs40xx_opt.c:428 -#, no-c-format -msgid "Sets the manual feed timeout in seconds" -msgstr "" - -#: ../backend/kvs1025_opt.c:625 ../backend/kvs20xx_opt.c:267 -#: ../backend/kvs40xx_opt.c:441 -#, no-c-format -msgid "Enable/Disable double feed detection" -msgstr "" - -#: ../backend/kvs1025_opt.c:631 ../backend/kvs20xx_opt.c:275 -#: ../backend/kvs40xx_opt.c:496 -#, no-c-format -msgid "fit-to-page" -msgstr "" - -#: ../backend/kvs1025_opt.c:632 ../backend/kvs20xx_opt.c:276 -#: ../backend/kvs40xx_opt.c:497 -#, no-c-format -msgid "Fit to page" -msgstr "" - -#: ../backend/kvs1025_opt.c:634 ../backend/kvs20xx_opt.c:277 -#: ../backend/kvs40xx_opt.c:498 -#, no-c-format -msgid "Scanner shrinks image to fit scanned page" -msgstr "" - -#: ../backend/kvs1025_opt.c:661 ../backend/kvs20xx_opt.c:308 -#: ../backend/kvs40xx_opt.c:532 -#, no-c-format -msgid "Set paper position : true for landscape, false for portrait" -msgstr "" - -#: ../backend/kvs1025_opt.c:735 ../backend/matsushita.c:1224 -#, no-c-format -msgid "Automatic threshold" -msgstr "" - -#: ../backend/kvs1025_opt.c:738 ../backend/matsushita.c:1227 -#, no-c-format -msgid "" -"Automatically sets brightness, contrast, white level, gamma, noise reduction " -"and image emphasis" -msgstr "" - -#: ../backend/kvs1025_opt.c:783 ../backend/kvs40xx_opt.c:763 -#: ../backend/matsushita.c:1275 -#, no-c-format -msgid "Noise reduction" -msgstr "" - -#: ../backend/kvs1025_opt.c:785 ../backend/kvs40xx_opt.c:764 -#: ../backend/matsushita.c:1277 -#, no-c-format -msgid "Reduce the isolated dot noise" -msgstr "" - -#: ../backend/kvs1025_opt.c:796 ../backend/kvs20xx_opt.c:411 -#: ../backend/kvs40xx_opt.c:654 ../backend/matsushita.c:1288 -#, no-c-format -msgid "Image emphasis" -msgstr "" - -#: ../backend/kvs1025_opt.c:797 ../backend/kvs20xx_opt.c:412 -#: ../backend/kvs40xx_opt.c:655 ../backend/matsushita.c:1289 -#, no-c-format -msgid "Sets the image emphasis" -msgstr "" - -#: ../backend/kvs1025_opt.c:808 ../backend/kvs1025_opt.c:809 -#: ../backend/matsushita.c:1300 ../backend/matsushita.c:1301 -#: ../backend/pixma_sane_options.c:110 -#, no-c-format -msgid "Gamma" -msgstr "" - -#: ../backend/kvs1025_opt.c:818 ../backend/kvs20xx_opt.c:435 -#: ../backend/kvs40xx_opt.c:680 -#, no-c-format -msgid "Lamp color" -msgstr "" - -#: ../backend/kvs1025_opt.c:819 ../backend/kvs20xx_opt.c:436 -#: ../backend/kvs40xx_opt.c:681 -#, no-c-format -msgid "Sets the lamp color (color dropout)" -msgstr "" - -#: ../backend/kvs1025_opt.c:832 -#, no-c-format -msgid "Inverse image in B/W or halftone mode" -msgstr "" - -#: ../backend/kvs1025_opt.c:840 -#, no-c-format -msgid "Mirror image (left/right flip)" -msgstr "" - -#: ../backend/kvs1025_opt.c:847 -#, no-c-format -msgid "jpeg compression" -msgstr "" - -#: ../backend/kvs1025_opt.c:850 -#, no-c-format -msgid "JPEG Image Compression with Q parameter, '0' - no compression" -msgstr "" - -#: ../backend/kvs1025_opt.c:860 -#, no-c-format -msgid "Rotate image clockwise" -msgstr "" - -#: ../backend/kvs1025_opt.c:862 -#, no-c-format -msgid "Request driver to rotate pages by a fixed amount" -msgstr "" - -#: ../backend/kvs1025_opt.c:872 -#, no-c-format -msgid "Software deskew" -msgstr "" - -#: ../backend/kvs1025_opt.c:874 -#, no-c-format -msgid "Request driver to rotate skewed pages digitally" -msgstr "" - -#: ../backend/kvs1025_opt.c:881 -#, no-c-format -msgid "Software despeckle diameter" -msgstr "" - -#: ../backend/kvs1025_opt.c:883 -#, no-c-format -msgid "Maximum diameter of lone dots to remove from scan" -msgstr "" - -#: ../backend/kvs1025_opt.c:902 -#, no-c-format -msgid "Software automatic cropping" -msgstr "" - -#: ../backend/kvs1025_opt.c:904 -#, no-c-format -msgid "Request driver to remove border from pages digitally" -msgstr "" - -#: ../backend/kvs20xx_opt.c:232 ../backend/kvs40xx_opt.c:395 -#, no-c-format -msgid "" -"Length Control Mode is a mode that the scanner reads up to the shorter " -"length of actual paper or logical document length." -msgstr "" - -#: ../backend/kvs20xx_opt.c:423 ../backend/kvs20xx_opt.c:424 -#: ../backend/kvs40xx_opt.c:667 ../backend/kvs40xx_opt.c:668 -#: ../backend/microtek2.h:640 -#, no-c-format -msgid "Gamma correction" -msgstr "" - -#: ../backend/kvs40xx_opt.c:116 -#, no-c-format -msgid "wait_doc_hopper_up" -msgstr "" - -#: ../backend/kvs40xx_opt.c:126 -#, no-c-format -msgid "A3" -msgstr "" - -#: ../backend/kvs40xx_opt.c:131 -#, no-c-format -msgid "Double letter 11x17 in" -msgstr "" - -#: ../backend/kvs40xx_opt.c:132 -#, no-c-format -msgid "B4" -msgstr "" - -#: ../backend/kvs40xx_opt.c:230 -#, no-c-format -msgid "High sensivity" -msgstr "" - -#: ../backend/kvs40xx_opt.c:231 -#, no-c-format -msgid "Low sensivity" -msgstr "" - -#: ../backend/kvs40xx_opt.c:242 -#, no-c-format -msgid "err_diffusion" -msgstr "" - -#: ../backend/kvs40xx_opt.c:248 -#, no-c-format -msgid "No detection" -msgstr "" - -#: ../backend/kvs40xx_opt.c:249 -#, no-c-format -msgid "Normal mode" -msgstr "" - -#: ../backend/kvs40xx_opt.c:250 -#, no-c-format -msgid "Enhanced mode" -msgstr "" - -#: ../backend/kvs40xx_opt.c:404 -#, no-c-format -msgid "" -"Long Paper Mode is a mode that the scanner reads the image after it divides " -"long paper by the length which is set in Document Size option." -msgstr "" - -#: ../backend/kvs40xx_opt.c:448 -#, no-c-format -msgid "Double feed detector sensitivity" -msgstr "" - -#: ../backend/kvs40xx_opt.c:449 -#, no-c-format -msgid "Set the double feed detector sensitivity" -msgstr "" - -#: ../backend/kvs40xx_opt.c:460 ../backend/kvs40xx_opt.c:461 -#, no-c-format -msgid "Do not stop after double feed detection" -msgstr "" - -#: ../backend/kvs40xx_opt.c:469 ../backend/kvs40xx_opt.c:470 -#, no-c-format -msgid "Ignore left double feed sensor" -msgstr "" - -#: ../backend/kvs40xx_opt.c:478 ../backend/kvs40xx_opt.c:479 -#, no-c-format -msgid "Ignore center double feed sensor" -msgstr "" - -#: ../backend/kvs40xx_opt.c:487 ../backend/kvs40xx_opt.c:488 -#, no-c-format -msgid "Ignore right double feed sensor" -msgstr "" - -#: ../backend/kvs40xx_opt.c:641 -#, no-c-format -msgid "Automatic threshold mode" -msgstr "" - -#: ../backend/kvs40xx_opt.c:642 -#, no-c-format -msgid "Sets the automatic threshold mode" -msgstr "" - -#: ../backend/kvs40xx_opt.c:693 -#, no-c-format -msgid "Inverse image in B/W mode" -msgstr "" - -#: ../backend/kvs40xx_opt.c:714 -#, no-c-format -msgid "JPEG compression" -msgstr "" - -#: ../backend/kvs40xx_opt.c:717 -#, no-c-format -msgid "JPEG compression (yours application must be able to uncompress)" -msgstr "" - -#: ../backend/kvs40xx_opt.c:736 ../backend/kvs40xx_opt.c:737 -#, no-c-format -msgid "Detect stapled document" -msgstr "" - -#: ../backend/kvs40xx_opt.c:775 -#, no-c-format -msgid "chroma of red" -msgstr "" - -#: ../backend/kvs40xx_opt.c:776 -#, no-c-format -msgid "Set chroma of red" -msgstr "" - -#: ../backend/kvs40xx_opt.c:786 -#, no-c-format -msgid "chroma of blue" -msgstr "" - -#: ../backend/kvs40xx_opt.c:787 -#, no-c-format -msgid "Set chroma of blue" -msgstr "" - -#: ../backend/kvs40xx_opt.c:797 ../backend/kvs40xx_opt.c:798 -#, no-c-format -msgid "Skew adjustment" -msgstr "" - -#: ../backend/kvs40xx_opt.c:807 -#, no-c-format -msgid "Stop scanner when a paper have been skewed" -msgstr "" - -#: ../backend/kvs40xx_opt.c:808 -#, no-c-format -msgid "Scanner will be stop when a paper have been skewed" -msgstr "" - -#: ../backend/kvs40xx_opt.c:815 -#, no-c-format -msgid "Crop actual image area" -msgstr "" - -#: ../backend/kvs40xx_opt.c:816 -#, no-c-format -msgid "Scanner automatically detect image area and crop it" -msgstr "" - -#: ../backend/kvs40xx_opt.c:826 -#, no-c-format -msgid "It is right and left reversing" -msgstr "" - -#: ../backend/kvs40xx_opt.c:833 ../backend/kvs40xx_opt.c:834 -#, no-c-format -msgid "Addition of space in top position" -msgstr "" - -#: ../backend/kvs40xx_opt.c:841 ../backend/kvs40xx_opt.c:842 -#, no-c-format -msgid "Addition of space in bottom position" -msgstr "" - -#: ../backend/leo.c:110 -#, no-c-format -msgid "Diamond" -msgstr "" - -#: ../backend/leo.c:111 -#, no-c-format -msgid "8x8 Coarse Fatting" -msgstr "" - -#: ../backend/leo.c:112 -#, no-c-format -msgid "8x8 Fine Fatting" -msgstr "" - -#: ../backend/leo.c:113 -#, no-c-format -msgid "8x8 Bayer" -msgstr "" - -#: ../backend/leo.c:114 -#, no-c-format -msgid "8x8 Vertical Line" -msgstr "" - -#: ../backend/lexmark.c:273 ../backend/umax_pp.c:715 -#, no-c-format -msgid "Gain" -msgstr "" - -#: ../backend/lexmark.c:274 ../backend/umax_pp.c:716 -#, no-c-format -msgid "Color channels gain settings" -msgstr "" - -#: ../backend/lexmark.c:283 ../backend/umax_pp.c:723 -#, no-c-format -msgid "Gray gain" -msgstr "" - -#: ../backend/lexmark.c:284 ../backend/umax_pp.c:724 -#, no-c-format -msgid "Sets gray channel gain" -msgstr "" - -#: ../backend/lexmark.c:297 ../backend/plustek.c:1001 ../backend/umax_pp.c:735 -#, no-c-format -msgid "Red gain" -msgstr "" - -#: ../backend/lexmark.c:298 ../backend/umax_pp.c:736 -#, no-c-format -msgid "Sets red channel gain" -msgstr "" - -#: ../backend/lexmark.c:311 ../backend/plustek.c:1017 ../backend/umax_pp.c:747 -#, no-c-format -msgid "Green gain" -msgstr "" - -#: ../backend/lexmark.c:312 ../backend/umax_pp.c:748 -#, no-c-format -msgid "Sets green channel gain" -msgstr "" - -#: ../backend/lexmark.c:325 ../backend/plustek.c:1033 ../backend/umax_pp.c:759 -#, no-c-format -msgid "Blue gain" -msgstr "" - -#: ../backend/lexmark.c:326 ../backend/umax_pp.c:760 -#, no-c-format -msgid "Sets blue channel gain" -msgstr "" - -#: ../backend/matsushita.c:139 -#, no-c-format -msgid "Bayer Dither 16" -msgstr "" - -#: ../backend/matsushita.c:140 -#, no-c-format -msgid "Bayer Dither 64" -msgstr "" - -#: ../backend/matsushita.c:141 -#, no-c-format -msgid "Halftone Dot 32" -msgstr "" - -#: ../backend/matsushita.c:142 -#, no-c-format -msgid "Halftone Dot 64" -msgstr "" - -#: ../backend/matsushita.c:143 -#, no-c-format -msgid "Error Diffusion" -msgstr "" - -#: ../backend/matsushita.c:160 -#, no-c-format -msgid "Mode 1" -msgstr "" - -#: ../backend/matsushita.c:161 -#, no-c-format -msgid "Mode 2" -msgstr "" - -#: ../backend/matsushita.c:162 -#, no-c-format -msgid "Mode 3" -msgstr "" - -#: ../backend/matsushita.c:176 -#, no-c-format -msgid "From white stick" -msgstr "" - -#: ../backend/matsushita.c:212 -#, no-c-format -msgid "Smooth" -msgstr "" - -#: ../backend/matsushita.c:214 ../backend/matsushita.c:229 -#, no-c-format -msgid "Low" -msgstr "" - -#: ../backend/matsushita.c:215 ../backend/matsushita.c:230 -#: ../backend/matsushita.c:1296 -#, no-c-format -msgid "Medium" -msgstr "" - -#: ../backend/matsushita.c:216 ../backend/matsushita.c:231 -#, no-c-format -msgid "High" -msgstr "" - -#: ../backend/matsushita.c:245 -#, no-c-format -msgid "CRT" -msgstr "" - -#: ../backend/matsushita.c:257 -#, no-c-format -msgid "One page" -msgstr "" - -#: ../backend/matsushita.c:258 -#, no-c-format -msgid "All pages" -msgstr "" - -#: ../backend/matsushita.c:1034 ../backend/plustek.c:1333 -#, no-c-format -msgid "sheetfed scanner" -msgstr "" - -#: ../backend/matsushita.h:209 -#, no-c-format -msgid "Grayscale 4 bits" -msgstr "" - -#: ../backend/matsushita.h:210 -#, no-c-format -msgid "Grayscale 8 bits" -msgstr "" - -#: ../backend/microtek2.h:601 -#, no-c-format -msgid "Shadow, midtone, highlight, exposure time" -msgstr "" - -#: ../backend/microtek2.h:603 -#, no-c-format -msgid "Special options" -msgstr "" - -#: ../backend/microtek2.h:604 -#, no-c-format -msgid "Color balance" -msgstr "" - -#: ../backend/microtek2.h:607 -#, no-c-format -msgid "Disable backtracking" -msgstr "" - -#: ../backend/microtek2.h:608 -#, no-c-format -msgid "If checked the scanner does not perform backtracking" -msgstr "" - -#: ../backend/microtek2.h:612 -#, no-c-format -msgid "Toggle lamp of flatbed" -msgstr "" - -#: ../backend/microtek2.h:613 -#, no-c-format -msgid "Toggles the lamp of the flatbed" -msgstr "" - -#: ../backend/microtek2.h:616 -#, no-c-format -msgid "Calibration by backend" -msgstr "" - -#: ../backend/microtek2.h:617 -#, no-c-format -msgid "If checked the color calibration before a scan is done by the backend" -msgstr "" - -#: ../backend/microtek2.h:621 -#, no-c-format -msgid "Use the lightlid-35mm adapter" -msgstr "" - -#: ../backend/microtek2.h:622 -#, no-c-format -msgid "This option turns off the lamp of the flatbed during a scan" -msgstr "" - -#: ../backend/microtek2.h:626 ../backend/snapscan-options.c:421 -#, no-c-format -msgid "Quality scan" -msgstr "" - -#: ../backend/microtek2.h:627 ../backend/snapscan-options.c:422 -#, no-c-format -msgid "Highest quality but lower speed" -msgstr "" - -#: ../backend/microtek2.h:630 -#, no-c-format -msgid "Fast scan" -msgstr "" - -#: ../backend/microtek2.h:631 -#, no-c-format -msgid "Highest speed but lower quality" -msgstr "" - -#: ../backend/microtek2.h:634 -#, no-c-format -msgid "Automatic adjustment of threshold" -msgstr "" - -#: ../backend/microtek2.h:635 -#, no-c-format -msgid "" -"If checked the backend automatically tries to determine an optimal value for " -"the threshold." -msgstr "" - -#: ../backend/microtek2.h:641 -#, no-c-format -msgid "Selects the gamma correction mode." -msgstr "" - -#: ../backend/microtek2.h:644 -#, no-c-format -msgid "Bind gamma" -msgstr "" - -#: ../backend/microtek2.h:645 -#, no-c-format -msgid "Use same gamma values for all colour channels." -msgstr "" - -#: ../backend/microtek2.h:649 -#, no-c-format -msgid "Scalar gamma" -msgstr "" - -#: ../backend/microtek2.h:650 -#, no-c-format -msgid "Selects a value for scalar gamma correction." -msgstr "" - -#: ../backend/microtek2.h:654 -#, no-c-format -msgid "Scalar gamma red" -msgstr "" - -#: ../backend/microtek2.h:655 -#, no-c-format -msgid "Selects a value for scalar gamma correction (red channel)" -msgstr "" - -#: ../backend/microtek2.h:659 -#, no-c-format -msgid "Scalar gamma green" -msgstr "" - -#: ../backend/microtek2.h:660 -#, no-c-format -msgid "Selects a value for scalar gamma correction (green channel)" -msgstr "" - -#: ../backend/microtek2.h:664 -#, no-c-format -msgid "Scalar gamma blue" -msgstr "" - -#: ../backend/microtek2.h:665 -#, no-c-format -msgid "Selects a value for scalar gamma correction (blue channel)" -msgstr "" - -#: ../backend/microtek2.h:669 -#, no-c-format -msgid "Channel" -msgstr "" - -#: ../backend/microtek2.h:670 -#, no-c-format -msgid "" -"Selects the colour band, \"Master\" means that all colours are affected." -msgstr "" - -#: ../backend/microtek2.h:674 -#, no-c-format -msgid "Midtone" -msgstr "" - -#: ../backend/microtek2.h:675 -#, no-c-format -msgid "Selects which radiance level should be considered \"50 % gray\"." -msgstr "" - -#: ../backend/microtek2.h:679 -#, no-c-format -msgid "Midtone for red" -msgstr "" - -#: ../backend/microtek2.h:680 -#, no-c-format -msgid "Selects which radiance level should be considered \"50 % red\"." -msgstr "" - -#: ../backend/microtek2.h:684 -#, no-c-format -msgid "Midtone for green" -msgstr "" - -#: ../backend/microtek2.h:685 -#, no-c-format -msgid "Selects which radiance level should be considered \"50 % green\"." -msgstr "" - -#: ../backend/microtek2.h:689 -#, no-c-format -msgid "Midtone for blue" -msgstr "" - -#: ../backend/microtek2.h:690 -#, no-c-format -msgid "Selects which radiance level should be considered \"50 % blue\"." -msgstr "" - -#: ../backend/microtek2.h:694 -#, no-c-format -msgid "Red balance" -msgstr "" - -#: ../backend/microtek2.h:695 -#, no-c-format -msgid "Balance factor for red. A value of 100% means no correction." -msgstr "" - -#: ../backend/microtek2.h:699 -#, no-c-format -msgid "Green balance" -msgstr "" - -#: ../backend/microtek2.h:700 -#, no-c-format -msgid "Balance factor for green. A value of 100% means no correction." -msgstr "" - -#: ../backend/microtek2.h:704 -#, no-c-format -msgid "Blue balance" -msgstr "" - -#: ../backend/microtek2.h:705 -#, no-c-format -msgid "Balance factor for blue. A value of 100% means no correction." -msgstr "" - -#: ../backend/microtek2.h:709 -#, no-c-format -msgid "Firmware balance" -msgstr "" - -#: ../backend/microtek2.h:710 -#, no-c-format -msgid "Sets the color balance values to the firmware provided values." -msgstr "" - -#: ../backend/mustek.c:149 -#, no-c-format -msgid "Slowest" -msgstr "" - -#: ../backend/mustek.c:149 -#, no-c-format -msgid "Slower" -msgstr "" - -#: ../backend/mustek.c:150 -#, no-c-format -msgid "Faster" -msgstr "" - -#: ../backend/mustek.c:150 -#, no-c-format -msgid "Fastest" -msgstr "" - -#: ../backend/mustek.c:177 -#, no-c-format -msgid "8x8 coarse" -msgstr "" - -#: ../backend/mustek.c:177 -#, no-c-format -msgid "8x8 normal" -msgstr "" - -#: ../backend/mustek.c:177 -#, no-c-format -msgid "8x8 fine" -msgstr "" - -#: ../backend/mustek.c:178 -#, no-c-format -msgid "8x8 very fine" -msgstr "" - -#: ../backend/mustek.c:178 -#, no-c-format -msgid "6x6 normal" -msgstr "" - -#: ../backend/mustek.c:179 -#, no-c-format -msgid "5x5 coarse" -msgstr "" - -#: ../backend/mustek.c:179 -#, no-c-format -msgid "5x5 fine" -msgstr "" - -#: ../backend/mustek.c:179 -#, no-c-format -msgid "4x4 coarse" -msgstr "" - -#: ../backend/mustek.c:180 -#, no-c-format -msgid "4x4 normal" -msgstr "" - -#: ../backend/mustek.c:180 -#, no-c-format -msgid "4x4 fine" -msgstr "" - -#: ../backend/mustek.c:180 -#, no-c-format -msgid "3x3 normal" -msgstr "" - -#: ../backend/mustek.c:181 -#, no-c-format -msgid "2x2 normal" -msgstr "" - -#: ../backend/mustek.c:181 -#, no-c-format -msgid "8x8 custom" -msgstr "" - -#: ../backend/mustek.c:182 -#, no-c-format -msgid "6x6 custom" -msgstr "" - -#: ../backend/mustek.c:183 -#, no-c-format -msgid "5x5 custom" -msgstr "" - -#: ../backend/mustek.c:183 -#, no-c-format -msgid "4x4 custom" -msgstr "" - -#: ../backend/mustek.c:184 -#, no-c-format -msgid "3x3 custom" -msgstr "" - -#: ../backend/mustek.c:185 -#, no-c-format -msgid "2x2 custom" -msgstr "" - -#: ../backend/mustek.c: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 "" - -#: ../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 "" - -#: ../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 "" - -#: ../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 "" - -#: ../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 "" - -#: ../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 "" - -#: ../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 -#, no-c-format -msgid "Color48" -msgstr "" - -#: ../backend/mustek_usb2.c:106 ../backend/mustek_usb2.c:114 -#, no-c-format -msgid "Color24" -msgstr "" - -#: ../backend/mustek_usb2.c:107 -#, no-c-format -msgid "Gray16" -msgstr "" - -#: ../backend/mustek_usb2.c:108 -#, no-c-format -msgid "Gray8" -msgstr "" - -#: ../backend/mustek_usb2.c:119 -#, no-c-format -msgid "Reflective" -msgstr "" - -#: ../backend/mustek_usb2.c:120 -#, no-c-format -msgid "Positive" -msgstr "" - -#: ../backend/mustek_usb2.c:421 -#, no-c-format -msgid "" -"Warm-up until the lamp's brightness is constant instead of insisting on 40 " -"seconds warm-up time." -msgstr "" - -#: ../backend/pixma.c:378 -#, no-c-format -msgid "Negative color" -msgstr "" - -#: ../backend/pixma.c:383 -#, no-c-format -msgid "Negative gray" -msgstr "" - -#: ../backend/pixma.c:396 -#, no-c-format -msgid "48 bits color" -msgstr "" - -#: ../backend/pixma.c:401 -#, no-c-format -msgid "16 bits gray" -msgstr "" - -#: ../backend/pixma_sane_options.c:82 -#, no-c-format -msgid "" -"Selects the scan source (such as a document-feeder). Set source before mode " -"and resolution. Resets mode and resolution to auto values." -msgstr "" - -#: ../backend/pixma_sane_options.c:96 -#, no-c-format -msgid "Button-controlled scan" -msgstr "" - -#: ../backend/pixma_sane_options.c:97 -#, 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:143 -#, no-c-format -msgid "Gamma function exponent" -msgstr "" - -#: ../backend/pixma_sane_options.c:144 -#, no-c-format -msgid "Changes intensity of midtones" -msgstr "" - -#: ../backend/pixma_sane_options.c:230 -#, no-c-format -msgid "Update button state" -msgstr "" - -#: ../backend/pixma_sane_options.c:242 -#, no-c-format -msgid "Button 1" -msgstr "" - -#: ../backend/pixma_sane_options.c:256 -#, no-c-format -msgid "Button 2" -msgstr "" - -#: ../backend/pixma_sane_options.c:270 -#, no-c-format -msgid "Type of original to scan" -msgstr "" - -#: ../backend/pixma_sane_options.c:284 -#, no-c-format -msgid "Target operation type" -msgstr "" - -#: ../backend/plustek.c:235 ../backend/plustek_pp.c:204 ../backend/u12.c:156 -#, no-c-format -msgid "Transparency" -msgstr "" - -#: ../backend/plustek.c:913 -#, no-c-format -msgid "Device-Settings" -msgstr "" - -#: ../backend/plustek.c:920 -#, no-c-format -msgid "Lampswitch" -msgstr "" - -#: ../backend/plustek.c:921 -#, no-c-format -msgid "Manually switching the lamp(s)." -msgstr "" - -#: ../backend/plustek.c:926 -#, no-c-format -msgid "Lamp off during dark calibration" -msgstr "" - -#: ../backend/plustek.c:927 -#, no-c-format -msgid "Always switches lamp off when doing dark calibration." -msgstr "" - -#: ../backend/plustek.c:935 -#, no-c-format -msgid "Calibration data cache" -msgstr "" - -#: ../backend/plustek.c:936 -#, no-c-format -msgid "Enables or disables calibration data cache." -msgstr "" - -#: ../backend/plustek.c:942 -#, no-c-format -msgid "Performs calibration" -msgstr "" - -#: ../backend/plustek.c:959 -#, no-c-format -msgid "Speedup sensor" -msgstr "" - -#: ../backend/plustek.c:960 -#, no-c-format -msgid "Enables or disables speeding up sensor movement." -msgstr "" - -#: ../backend/plustek.c:974 -#, no-c-format -msgid "Warmup-time" -msgstr "" - -#: ../backend/plustek.c:975 -#, no-c-format -msgid "Warmup-time in seconds." -msgstr "" - -#: ../backend/plustek.c:987 -#, no-c-format -msgid "Lampoff-time" -msgstr "" - -#: ../backend/plustek.c:988 -#, no-c-format -msgid "Lampoff-time in seconds." -msgstr "" - -#: ../backend/plustek.c:995 -#, no-c-format -msgid "Analog frontend" -msgstr "" - -#: ../backend/plustek.c:1002 -#, no-c-format -msgid "Red gain value of the AFE" -msgstr "" - -#: ../backend/plustek.c:1009 ../backend/umax_pp.c:792 -#, no-c-format -msgid "Red offset" -msgstr "" - -#: ../backend/plustek.c:1010 -#, no-c-format -msgid "Red offset value of the AFE" -msgstr "" - -#: ../backend/plustek.c:1018 -#, no-c-format -msgid "Green gain value of the AFE" -msgstr "" - -#: ../backend/plustek.c:1025 ../backend/umax_pp.c:804 -#, no-c-format -msgid "Green offset" -msgstr "" - -#: ../backend/plustek.c:1026 -#, no-c-format -msgid "Green offset value of the AFE" -msgstr "" - -#: ../backend/plustek.c:1034 -#, no-c-format -msgid "Blue gain value of the AFE" -msgstr "" - -#: ../backend/plustek.c:1041 ../backend/umax_pp.c:816 -#, no-c-format -msgid "Blue offset" -msgstr "" - -#: ../backend/plustek.c:1042 -#, no-c-format -msgid "Blue offset value of the AFE" -msgstr "" - -#: ../backend/plustek.c:1049 -#, no-c-format -msgid "Red lamp off" -msgstr "" - -#: ../backend/plustek.c:1050 -#, no-c-format -msgid "Defines red lamp off parameter" -msgstr "" - -#: ../backend/plustek.c:1057 -#, no-c-format -msgid "Green lamp off" -msgstr "" - -#: ../backend/plustek.c:1058 -#, no-c-format -msgid "Defines green lamp off parameter" -msgstr "" - -#: ../backend/plustek.c:1065 -#, no-c-format -msgid "Blue lamp off" -msgstr "" - -#: ../backend/plustek.c:1066 -#, no-c-format -msgid "Defines blue lamp off parameter" -msgstr "" - -#: ../backend/plustek.c:1096 -#, no-c-format -msgid "This option reflects the status of the scanner buttons." -msgstr "" - -#: ../backend/plustek_pp.c:197 -#, no-c-format -msgid "Color36" -msgstr "" - -#: ../backend/plustek_pp.c:211 -#, no-c-format -msgid "Dithermap 1" -msgstr "" - -#: ../backend/plustek_pp.c:212 -#, no-c-format -msgid "Dithermap 2" -msgstr "" - -#: ../backend/plustek_pp.c:213 -#, no-c-format -msgid "Randomize" -msgstr "" - -#: ../backend/pnm.c:168 -#, no-c-format -msgid "Source Selection" -msgstr "" - -#: ../backend/pnm.c:205 -#, no-c-format -msgid "Image Enhancement" -msgstr "" - -#: ../backend/pnm.c:241 -#, no-c-format -msgid "Grayify" -msgstr "" - -#: ../backend/pnm.c:242 -#, no-c-format -msgid "Load the image as grayscale." -msgstr "" - -#: ../backend/pnm.c:253 -#, no-c-format -msgid "Three-Pass Simulation" -msgstr "" - -#: ../backend/pnm.c:255 -#, no-c-format -msgid "" -"Simulate a three-pass scanner by returning 3 separate frames. For kicks, it " -"returns green, then blue, then red." -msgstr "" - -#: ../backend/pnm.c:267 -#, no-c-format -msgid "Hand-Scanner Simulation" -msgstr "" - -#: ../backend/pnm.c:268 -#, no-c-format -msgid "" -"Simulate a hand-scanner. Hand-scanners often do not know the image height a " -"priori. Instead, they return a height of -1. Setting this option allows 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:2803 -#, no-c-format -msgid "This option reflects the status of a scanner button." -msgstr "" - -#: ../backend/rts8891.c:2834 ../backend/umax.c:5795 ../backend/umax_pp.c:639 -#, no-c-format -msgid "Lamp on" -msgstr "" - -#: ../backend/rts8891.c:2835 ../backend/umax.c:5796 -#, no-c-format -msgid "Turn on scanner lamp" -msgstr "" - -#: ../backend/rts8891.c:2845 ../backend/umax1220u.c:248 ../backend/umax.c:5812 -#, no-c-format -msgid "Lamp off" -msgstr "" - -#: ../backend/rts8891.c:2846 ../backend/umax1220u.c:249 ../backend/umax.c:5813 -#, no-c-format -msgid "Turn off scanner lamp" -msgstr "" - -#: ../backend/sm3840.c:760 -#, no-c-format -msgid "Lamp timeout" -msgstr "" - -#: ../backend/sm3840.c:762 -#, no-c-format -msgid "Minutes until lamp is turned off after scan" -msgstr "" - -#: ../backend/sm3840.c:772 -#, no-c-format -msgid "Threshold value for lineart mode" -msgstr "" - -#: ../backend/snapscan-options.c:88 -#, no-c-format -msgid "Document Feeder" -msgstr "" - -#: ../backend/snapscan-options.c:92 -#, no-c-format -msgid "6x4 (inch)" -msgstr "" - -#: ../backend/snapscan-options.c:93 -#, no-c-format -msgid "8x10 (inch)" -msgstr "" - -#: ../backend/snapscan-options.c:94 -#, no-c-format -msgid "8.5x11 (inch)" -msgstr "" - -#: ../backend/snapscan-options.c:97 -#, no-c-format -msgid "Halftoning Unsupported" -msgstr "" - -#: ../backend/snapscan-options.c:98 -#, no-c-format -msgid "DispersedDot8x8" -msgstr "" - -#: ../backend/snapscan-options.c:99 -#, no-c-format -msgid "DispersedDot16x16" -msgstr "" - -#: ../backend/snapscan-options.c:103 -#, no-c-format -msgid "" -"Number of scan lines to request in a SCSI read. Changing this parameter " -"allows you to tune the speed at which data is read from the scanner during " -"scans. If this is set too low, the scanner will have to stop periodically in " -"the middle of a scan; if it's set too high, X-based frontends may stop " -"responding to X events and your system could bog down." -msgstr "" - -#: ../backend/snapscan-options.c:111 -#, no-c-format -msgid "Frame number of media holder that should be scanned." -msgstr "" - -#: ../backend/snapscan-options.c:114 -#, no-c-format -msgid "Use manual or automatic selection of focus point." -msgstr "" - -#: ../backend/snapscan-options.c:117 -#, no-c-format -msgid "Focus point for scanning." -msgstr "" - -#: ../backend/snapscan-options.c:482 -#, no-c-format -msgid "Preview mode" -msgstr "" - -#: ../backend/snapscan-options.c:484 -#, no-c-format -msgid "" -"Select the mode for previews. Greyscale previews usually give the best " -"combination of speed and detail." -msgstr "" - -#: ../backend/snapscan-options.c:601 -#, no-c-format -msgid "Predefined settings" -msgstr "" - -#: ../backend/snapscan-options.c:603 -#, no-c-format -msgid "" -"Provides standard scanning areas for photographs, printed pages and the like." -msgstr "" - -#: ../backend/snapscan-options.c:884 -#, no-c-format -msgid "Frame" -msgstr "" - -#: ../backend/snapscan-options.c:885 -#, no-c-format -msgid "Frame to be scanned" -msgstr "" - -#: ../backend/snapscan-options.c:897 -#, no-c-format -msgid "Focus-mode" -msgstr "" - -#: ../backend/snapscan-options.c:898 -#, no-c-format -msgid "Auto or manual focus" -msgstr "" - -#: ../backend/snapscan-options.c:911 -#, no-c-format -msgid "Focus-point" -msgstr "" - -#: ../backend/snapscan-options.c:912 -#, no-c-format -msgid "Focus point" -msgstr "" - -#: ../backend/snapscan-options.c:930 -#, no-c-format -msgid "Colour lines per read" -msgstr "" - -#: ../backend/snapscan-options.c:942 -#, no-c-format -msgid "Greyscale lines per read" -msgstr "" - -#: ../backend/stv680.c:974 -#, no-c-format -msgid "webcam" -msgstr "" - -#: ../backend/stv680.h:115 -#, no-c-format -msgid "Color RAW" -msgstr "" - -#: ../backend/stv680.h:116 -#, no-c-format -msgid "Color RGB" -msgstr "" - -#: ../backend/stv680.h:117 -#, no-c-format -msgid "Color RGB TEXT" -msgstr "" - -#: ../backend/test.c:137 -#, no-c-format -msgid "Solid black" -msgstr "" - -#: ../backend/test.c:137 -#, no-c-format -msgid "Solid white" -msgstr "" - -#: ../backend/test.c:138 -#, no-c-format -msgid "Color pattern" -msgstr "" - -#: ../backend/test.c:138 -#, no-c-format -msgid "Grid" -msgstr "" - -#: ../backend/test.c:163 ../backend/test.c:171 -#, no-c-format -msgid "First entry" -msgstr "" - -#: ../backend/test.c:163 ../backend/test.c:171 -#, no-c-format -msgid "Second entry" -msgstr "" - -#: ../backend/test.c:165 -#, no-c-format -msgid "" -"This is the very long third entry. Maybe the frontend has an idea how to " -"display it" -msgstr "" - -#: ../backend/test.c:348 -#, no-c-format -msgid "Hand-scanner simulation" -msgstr "" - -#: ../backend/test.c:349 -#, no-c-format -msgid "" -"Simulate a hand-scanner. Hand-scanners do not know the image height a " -"priori. Instead, they return a height of -1. Setting this option allows to " -"test whether a frontend can handle this correctly. This option also enables " -"a fixed width of 11 cm." -msgstr "" - -#: ../backend/test.c:366 -#, no-c-format -msgid "Three-pass simulation" -msgstr "" - -#: ../backend/test.c:367 -#, no-c-format -msgid "" -"Simulate a three-pass scanner. In color mode, three frames are transmitted." -msgstr "" - -#: ../backend/test.c:382 -#, no-c-format -msgid "Set the order of frames" -msgstr "" - -#: ../backend/test.c:383 -#, no-c-format -msgid "Set the order of frames in three-pass color mode." -msgstr "" - -#: ../backend/test.c:416 -#, no-c-format -msgid "" -"If Automatic Document Feeder is selected, the feeder will be 'empty' after " -"10 scans." -msgstr "" - -#: ../backend/test.c:431 -#, no-c-format -msgid "Special Options" -msgstr "" - -#: ../backend/test.c:444 -#, no-c-format -msgid "Select the test picture" -msgstr "" - -#: ../backend/test.c:446 -#, no-c-format -msgid "" -"Select the kind of test picture. Available options:\n" -"Solid black: fills the whole scan with black.\n" -"Solid white: fills the whole scan with white.\n" -"Color pattern: draws various color test patterns depending on the mode.\n" -"Grid: draws a black/white grid with a width and height of 10 mm per square." -msgstr "" - -#: ../backend/test.c:467 -#, no-c-format -msgid "Invert endianness" -msgstr "" - -#: ../backend/test.c:468 -#, no-c-format -msgid "" -"Exchange upper and lower byte of image data in 16 bit modes. This option can " -"be used to test the 16 bit modes of frontends, e.g. if the frontend uses the " -"correct endianness." -msgstr "" - -#: ../backend/test.c:484 -#, no-c-format -msgid "Read limit" -msgstr "" - -#: ../backend/test.c:485 -#, no-c-format -msgid "Limit the amount of data transferred with each call to sane_read()." -msgstr "" - -#: ../backend/test.c:498 -#, no-c-format -msgid "Size of read-limit" -msgstr "" - -#: ../backend/test.c:499 -#, no-c-format -msgid "The (maximum) amount of data transferred with each call to sane_read()." -msgstr "" - -#: ../backend/test.c:514 -#, no-c-format -msgid "Read delay" -msgstr "" - -#: ../backend/test.c:515 -#, no-c-format -msgid "Delay the transfer of data to the pipe." -msgstr "" - -#: ../backend/test.c:527 -#, no-c-format -msgid "Duration of read-delay" -msgstr "" - -#: ../backend/test.c:528 -#, no-c-format -msgid "" -"How long to wait after transferring each buffer of data through the pipe." -msgstr "" - -#: ../backend/test.c:543 -#, no-c-format -msgid "Return-value of sane_read" -msgstr "" - -#: ../backend/test.c:545 -#, no-c-format -msgid "" -"Select the return-value of sane_read(). \"Default\" is the normal handling " -"for scanning. All other status codes are for testing how the frontend " -"handles them." -msgstr "" - -#: ../backend/test.c:562 -#, no-c-format -msgid "Loss of pixels per line" -msgstr "" - -#: ../backend/test.c:564 -#, no-c-format -msgid "The number of pixels that are wasted at the end of each line." -msgstr "" - -#: ../backend/test.c:577 -#, no-c-format -msgid "Fuzzy parameters" -msgstr "" - -#: ../backend/test.c:578 -#, no-c-format -msgid "" -"Return fuzzy lines and bytes per line when sane_parameters() is called " -"before sane_start()." -msgstr "" - -#: ../backend/test.c:591 -#, no-c-format -msgid "Use non-blocking IO" -msgstr "" - -#: ../backend/test.c:592 -#, no-c-format -msgid "Use non-blocking IO for sane_read() if supported by the frontend." -msgstr "" - -#: ../backend/test.c:605 -#, no-c-format -msgid "Offer select file descriptor" -msgstr "" - -#: ../backend/test.c:606 -#, no-c-format -msgid "" -"Offer a select filedescriptor for detecting if sane_read() will return data." -msgstr "" - -#: ../backend/test.c:619 -#, no-c-format -msgid "Enable test options" -msgstr "" - -#: ../backend/test.c:620 -#, no-c-format -msgid "" -"Enable various test options. This is for testing the ability of frontends to " -"view and modify all the different SANE option types." -msgstr "" - -#: ../backend/test.c:634 -#, no-c-format -msgid "Print options" -msgstr "" - -#: ../backend/test.c:635 -#, no-c-format -msgid "Print a list of all options." -msgstr "" - -#: ../backend/test.c:712 -#, no-c-format -msgid "Bool test options" -msgstr "" - -#: ../backend/test.c:725 -#, no-c-format -msgid "(1/6) Bool soft select soft detect" -msgstr "" - -#: ../backend/test.c:727 -#, no-c-format -msgid "" -"(1/6) Bool test option that has soft select and soft detect (and advanced) " -"capabilities. That's just a normal bool option." -msgstr "" - -#: ../backend/test.c:743 -#, no-c-format -msgid "(2/6) Bool hard select soft detect" -msgstr "" - -#: ../backend/test.c:745 -#, no-c-format -msgid "" -"(2/6) Bool test option that has hard select and soft detect (and advanced) " -"capabilities. That means the option can't be set by the frontend but by the " -"user (e.g. by pressing a button at the device)." -msgstr "" - -#: ../backend/test.c:762 -#, no-c-format -msgid "(3/6) Bool hard select" -msgstr "" - -#: ../backend/test.c:763 -#, no-c-format -msgid "" -"(3/6) Bool test option that has hard select (and advanced) capabilities. " -"That means the option can't be set by the frontend but by the user (e.g. by " -"pressing a button at the device) and can't be read by the frontend." -msgstr "" - -#: ../backend/test.c:781 -#, no-c-format -msgid "(4/6) Bool soft detect" -msgstr "" - -#: ../backend/test.c:782 -#, no-c-format -msgid "" -"(4/6) Bool test option that has soft detect (and advanced) capabilities. " -"That means the option is read-only." -msgstr "" - -#: ../backend/test.c:798 -#, no-c-format -msgid "(5/6) Bool soft select soft detect emulated" -msgstr "" - -#: ../backend/test.c:799 -#, no-c-format -msgid "" -"(5/6) Bool test option that has soft select, soft detect, and emulated (and " -"advanced) capabilities." -msgstr "" - -#: ../backend/test.c:815 -#, no-c-format -msgid "(6/6) Bool soft select soft detect auto" -msgstr "" - -#: ../backend/test.c:816 -#, no-c-format -msgid "" -"(6/6) Bool test option that has soft select, soft detect, and automatic (and " -"advanced) capabilities. This option can be automatically set by the backend." -msgstr "" - -#: ../backend/test.c:833 -#, no-c-format -msgid "Int test options" -msgstr "" - -#: ../backend/test.c:846 -#, no-c-format -msgid "(1/6) Int" -msgstr "" - -#: ../backend/test.c:847 -#, no-c-format -msgid "(1/6) Int test option with no unit and no constraint set." -msgstr "" - -#: ../backend/test.c:862 -#, no-c-format -msgid "(2/6) Int constraint range" -msgstr "" - -#: ../backend/test.c:863 -#, no-c-format -msgid "" -"(2/6) Int test option with unit pixel and constraint range set. Minimum is " -"4, maximum 192, and quant is 2." -msgstr "" - -#: ../backend/test.c:879 -#, no-c-format -msgid "(3/6) Int constraint word list" -msgstr "" - -#: ../backend/test.c:880 -#, no-c-format -msgid "(3/6) Int test option with unit bits and constraint word list set." -msgstr "" - -#: ../backend/test.c:895 -#, no-c-format -msgid "(4/6) Int array" -msgstr "" - -#: ../backend/test.c:896 -#, no-c-format -msgid "" -"(4/6) Int test option with unit mm and using an array without constraints." -msgstr "" - -#: ../backend/test.c:911 -#, no-c-format -msgid "(5/6) Int array constraint range" -msgstr "" - -#: ../backend/test.c:912 -#, no-c-format -msgid "" -"(5/6) Int test option with unit dpi and using an array with a range " -"constraint. Minimum is 4, maximum 192, and quant is 2." -msgstr "" - -#: ../backend/test.c:929 -#, no-c-format -msgid "(6/6) Int array constraint word list" -msgstr "" - -#: ../backend/test.c:930 -#, no-c-format -msgid "" -"(6/6) Int test option with unit percent and using an array with a word list " -"constraint." -msgstr "" - -#: ../backend/test.c:946 -#, no-c-format -msgid "Fixed test options" -msgstr "" - -#: ../backend/test.c:959 -#, no-c-format -msgid "(1/3) Fixed" -msgstr "" - -#: ../backend/test.c:960 -#, no-c-format -msgid "(1/3) Fixed test option with no unit and no constraint set." -msgstr "" - -#: ../backend/test.c:975 -#, no-c-format -msgid "(2/3) Fixed constraint range" -msgstr "" - -#: ../backend/test.c:976 -#, no-c-format -msgid "" -"(2/3) Fixed test option with unit microsecond and constraint range set. " -"Minimum is -42.17, maximum 32767.9999, and quant is 2.0." -msgstr "" - -#: ../backend/test.c:992 -#, no-c-format -msgid "(3/3) Fixed constraint word list" -msgstr "" - -#: ../backend/test.c:993 -#, no-c-format -msgid "(3/3) Fixed test option with no unit and constraint word list set." -msgstr "" - -#: ../backend/test.c:1008 -#, no-c-format -msgid "String test options" -msgstr "" - -#: ../backend/test.c:1021 -#, no-c-format -msgid "(1/3) String" -msgstr "" - -#: ../backend/test.c:1022 -#, no-c-format -msgid "(1/3) String test option without constraint." -msgstr "" - -#: ../backend/test.c:1039 -#, no-c-format -msgid "(2/3) String constraint string list" -msgstr "" - -#: ../backend/test.c:1040 -#, no-c-format -msgid "(2/3) String test option with string list constraint." -msgstr "" - -#: ../backend/test.c:1059 -#, no-c-format -msgid "(3/3) String constraint long string list" -msgstr "" - -#: ../backend/test.c:1060 -#, no-c-format -msgid "" -"(3/3) String test option with string list constraint. Contains some more " -"entries..." -msgstr "" - -#: ../backend/test.c:1080 -#, no-c-format -msgid "Button test options" -msgstr "" - -#: ../backend/test.c:1093 -#, no-c-format -msgid "(1/1) Button" -msgstr "" - -#: ../backend/test.c:1094 -#, no-c-format -msgid "(1/1) Button test option. Prints some text..." -msgstr "" - -#: ../backend/u12.c:149 -#, no-c-format -msgid "Color 36" -msgstr "" - -#: ../backend/umax.c:235 -#, no-c-format -msgid "Use Image Composition" -msgstr "" - -#: ../backend/umax.c:236 -#, no-c-format -msgid "Bi-level black and white (lineart mode)" -msgstr "" - -#: ../backend/umax.c:237 -#, no-c-format -msgid "Dithered/halftone black & white (halftone mode)" -msgstr "" - -#: ../backend/umax.c:238 -#, no-c-format -msgid "Multi-level black & white (grayscale mode)" -msgstr "" - -#: ../backend/umax.c:239 -#, no-c-format -msgid "Multi-level RGB color (one pass color)" -msgstr "" - -#: ../backend/umax.c:240 -#, no-c-format -msgid "Ignore calibration" -msgstr "" - -#: ../backend/umax.c:5733 -#, no-c-format -msgid "Disable pre focus" -msgstr "" - -#: ../backend/umax.c:5734 -#, no-c-format -msgid "Do not calibrate focus" -msgstr "" - -#: ../backend/umax.c:5745 -#, no-c-format -msgid "Manual pre focus" -msgstr "" - -#: ../backend/umax.c:5757 -#, no-c-format -msgid "Fix focus position" -msgstr "" - -#: ../backend/umax.c:5769 -#, no-c-format -msgid "Lens calibration in doc position" -msgstr "" - -#: ../backend/umax.c:5770 -#, no-c-format -msgid "Calibrate lens focus in document position" -msgstr "" - -#: ../backend/umax.c:5781 -#, no-c-format -msgid "Holder focus position 0mm" -msgstr "" - -#: ../backend/umax.c:5782 -#, no-c-format -msgid "Use 0mm holder focus position instead of 0.6mm" -msgstr "" - -#: ../backend/umax.c:5885 -#, no-c-format -msgid "Calibration mode" -msgstr "" - -#: ../backend/umax.c:5886 -#, no-c-format -msgid "Define calibration mode" -msgstr "" - -#: ../backend/umax_pp.c:640 -#, no-c-format -msgid "Sets lamp on/off" -msgstr "" - -#: ../backend/umax_pp.c:649 -#, no-c-format -msgid "UTA on" -msgstr "" - -#: ../backend/umax_pp.c:650 -#, no-c-format -msgid "Sets UTA on/off" -msgstr "" - -#: ../backend/umax_pp.c:771 -#, no-c-format -msgid "Offset" -msgstr "" - -#: ../backend/umax_pp.c:773 -#, no-c-format -msgid "Color channels offset settings" -msgstr "" - -#: ../backend/umax_pp.c:780 -#, no-c-format -msgid "Gray offset" -msgstr "" - -#: ../backend/umax_pp.c:781 -#, no-c-format -msgid "Sets gray channel offset" -msgstr "" - -#: ../backend/umax_pp.c:793 -#, no-c-format -msgid "Sets red channel offset" -msgstr "" - -#: ../backend/umax_pp.c:805 -#, no-c-format -msgid "Sets green channel offset" -msgstr "" - -#: ../backend/umax_pp.c:817 -#, no-c-format -msgid "Sets blue channel offset" -msgstr "" diff --git a/po/sv.po b/po/sv.po index 16658f7..40a956b 100644 --- a/po/sv.po +++ b/po/sv.po @@ -4701,7 +4701,7 @@ msgstr "Handbildläsarsimulering" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulera en handbildläsare. Handbildläsare vet oftast inte bildhöjden i " "förväg. I stället returnerar de en höjd som är -1. Om denna inställning " @@ -5043,7 +5043,7 @@ msgstr "Handbildläsarsimulering" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulera en handbildläsare. Handbildläsare vet oftast inte bildhöjden i " diff --git a/po/uk.po b/po/uk.po index 22fb63b..fd54a1f 100644 --- a/po/uk.po +++ b/po/uk.po @@ -4775,7 +4775,7 @@ msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" 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." +"option allows one to test whether a frontend can handle this correctly." msgstr "" "Імітує ручний Ñканер. Ручні Ñканери чаÑто попередньо не отримують даних " "щодо виÑоти зображеннÑ. ЗаміÑÑ‚ÑŒ цього, вони повертають виÑоту рівну -1. " @@ -5164,7 +5164,7 @@ msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" 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 " +"allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Імітує ручний Ñканер. Ручні Ñканери попередньо не отримують даних щодо " diff --git a/sanei/sanei_usb.c b/sanei/sanei_usb.c index 7401658..f210d4f 100644 --- a/sanei/sanei_usb.c +++ b/sanei/sanei_usb.c @@ -154,6 +154,7 @@ typedef struct SANE_Int control_in_ep; SANE_Int control_out_ep; SANE_Int interface_nr; + SANE_Int alt_setting; SANE_Int missing; #ifdef HAVE_LIBUSB usb_dev_handle *libusb_handle; @@ -460,8 +461,6 @@ sanei_libusb_strerror (int errcode) default: return "Unknown libusb-1.0 error code"; } - - return "Unknown libusb-1.0 error code"; } #endif /* HAVE_LIBUSB_1_0 */ @@ -635,6 +634,7 @@ static void usbcall_scan_devices(void) device.product = pDevDesc->idProduct; device.method = sanei_usb_method_usbcalls; device.interface_nr = interface; + device.alt_setting = 0; DBG (4, "%s: found usbcalls device (0x%04x/0x%04x) as device number %s\n", __func__, pDevDesc->idVendor, pDevDesc->idProduct,device.devname); store_device(device); @@ -821,7 +821,7 @@ static void libusb_scan_devices(void) "scanner (%d/%d)\n", __func__, dev->descriptor.idVendor, dev->descriptor.idProduct, interface, dev->descriptor.bDeviceClass, - dev->config[0].interface[interface].altsetting != 0 + dev->config[0].interface[interface].num_altsetting != 0 ? dev->config[0].interface[interface].altsetting[0]. bInterfaceClass : -1); } @@ -845,6 +845,7 @@ static void libusb_scan_devices(void) device.product = dev->descriptor.idProduct; device.method = sanei_usb_method_libusb; device.interface_nr = interface; + device.alt_setting = 0; DBG (4, "%s: found libusb device (0x%04x/0x%04x) interface " "%d at %s\n", __func__, @@ -991,7 +992,7 @@ static void libusb_scan_devices(void) "%s: device 0x%04x/0x%04x, interface %d " "doesn't look like a scanner (%d/%d)\n", __func__, vid, pid, interface, desc.bDeviceClass, - (config0->interface[interface].altsetting != 0) + (config0->interface[interface].num_altsetting != 0) ? config0->interface[interface].altsetting[0].bInterfaceClass : -1); } @@ -1018,6 +1019,7 @@ static void libusb_scan_devices(void) device.product = pid; device.method = sanei_usb_method_libusb; device.interface_nr = interface; + device.alt_setting = 0; DBG (4, "%s: found libusb-1.0 device (0x%04x/0x%04x) interface " "%d at %s\n", __func__, @@ -1381,30 +1383,32 @@ sanei_usb_open (SANE_String_Const devname, SANE_Int * dn) "configuration (%d), choosing first config (%d)\n", dev->descriptor.bNumConfigurations, dev->config[0].bConfigurationValue); - } - result = usb_set_configuration (devices[devcount].libusb_handle, - dev->config[0].bConfigurationValue); - if (result < 0) - { - SANE_Status status = SANE_STATUS_INVAL; - DBG (1, "sanei_usb_open: libusb complained: %s\n", usb_strerror ()); - if (errno == EPERM || errno == EACCES) - { - DBG (1, "Make sure you run as root or set appropriate " - "permissions\n"); - status = SANE_STATUS_ACCESS_DENIED; - } - else if (errno == EBUSY) - { - DBG (3, "Maybe the kernel scanner driver or usblp claims the " - "interface? Ignoring this error...\n"); - status = SANE_STATUS_GOOD; - } - if (status != SANE_STATUS_GOOD) + result = usb_set_configuration (devices[devcount].libusb_handle, + dev->config[0].bConfigurationValue); + if (result < 0) { - usb_close (devices[devcount].libusb_handle); - return status; + SANE_Status status = SANE_STATUS_INVAL; + + DBG (1, "sanei_usb_open: libusb complained: %s\n", + usb_strerror ()); + if (errno == EPERM || errno == EACCES) + { + DBG (1, "Make sure you run as root or set appropriate " + "permissions\n"); + status = SANE_STATUS_ACCESS_DENIED; + } + else if (errno == EBUSY) + { + DBG (3, "Maybe the kernel scanner driver or usblp claims the " + "interface? Ignoring this error...\n"); + status = SANE_STATUS_GOOD; + } + if (status != SANE_STATUS_GOOD) + { + usb_close (devices[devcount].libusb_handle); + return status; + } } } @@ -1445,13 +1449,13 @@ sanei_usb_open (SANE_String_Const devname, SANE_Int * dn) DBG (5, "sanei_usb_open: interface nr: %d\n", i); DBG (5, "sanei_usb_open: alt_setting nr: %d\n", a); - /* Start by interfaces found in sanei_usb_init */ - if (c == 0 && i != devices[devcount].interface_nr) - { - DBG (5, "sanei_usb_open: interface %d not detected as " - "a scanner by sanei_usb_init, ignoring.\n", i); - continue; - } + /* Start by interfaces found in sanei_usb_init */ + if (c == 0 && i != devices[devcount].interface_nr) + { + DBG (5, "sanei_usb_open: interface %d not detected as " + "a scanner by sanei_usb_init, ignoring.\n", i); + continue; + } interface = &dev->config[c].interface[i].altsetting[a]; @@ -1672,37 +1676,40 @@ sanei_usb_open (SANE_String_Const devname, SANE_Int * dn) "configuration (%d), choosing first config (%d)\n", desc.bNumConfigurations, config0->bConfigurationValue); - } - result = libusb_set_configuration (devices[devcount].lu_handle, - config0->bConfigurationValue); - libusb_free_config_descriptor (config0); + result = 0; + if (config != config0->bConfigurationValue) + result = libusb_set_configuration (devices[devcount].lu_handle, + config0->bConfigurationValue); - if (result < 0) - { - SANE_Status status = SANE_STATUS_INVAL; - - DBG (1, "sanei_usb_open: libusb complained: %s\n", - sanei_libusb_strerror (result)); - if (result == LIBUSB_ERROR_ACCESS) - { - DBG (1, "Make sure you run as root or set appropriate " - "permissions\n"); - status = SANE_STATUS_ACCESS_DENIED; - } - else if (result == LIBUSB_ERROR_BUSY) + if (result < 0) { - DBG (3, "Maybe the kernel scanner driver or usblp claims the " - "interface? Ignoring this error...\n"); - status = SANE_STATUS_GOOD; - } + SANE_Status status = SANE_STATUS_INVAL; - if (status != SANE_STATUS_GOOD) - { - libusb_close (devices[devcount].lu_handle); - return status; + DBG (1, "sanei_usb_open: libusb complained: %s\n", + sanei_libusb_strerror (result)); + if (result == LIBUSB_ERROR_ACCESS) + { + DBG (1, "Make sure you run as root or set appropriate " + "permissions\n"); + status = SANE_STATUS_ACCESS_DENIED; + } + else if (result == LIBUSB_ERROR_BUSY) + { + DBG (3, "Maybe the kernel scanner driver or usblp claims " + "the interface? Ignoring this error...\n"); + status = SANE_STATUS_GOOD; + } + + if (status != SANE_STATUS_GOOD) + { + libusb_close (devices[devcount].lu_handle); + libusb_free_config_descriptor (config0); + return status; + } } } + libusb_free_config_descriptor (config0); /* Claim the interface */ result = libusb_claim_interface (devices[devcount].lu_handle, @@ -2128,22 +2135,24 @@ sanei_usb_close (SANE_Int dn) else #ifdef HAVE_LIBUSB { -#if 0 - /* Should only be done in case of a stall */ - usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep); - usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_out_ep); - usb_clear_halt (devices[dn].libusb_handle, devices[dn].iso_in_ep); - /* be careful, we don't know if we are in DATA0 stage now */ - usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_in_ep); - usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_out_ep); - usb_resetep (devices[dn].libusb_handle, devices[dn].iso_in_ep); -#endif /* 0 */ + /* This call seems to be required by Linux xhci driver + * even though it should be a no-op. Without it, the + * host or driver does not reset it's data toggle bit. + * We intentionally ignore the return val */ + sanei_usb_set_altinterface (dn, devices[dn].alt_setting); + usb_release_interface (devices[dn].libusb_handle, devices[dn].interface_nr); usb_close (devices[dn].libusb_handle); } #elif defined(HAVE_LIBUSB_1_0) { + /* This call seems to be required by Linux xhci driver + * even though it should be a no-op. Without it, the + * host or driver does not reset it's data toggle bit. + * We intentionally ignore the return val */ + sanei_usb_set_altinterface (dn, devices[dn].alt_setting); + libusb_release_interface (devices[dn].lu_handle, devices[dn].interface_nr); libusb_close (devices[dn].lu_handle); @@ -2168,7 +2177,6 @@ sanei_usb_set_timeout (SANE_Int timeout) SANE_Status sanei_usb_clear_halt (SANE_Int dn) { -#ifdef HAVE_LIBUSB int ret; if (dn >= device_number || dn < 0) @@ -2177,6 +2185,14 @@ sanei_usb_clear_halt (SANE_Int dn) return SANE_STATUS_INVAL; } +#ifdef HAVE_LIBUSB + + /* This call seems to be required by Linux xhci driver + * even though it should be a no-op. Without it, the + * host or driver does not send the clear to the device. + * We intentionally ignore the return val */ + sanei_usb_set_altinterface (dn, devices[dn].alt_setting); + ret = usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep); if (ret){ DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret); @@ -2189,18 +2205,13 @@ sanei_usb_clear_halt (SANE_Int dn) return SANE_STATUS_INVAL; } - /* be careful, we don't know if we are in DATA0 stage now - ret = usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_in_ep); - ret = usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_out_ep); - */ #elif defined(HAVE_LIBUSB_1_0) - int ret; - if (dn >= device_number || dn < 0) - { - DBG (1, "sanei_usb_clear_halt: dn >= device number || dn < 0\n"); - return SANE_STATUS_INVAL; - } + /* This call seems to be required by Linux xhci driver + * even though it should be a no-op. Without it, the + * host or driver does not send the clear to the device. + * We intentionally ignore the return val */ + sanei_usb_set_altinterface (dn, devices[dn].alt_setting); ret = libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep); if (ret){ @@ -3038,6 +3049,8 @@ sanei_usb_set_altinterface (SANE_Int dn, SANE_Int alternate) DBG (5, "sanei_usb_set_altinterface: alternate = %d\n", alternate); + devices[dn].alt_setting = alternate; + if (devices[dn].method == sanei_usb_method_scanner_driver) { #if defined(__linux__) diff --git a/testsuite/sanei/sanei_config_test.c b/testsuite/sanei/sanei_config_test.c index 9a07f2b..3d1f5af 100644 --- a/testsuite/sanei/sanei_config_test.c +++ b/testsuite/sanei/sanei_config_test.c @@ -895,6 +895,9 @@ sanei_config_suite (void) int main (void) { + /* set up config dir for local conf files */ + putenv("SANE_CONFIG_DIR=.:/"); + /* run suites */ sanei_config_suite (); diff --git a/testsuite/tools/Makefile.am b/testsuite/tools/Makefile.am index 178041b..1664ecb 100644 --- a/testsuite/tools/Makefile.am +++ b/testsuite/tools/Makefile.am @@ -32,7 +32,7 @@ check.local: do \ echo "PASS: sane-desc -m $$mode -s $(srcdir)/data"; \ $(SANEDESC) -m $$mode -s $(srcdir)/data >$$mode.res ;\ - if ! diff --ignore-matching-lines="..:..:.. 20[0-9][0-9]" $(srcdir)/data/$$mode.ref $$mode.res ; \ + if ! diff --ignore-matching-lines="..:..:.. 20[0-9][0-9]" --ignore-matching-lines="sane-backends 1.0...git" $(srcdir)/data/$$mode.ref $$mode.res ; \ then \ echo "**** File generated for $$mode mode is different from reference" ;\ exit 1 ;\ diff --git a/testsuite/tools/Makefile.in b/testsuite/tools/Makefile.in index 6f735d0..e02349b 100644 --- a/testsuite/tools/Makefile.in +++ b/testsuite/tools/Makefile.in @@ -503,7 +503,7 @@ check.local: do \ echo "PASS: sane-desc -m $$mode -s $(srcdir)/data"; \ $(SANEDESC) -m $$mode -s $(srcdir)/data >$$mode.res ;\ - if ! diff --ignore-matching-lines="..:..:.. 20[0-9][0-9]" $(srcdir)/data/$$mode.ref $$mode.res ; \ + if ! diff --ignore-matching-lines="..:..:.. 20[0-9][0-9]" --ignore-matching-lines="sane-backends 1.0...git" $(srcdir)/data/$$mode.ref $$mode.res ; \ then \ echo "**** File generated for $$mode mode is different from reference" ;\ exit 1 ;\ diff --git a/testsuite/tools/data/hwdb.ref b/testsuite/tools/data/hwdb.ref index 357aaa8..909ac46 100644 --- a/testsuite/tools/data/hwdb.ref +++ b/testsuite/tools/data/hwdb.ref @@ -1,5 +1,5 @@ # This file was automatically created based on description files (*.desc) -# by sane-desc 3.5 from sane-backends 1.0.24git on Thu Aug 1 18:50:19 2013 +# by sane-desc 3.5 from sane-backends 1.0.25git on Tue Dec 3 15:24:46 2013 # # hwdb file for supported USB devices # @@ -14,637 +14,637 @@ # the sane-devel mailing list (sane-devel@lists.alioth.debian.org). # # Hewlett-Packard ScanJet 4100C -usb:v03F0p03F0* +usb:v03F0p0101* libsane_matched=yes # Hewlett-Packard ScanJet 4200C | Hewlett-Packard ScanJet 4200Cxi | Hewlett-Packard ScanJet 4200Cse -usb:v03F0p03F0* +usb:v03F0p0105* libsane_matched=yes # Hewlett-Packard ScanJet 6200C | Hewlett-Packard ScanJet 6250C -usb:v03F0p03F0* +usb:v03F0p0201* libsane_matched=yes # Hewlett-Packard ScanJet 3300c -usb:v03F0p03F0* +usb:v03F0p0205* libsane_matched=yes # Hewlett-Packard ScanJet 4300c -usb:v03F0p03F0* +usb:v03F0p0305* libsane_matched=yes # Hewlett-Packard ScanJet 5200C -usb:v03F0p03F0* +usb:v03F0p0401* libsane_matched=yes # Hewlett-Packard ScanJet 3400c -usb:v03F0p03F0* +usb:v03F0p0405* libsane_matched=yes # Hewlett-Packard ScanJet 2100C -usb:v03F0p03F0* +usb:v03F0p0505* libsane_matched=yes # Hewlett-Packard ScanJet 6300C | Hewlett-Packard ScanJet 6350C | Hewlett-Packard ScanJet 6390C -usb:v03F0p03F0* +usb:v03F0p0601* libsane_matched=yes # Hewlett-Packard ScanJet 2200C -usb:v03F0p03F0* +usb:v03F0p0605* libsane_matched=yes # Hewlett-Packard ScanJet 5300C | Hewlett-Packard ScanJet 5370C -usb:v03F0p03F0* +usb:v03F0p0701* libsane_matched=yes # Hewlett-Packard scanjet 4400c -usb:v03F0p03F0* +usb:v03F0p0705* libsane_matched=yes # Hewlett-Packard ScanJet 7400c | Hewlett-Packard ScanJet 7450c | Hewlett-Packard ScanJet 7490c -usb:v03F0p03F0* +usb:v03F0p0801* libsane_matched=yes # Hewlett-Packard scanjet 4470c -usb:v03F0p03F0* +usb:v03F0p0805* libsane_matched=yes # Hewlett-Packard ScanJet 2300C -usb:v03F0p03F0* +usb:v03F0p0901* libsane_matched=yes # Hewlett-Packard ScanJet 2400C | Hewlett-Packard ScanJet G2410 -usb:v03F0p03F0* +usb:v03F0p0A01* libsane_matched=yes # Hewlett-Packard ScanJet 8200 | Hewlett-Packard ScanJet 8250 | Hewlett-Packard ScanJet 8290 -usb:v03F0p03F0* +usb:v03F0p0B01* libsane_matched=yes # Hewlett-Packard ScanJet 5400c -usb:v03F0p03F0* +usb:v03F0p1005* libsane_matched=yes # Hewlett-Packard ScanJet 5470c -usb:v03F0p03F0* +usb:v03F0p1105* libsane_matched=yes # Hewlett-Packard ScanJet 4500C | Hewlett-Packard ScanJet 5550C -usb:v03F0p03F0* +usb:v03F0p1205* libsane_matched=yes # Hewlett-Packard ScanJet 4570C | Hewlett-Packard ScanJet 5500C -usb:v03F0p03F0* +usb:v03F0p1305* libsane_matched=yes # Hewlett-Packard ScanJet 3670C | Hewlett-Packard ScanJet 3690C -usb:v03F0p03F0* +usb:v03F0p1405* libsane_matched=yes # Hewlett-Packard ScanJet 5590 -usb:v03F0p03F0* +usb:v03F0p1705* libsane_matched=yes # Hewlett-Packard ScanJet 7650 -usb:v03F0p03F0* +usb:v03F0p1805* libsane_matched=yes # Hewlett-Packard ScanJet 4850C -usb:v03F0p03F0* +usb:v03F0p1B05* libsane_matched=yes # Hewlett-Packard ScanJet 3530C | Hewlett-Packard ScanJet 3570C -usb:v03F0p03F0* +usb:v03F0p2005* libsane_matched=yes # Hewlett-Packard ScanJet 3500C -usb:v03F0p03F0* +usb:v03F0p2205* libsane_matched=yes # Hewlett-Packard ScanJet 3970c -usb:v03F0p03F0* +usb:v03F0p2305* libsane_matched=yes # Hewlett-Packard ScanJet 4070 Photosmart -usb:v03F0p03F0* +usb:v03F0p2405* libsane_matched=yes # Hewlett-Packard ScanJet 3800 -usb:v03F0p03F0* +usb:v03F0p2605* libsane_matched=yes # Hewlett-Packard ScanJet G2710 -usb:v03F0p03F0* +usb:v03F0p2805* libsane_matched=yes # Hewlett-Packard ScanJet 8300 | Hewlett-Packard ScanJet 8350 | Hewlett-Packard ScanJet 8390 -usb:v03F0p03F0* +usb:v03F0p3805* libsane_matched=yes # Hewlett-Packard ScanJet 8270 -usb:v03F0p03F0* +usb:v03F0p3905* libsane_matched=yes # Hewlett-Packard LaserJet M1005 MFP -usb:v03F0p03F0* +usb:v03F0p3B17* libsane_matched=yes # Hewlett-Packard ScanJet 4370 -usb:v03F0p03F0* +usb:v03F0p4105* libsane_matched=yes # Hewlett-Packard ScanJet G3010 -usb:v03F0p03F0* +usb:v03F0p4205* libsane_matched=yes # Hewlett-Packard ScanJet G3110 -usb:v03F0p03F0* +usb:v03F0p4305* libsane_matched=yes # Hewlett-Packard ScanJet G4010 -usb:v03F0p03F0* +usb:v03F0p4505* libsane_matched=yes # Hewlett-Packard ScanJet G4050 -usb:v03F0p03F0* +usb:v03F0p4605* libsane_matched=yes # Hewlett-Packard ScanJet N6310 -usb:v03F0p03F0* +usb:v03F0p4705* libsane_matched=yes # Hewlett-Packard LaserJet M1120 MFP -usb:v03F0p03F0* +usb:v03F0p5617* libsane_matched=yes # Hewlett-Packard LaserJet M1120n MFP -usb:v03F0p03F0* +usb:v03F0p5717* libsane_matched=yes # Mustek BearPaw 1200 -usb:v0400p0400* +usb:v0400p1000* libsane_matched=yes # Mustek BearPaw 1200 | Mustek BearPaw 2400 -usb:v0400p0400* +usb:v0400p1001* libsane_matched=yes # Kodak ESP 5100 -usb:v040Ap040A* +usb:v040Ap4025* libsane_matched=yes # Kodak ESP 5300 -usb:v040Ap040A* +usb:v040Ap4026* libsane_matched=yes # Kodak ESP 5500 -usb:v040Ap040A* +usb:v040Ap4027* libsane_matched=yes # Kodak ESP 5000 -usb:v040Ap040A* +usb:v040Ap4028* libsane_matched=yes # Kodak ESP 3300 -usb:v040Ap040A* +usb:v040Ap4031* libsane_matched=yes # Kodak ESP 5 -usb:v040Ap040A* +usb:v040Ap4032* libsane_matched=yes # Kodak ESP 7 -usb:v040Ap040A* +usb:v040Ap403E* libsane_matched=yes # Kodak ESP 9 -usb:v040Ap040A* +usb:v040Ap403F* libsane_matched=yes # Kodak ESP 5200 -usb:v040Ap040A* +usb:v040Ap4041* libsane_matched=yes # Kodak ESP 3200 -usb:v040Ap040A* +usb:v040Ap4043* libsane_matched=yes # Kodak ESP 4100 -usb:v040Ap040A* +usb:v040Ap4053* libsane_matched=yes # Kodak ESP 6100 -usb:v040Ap040A* +usb:v040Ap4054* libsane_matched=yes # Kodak ESP 7200 -usb:v040Ap040A* +usb:v040Ap4056* libsane_matched=yes # Kodak ESP C110 -usb:v040Ap040A* +usb:v040Ap4057* libsane_matched=yes # Kodak ESP C115 -usb:v040Ap040A* +usb:v040Ap4058* libsane_matched=yes # Kodak ESP 2150 -usb:v040Ap040A* +usb:v040Ap4059* libsane_matched=yes # Kodak ESP C310 -usb:v040Ap040A* +usb:v040Ap405D* libsane_matched=yes # Kodak ESP C315 -usb:v040Ap040A* +usb:v040Ap405E* libsane_matched=yes # Advent AW10 -usb:v040Ap040A* +usb:v040Ap4060* libsane_matched=yes # Kodak Hero Office 6.1 -usb:v040Ap040A* +usb:v040Ap4062* libsane_matched=yes # Kodak Hero 7.1 -usb:v040Ap040A* +usb:v040Ap4063* libsane_matched=yes # Kodak Hero 5.1 -usb:v040Ap040A* +usb:v040Ap4064* libsane_matched=yes # Kodak ESP 9200 -usb:v040Ap040A* +usb:v040Ap4065* libsane_matched=yes # Kodak ESP 2170 -usb:v040Ap040A* +usb:v040Ap4066* libsane_matched=yes # Kodak Hero 9.1 -usb:v040Ap040A* +usb:v040Ap4067* libsane_matched=yes # Kodak Hero 3.1 -usb:v040Ap040A* +usb:v040Ap406D* libsane_matched=yes # Kodak i30 -usb:v040Ap040A* +usb:v040Ap6001* libsane_matched=yes # Kodak i40 -usb:v040Ap040A* +usb:v040Ap6002* libsane_matched=yes # Kodak i50 | Kodak i55 -usb:v040Ap040A* +usb:v040Ap6003* libsane_matched=yes # Kodak i60 | Kodak i65 -usb:v040Ap040A* +usb:v040Ap6004* libsane_matched=yes # Kodak i80 -usb:v040Ap040A* +usb:v040Ap6005* libsane_matched=yes # Creative WebCam Go Mini -usb:v041Ep041E* +usb:v041Ep4007* libsane_matched=yes # Lexmark X70 | Lexmark X73 -usb:v043Dp043D* +usb:v043Dp002D* libsane_matched=yes # Lexmark X74 -usb:v043Dp043D* +usb:v043Dp0060* libsane_matched=yes # Lexmark X1110 | Lexmark X1130 | Lexmark X1140 # Lexmark X1150 | Lexmark X1170 | Lexmark X1180 # Lexmark X1185 | Lexmark X1195 -usb:v043Dp043D* +usb:v043Dp007C* libsane_matched=yes # Lexmark X12xx -usb:v043Dp043D* +usb:v043Dp007D* libsane_matched=yes # Genius ColorPage HR6 V1 -usb:v0458p0458* +usb:v0458p2004* libsane_matched=yes # Genius Colorpage HR6 V2 -usb:v0458p0458* +usb:v0458p2007* libsane_matched=yes # Genius Colorpage HR6 V2 -usb:v0458p0458* +usb:v0458p2008* libsane_matched=yes # Genius Colorpage HR6A -usb:v0458p0458* +usb:v0458p2009* libsane_matched=yes # Genius Colorpage Vivid3x | Genius Colorpage Vivid3 V2 -usb:v0458p0458* +usb:v0458p2011* libsane_matched=yes # Genius Colorpage HR7 -usb:v0458p0458* +usb:v0458p2013* libsane_matched=yes # Genius Colorpage Vivid4 -usb:v0458p0458* +usb:v0458p2014* libsane_matched=yes # Genius Colorpage HR7LE -usb:v0458p0458* +usb:v0458p2015* libsane_matched=yes # Genius Colorpage HR6X -usb:v0458p0458* +usb:v0458p2016* libsane_matched=yes # Genius Colorpage Vivid3xe -usb:v0458p0458* +usb:v0458p2017* libsane_matched=yes # Genius Colorpage Vivid4xe -usb:v0458p0458* +usb:v0458p201A* libsane_matched=yes # Genius Colorpage Vivid4x -usb:v0458p0458* +usb:v0458p201B* libsane_matched=yes # Genius Colorpage Vivid 1200 X -usb:v0458p0458* +usb:v0458p201D* libsane_matched=yes # Genius ColorPage Slim 1200 -usb:v0458p0458* +usb:v0458p201E* libsane_matched=yes # Genius Colorpage Vivid 1200 XE -usb:v0458p0458* +usb:v0458p201F* libsane_matched=yes # Genius Colorpage SF600 -usb:v0458p0458* +usb:v0458p2021* libsane_matched=yes # Medion/Lifetec/Tevion/Cytron MD5345 | Medion/Lifetec/Tevion/Cytron MD6228 | Medion/Lifetec/Tevion/Cytron MD6471 -usb:v0461p0461* +usb:v0461p0377* libsane_matched=yes # Xerox 2400 Onetouch -usb:v0461p0461* +usb:v0461p038B* libsane_matched=yes # Trust Office Scan USB 19200 -usb:v047Bp047B* +usb:v047Bp1000* libsane_matched=yes # Hewlett-Packard ScanJet 4300c/Silitek -usb:v047Bp047B* +usb:v047Bp1002* libsane_matched=yes # Kyocera FS-1016MFP -usb:v0482p0482* +usb:v0482p0335* libsane_matched=yes # Compaq S4-100 -usb:v049Fp049F* +usb:v049Fp001A* libsane_matched=yes # Benq (Acer) 310U -usb:v04A5p04A5* +usb:v04A5p1A20* libsane_matched=yes # Benq (Acer) 620U -usb:v04A5p04A5* +usb:v04A5p1A2A* libsane_matched=yes # Benq (Acer) 320U | Benq (Acer) 340U | Mitsubishi Diamondview 648UT -usb:v04A5p04A5* +usb:v04A5p2022* libsane_matched=yes # Benq (Acer) 620UT -usb:v04A5p04A5* +usb:v04A5p2040* libsane_matched=yes # Benq (Acer) 640U | Guillemot / Hercules Maxi Scan A4 USB 640U | Guillemot / Hercules Maxi A4 36 bit -usb:v04A5p04A5* +usb:v04A5p2060* libsane_matched=yes # Benq (Acer) 640bu -usb:v04A5p04A5* +usb:v04A5p207E* libsane_matched=yes # Benq (Acer) 3300 | Benq (Acer) 4300 | Mitsubishi Diamondview 650U -usb:v04A5p04A5* +usb:v04A5p20B0* libsane_matched=yes # Benq (Acer) 640BT -usb:v04A5p04A5* +usb:v04A5p20BE* libsane_matched=yes # Benq (Acer) 1240 -usb:v04A5p04A5* +usb:v04A5p20C0* libsane_matched=yes # Benq (Acer) 3300 | Benq (Acer) 4300 | Guillemot / Hercules Scan@home Touch 1248 (USB) -usb:v04A5p04A5* +usb:v04A5p20DE* libsane_matched=yes # Benq (Acer) 5000 -usb:v04A5p04A5* +usb:v04A5p20F8* libsane_matched=yes # Benq (Acer) 5000E | Benq (Acer) 5000U -usb:v04A5p04A5* +usb:v04A5p20FC* libsane_matched=yes # Benq (Acer) 5300 -usb:v04A5p04A5* +usb:v04A5p20FE* libsane_matched=yes # Benq (Acer) 5150 | Benq (Acer) 5250 -usb:v04A5p04A5* +usb:v04A5p2137* libsane_matched=yes # BenQ 5550 -usb:v04A5p04A5* +usb:v04A5p2211* libsane_matched=yes # Visioneer Visioneer OneTouch 7100 -usb:v04A7p04A7* +usb:v04A7p0229* libsane_matched=yes # Visioneer 9650 -usb:v04A7p04A7* +usb:v04A7p0390* libsane_matched=yes # Visioneer 9320 -usb:v04A7p04A7* +usb:v04A7p0420* libsane_matched=yes # Visioneer 9450 -usb:v04A7p04A7* +usb:v04A7p0421* libsane_matched=yes # Visioneer 9550 -usb:v04A7p04A7* +usb:v04A7p0422* libsane_matched=yes # Visioneer 9750 -usb:v04A7p04A7* +usb:v04A7p0423* libsane_matched=yes # Visioneer Strobe XP 450 -usb:v04A7p04A7* +usb:v04A7p0424* libsane_matched=yes # Visioneer Strobe XP 200 -usb:v04A7p04A7* +usb:v04A7p0426* libsane_matched=yes # Visioneer Strobe XP 100 -usb:v04A7p04A7* +usb:v04A7p0427* libsane_matched=yes # Visioneer OneTouch 7300 -usb:v04A7p04A7* +usb:v04A7p0444* libsane_matched=yes # Xerox DocuMate510 -usb:v04A7p04A7* +usb:v04A7p0446* libsane_matched=yes # Xerox DocuMate520 -usb:v04A7p04A7* +usb:v04A7p0447* libsane_matched=yes # Xerox DocuMate250 -usb:v04A7p04A7* +usb:v04A7p0448* libsane_matched=yes # Xerox DocuMate252 -usb:v04A7p04A7* +usb:v04A7p0449* libsane_matched=yes # Xerox DocuMate262 -usb:v04A7p04A7* +usb:v04A7p044C* libsane_matched=yes # Visioneer Strobe XP 300 -usb:v04A7p04A7* +usb:v04A7p0474* libsane_matched=yes # Xerox DocuMate272 -usb:v04A7p04A7* +usb:v04A7p0475* libsane_matched=yes # Xerox DocuMate232 -usb:v04A7p04A7* +usb:v04A7p0476* libsane_matched=yes # Xerox DocuMate152 -usb:v04A7p04A7* +usb:v04A7p0477* libsane_matched=yes # Xerox DocuMate752 -usb:v04A7p04A7* +usb:v04A7p0478* libsane_matched=yes # Visioneer Strobe XP 470 -usb:v04A7p04A7* +usb:v04A7p0479* libsane_matched=yes # Visioneer 9450-G -usb:v04A7p04A7* +usb:v04A7p047A* libsane_matched=yes # Visioneer 9650-G -usb:v04A7p04A7* +usb:v04A7p047B* libsane_matched=yes # Xerox DocuMate510-G -usb:v04A7p04A7* +usb:v04A7p047C* libsane_matched=yes # Xerox DocuMate252-G -usb:v04A7p04A7* +usb:v04A7p048C* libsane_matched=yes # Xerox DocuMate262-G -usb:v04A7p04A7* +usb:v04A7p048D* libsane_matched=yes # Xerox DocuMate272-G -usb:v04A7p04A7* +usb:v04A7p048E* libsane_matched=yes # Visioneer Strobe XP 470-G | Visioneer Patriot 470 -usb:v04A7p04A7* +usb:v04A7p048F* libsane_matched=yes # Xerox DocuMate250-G -usb:v04A7p04A7* +usb:v04A7p0490* libsane_matched=yes # Visioneer Strobe XP 450-G -usb:v04A7p04A7* +usb:v04A7p0491* libsane_matched=yes # Xerox DocuMate520-G -usb:v04A7p04A7* +usb:v04A7p0492* libsane_matched=yes # Visioneer 9750-G -usb:v04A7p04A7* +usb:v04A7p0493* libsane_matched=yes # Visioneer Roadwarrior -usb:v04A7p04A7* +usb:v04A7p0494* libsane_matched=yes # Xerox DocuMate512 -usb:v04A7p04A7* +usb:v04A7p0495* libsane_matched=yes # Visioneer Patriot 430 -usb:v04A7p04A7* +usb:v04A7p0497* libsane_matched=yes # Visioneer Patriot 680 | Xerox DocuMate632 -usb:v04A7p04A7* +usb:v04A7p0498* libsane_matched=yes # Visioneer Patriot 780 -usb:v04A7p04A7* +usb:v04A7p0499* libsane_matched=yes # Xerox DocuMate752 -usb:v04A7p04A7* +usb:v04A7p049A* libsane_matched=yes # Visioneer Strobe XP 100,r3 -usb:v04A7p04A7* +usb:v04A7p049B* libsane_matched=yes # Xerox DocuMate150 -usb:v04A7p04A7* +usb:v04A7p049C* libsane_matched=yes # Xerox DocuMate162 -usb:v04A7p04A7* +usb:v04A7p049D* libsane_matched=yes # Xerox DocuMate262i @@ -652,1519 +652,1519 @@ usb:v04A7p04A7* libsane_matched=yes # Xerox Travel Scanner 100 -usb:v04A7p04A7* +usb:v04A7p04AC* libsane_matched=yes # Canon DR-2080C -usb:v04A9p04A9* +usb:v04A9p1601* libsane_matched=yes # Canon CR-180 | Canon CR-180II -usb:v04A9p04A9* +usb:v04A9p1602* libsane_matched=yes # Canon DR-9080C -usb:v04A9p04A9* +usb:v04A9p1603* libsane_matched=yes # Canon DR-7080C -usb:v04A9p04A9* +usb:v04A9p1604* libsane_matched=yes # Canon DR-5010C -usb:v04A9p04A9* +usb:v04A9p1606* libsane_matched=yes # Canon DR-6080 -usb:v04A9p04A9* +usb:v04A9p1607* libsane_matched=yes # Canon DR-2580C -usb:v04A9p04A9* +usb:v04A9p1608* libsane_matched=yes # Canon DR-3080CII -usb:v04A9p04A9* +usb:v04A9p1609* libsane_matched=yes # Canon DR-2050C | Canon DR-2050SP -usb:v04A9p04A9* +usb:v04A9p160A* libsane_matched=yes # Canon DR-7580 -usb:v04A9p04A9* +usb:v04A9p160B* libsane_matched=yes # Canon PIXMA MP750 -usb:v04A9p04A9* +usb:v04A9p1706* libsane_matched=yes # Canon PIXMA MP780 | Canon PIXMA MP790 -usb:v04A9p04A9* +usb:v04A9p1707* libsane_matched=yes # Canon PIXMA MP760 | Canon PIXMA MP770 -usb:v04A9p04A9* +usb:v04A9p1708* libsane_matched=yes # Canon PIXMA MP150 -usb:v04A9p04A9* +usb:v04A9p1709* libsane_matched=yes # Canon PIXMA MP170 -usb:v04A9p04A9* +usb:v04A9p170A* libsane_matched=yes # Canon PIXMA MP450 -usb:v04A9p04A9* +usb:v04A9p170B* libsane_matched=yes # Canon PIXMA MP500 -usb:v04A9p04A9* +usb:v04A9p170C* libsane_matched=yes # Canon PIXMA MP800 -usb:v04A9p04A9* +usb:v04A9p170D* libsane_matched=yes # Canon PIXMA MP800R -usb:v04A9p04A9* +usb:v04A9p170E* libsane_matched=yes # Canon PIXMA MP530 -usb:v04A9p04A9* +usb:v04A9p1712* libsane_matched=yes # Canon PIXMA MP830 -usb:v04A9p04A9* +usb:v04A9p1713* libsane_matched=yes # Canon PIXMA MP160 -usb:v04A9p04A9* +usb:v04A9p1714* libsane_matched=yes # Canon PIXMA MP180 -usb:v04A9p04A9* +usb:v04A9p1715* libsane_matched=yes # Canon PIXMA MP460 -usb:v04A9p04A9* +usb:v04A9p1716* libsane_matched=yes # Canon PIXMA MP510 -usb:v04A9p04A9* +usb:v04A9p1717* libsane_matched=yes # Canon PIXMA MP600 -usb:v04A9p04A9* +usb:v04A9p1718* libsane_matched=yes # Canon PIXMA MP600R -usb:v04A9p04A9* +usb:v04A9p1719* libsane_matched=yes # Canon PIXMA MP810 -usb:v04A9p04A9* +usb:v04A9p171A* libsane_matched=yes # Canon PIXMA MP960 -usb:v04A9p04A9* +usb:v04A9p171B* libsane_matched=yes # Canon PIXMA MX7600 -usb:v04A9p04A9* +usb:v04A9p171C* libsane_matched=yes # Canon PIXMA MP210 -usb:v04A9p04A9* +usb:v04A9p1721* libsane_matched=yes # Canon PIXMA MP220 -usb:v04A9p04A9* +usb:v04A9p1722* libsane_matched=yes # Canon PIXMA MP470 -usb:v04A9p04A9* +usb:v04A9p1723* libsane_matched=yes # Canon PIXMA MP520 -usb:v04A9p04A9* +usb:v04A9p1724* libsane_matched=yes # Canon PIXMA MP610 -usb:v04A9p04A9* +usb:v04A9p1725* libsane_matched=yes # Canon PIXMA MP970 -usb:v04A9p04A9* +usb:v04A9p1726* libsane_matched=yes # Canon PIXMA MX300 -usb:v04A9p04A9* +usb:v04A9p1727* libsane_matched=yes # Canon PIXMA MX310 -usb:v04A9p04A9* +usb:v04A9p1728* libsane_matched=yes # Canon PIXMA MX700 -usb:v04A9p04A9* +usb:v04A9p1729* libsane_matched=yes # Canon PIXMA MP140 -usb:v04A9p04A9* +usb:v04A9p172B* libsane_matched=yes # Canon PIXMA MX850 -usb:v04A9p04A9* +usb:v04A9p172C* libsane_matched=yes # Canon PIXMA MP980 -usb:v04A9p04A9* +usb:v04A9p172D* libsane_matched=yes # Canon PIXMA MP630 -usb:v04A9p04A9* +usb:v04A9p172E* libsane_matched=yes # Canon PIXMA MP620 -usb:v04A9p04A9* +usb:v04A9p172F* libsane_matched=yes # Canon PIXMA MP540 -usb:v04A9p04A9* +usb:v04A9p1730* libsane_matched=yes # Canon PIXMA MP480 -usb:v04A9p04A9* +usb:v04A9p1731* libsane_matched=yes # Canon PIXMA MP240 -usb:v04A9p04A9* +usb:v04A9p1732* libsane_matched=yes # Canon PIXMA MP260 -usb:v04A9p04A9* +usb:v04A9p1733* libsane_matched=yes # Canon PIXMA MP190 -usb:v04A9p04A9* +usb:v04A9p1734* libsane_matched=yes # Canon PIXMA MX860 -usb:v04A9p04A9* +usb:v04A9p1735* libsane_matched=yes # Canon PIXMA MX320 -usb:v04A9p04A9* +usb:v04A9p1736* libsane_matched=yes # Canon PIXMA MX330 -usb:v04A9p04A9* +usb:v04A9p1737* libsane_matched=yes # Canon PIXMA MP250 -usb:v04A9p04A9* +usb:v04A9p173A* libsane_matched=yes # Canon PIXMA MP270 -usb:v04A9p04A9* +usb:v04A9p173B* libsane_matched=yes # Canon PIXMA MP490 -usb:v04A9p04A9* +usb:v04A9p173C* libsane_matched=yes # Canon PIXMA MP550 -usb:v04A9p04A9* +usb:v04A9p173D* libsane_matched=yes # Canon PIXMA MP560 -usb:v04A9p04A9* +usb:v04A9p173E* libsane_matched=yes # Canon PIXMA MP640 -usb:v04A9p04A9* +usb:v04A9p173F* libsane_matched=yes # Canon PIXMA MP990 -usb:v04A9p04A9* +usb:v04A9p1740* libsane_matched=yes # Canon PIXMA MX340 -usb:v04A9p04A9* +usb:v04A9p1741* libsane_matched=yes # Canon PIXMA MX350 -usb:v04A9p04A9* +usb:v04A9p1742* libsane_matched=yes # Canon PIXMA MX870 -usb:v04A9p04A9* +usb:v04A9p1743* libsane_matched=yes # Canon PIXMA MP280 -usb:v04A9p04A9* +usb:v04A9p1746* libsane_matched=yes # Canon PIXMA MP495 -usb:v04A9p04A9* +usb:v04A9p1747* libsane_matched=yes # Canon PIXMA MG5100 Series -usb:v04A9p04A9* +usb:v04A9p1748* libsane_matched=yes # Canon PIXMA MG5200 Series -usb:v04A9p04A9* +usb:v04A9p1749* libsane_matched=yes # Canon PIXMA MG6100 Series -usb:v04A9p04A9* +usb:v04A9p174A* libsane_matched=yes # Canon PIXMA MG8100 Series -usb:v04A9p04A9* +usb:v04A9p174B* libsane_matched=yes # Canon PIXMA MX360 -usb:v04A9p04A9* +usb:v04A9p174D* libsane_matched=yes # Canon PIXMA MX410 -usb:v04A9p04A9* +usb:v04A9p174E* libsane_matched=yes # Canon PIXMA MX420 -usb:v04A9p04A9* +usb:v04A9p174F* libsane_matched=yes # Canon PIXMA MX880 Series | Canon PIXMA MX882 | Canon PIXMA MX885 -usb:v04A9p04A9* +usb:v04A9p1750* libsane_matched=yes # Canon PIXMA MG2100 Series -usb:v04A9p04A9* +usb:v04A9p1751* libsane_matched=yes # Canon PIXMA MG3100 Series -usb:v04A9p04A9* +usb:v04A9p1752* libsane_matched=yes # Canon PIXMA MG4100 Series -usb:v04A9p04A9* +usb:v04A9p1753* libsane_matched=yes # Canon PIXMA MG5300 Series -usb:v04A9p04A9* +usb:v04A9p1754* libsane_matched=yes # Canon PIXMA MG6200 Series -usb:v04A9p04A9* +usb:v04A9p1755* libsane_matched=yes # Canon PIXMA MG8200 Series -usb:v04A9p04A9* +usb:v04A9p1756* libsane_matched=yes # Canon PIXMA MP493 -usb:v04A9p04A9* +usb:v04A9p1757* libsane_matched=yes # Canon PIXMA E500 -usb:v04A9p04A9* +usb:v04A9p1758* libsane_matched=yes # Canon PIXMA MX370 Series -usb:v04A9p04A9* +usb:v04A9p1759* libsane_matched=yes # Canon PIXMA E600 -usb:v04A9p04A9* +usb:v04A9p175A* libsane_matched=yes # Canon PIXMA MX430 Series -usb:v04A9p04A9* +usb:v04A9p175B* libsane_matched=yes # Canon PIXMA MX510 Series -usb:v04A9p04A9* +usb:v04A9p175C* libsane_matched=yes # Canon PIXMA MX710 Series -usb:v04A9p04A9* +usb:v04A9p175D* libsane_matched=yes # Canon PIXMA MX890 Series -usb:v04A9p04A9* +usb:v04A9p175E* libsane_matched=yes # Canon PIXMA MP230 -usb:v04A9p04A9* +usb:v04A9p175F* libsane_matched=yes # Canon PIXMA MG2200 Series -usb:v04A9p04A9* +usb:v04A9p1760* libsane_matched=yes # Canon PIXMA E510 -usb:v04A9p04A9* +usb:v04A9p1761* libsane_matched=yes # Canon PIXMA MG3200 Series -usb:v04A9p04A9* +usb:v04A9p1762* libsane_matched=yes # Canon PIXMA MG4200 Series -usb:v04A9p04A9* +usb:v04A9p1763* libsane_matched=yes # Canon PIXMA MG5400 Series -usb:v04A9p04A9* +usb:v04A9p1764* libsane_matched=yes # Canon PIXMA MG6300 Series -usb:v04A9p04A9* +usb:v04A9p1765* libsane_matched=yes # Canon PIXMA MX390 Series -usb:v04A9p04A9* +usb:v04A9p1766* libsane_matched=yes # Canon PIXMA E610 -usb:v04A9p04A9* +usb:v04A9p1767* libsane_matched=yes # Canon PIXMA MX450 Series -usb:v04A9p04A9* +usb:v04A9p1768* libsane_matched=yes # Canon PIXMA MX520 Series -usb:v04A9p04A9* +usb:v04A9p1769* libsane_matched=yes # Canon PIXMA MX720 Series -usb:v04A9p04A9* +usb:v04A9p176A* libsane_matched=yes # Canon PIXMA MX920 Series -usb:v04A9p04A9* +usb:v04A9p176B* libsane_matched=yes # Canon CanoScan 8800F -usb:v04A9p04A9* +usb:v04A9p1901* libsane_matched=yes # Canon CanoScan LiDE 100 -usb:v04A9p04A9* +usb:v04A9p1904* libsane_matched=yes # Canon CanoScan LiDE 200 -usb:v04A9p04A9* +usb:v04A9p1905* libsane_matched=yes # Canon CanoScan 700F -usb:v04A9p04A9* +usb:v04A9p1907* libsane_matched=yes # Canon CanoScan 9000F -usb:v04A9p04A9* +usb:v04A9p1908* libsane_matched=yes # Canon CanoScan LiDE 110 -usb:v04A9p04A9* +usb:v04A9p1909* libsane_matched=yes # Canon CanoScan LiDE 210 -usb:v04A9p04A9* +usb:v04A9p190A* libsane_matched=yes # Canon CanoScan 9000F Mark II -usb:v04A9p04A9* +usb:v04A9p190D* libsane_matched=yes # Canon CanoScan fb630u | Canon CanoScan fb636u -usb:v04A9p04A9* +usb:v04A9p2204* libsane_matched=yes # Canon CanoScan N650U/N656U -usb:v04A9p04A9* +usb:v04A9p2206* libsane_matched=yes # Canon CanoScan N1220U -usb:v04A9p04A9* +usb:v04A9p2207* libsane_matched=yes # Canon CanoScan D660U -usb:v04A9p04A9* +usb:v04A9p2208* libsane_matched=yes # Canon CanoScan N670U/N676U/LiDE20 -usb:v04A9p04A9* +usb:v04A9p220D* libsane_matched=yes # Canon CanoScan N1240U/LiDE30 -usb:v04A9p04A9* +usb:v04A9p220E* libsane_matched=yes # Canon CanoScan LiDE 35 | Canon CanoScan LiDE 40 | Canon CanoScan LiDE 50 -usb:v04A9p04A9* +usb:v04A9p2213* libsane_matched=yes # Canon CanoScan LiDE 60 -usb:v04A9p04A9* +usb:v04A9p221C* libsane_matched=yes # Canon CanoScan LiDE25 -usb:v04A9p04A9* +usb:v04A9p2220* libsane_matched=yes # Canon DR-1210C -usb:v04A9p04A9* +usb:v04A9p2222* libsane_matched=yes # Canon PIXMA MP730 -usb:v04A9p04A9* +usb:v04A9p262F* libsane_matched=yes # Canon PIXMA MP700 -usb:v04A9p04A9* +usb:v04A9p2630* libsane_matched=yes # Canon PIXMA MP360 -usb:v04A9p04A9* +usb:v04A9p263C* libsane_matched=yes # Canon PIXMA MP370 -usb:v04A9p04A9* +usb:v04A9p263D* libsane_matched=yes # Canon PIXMA MP390 -usb:v04A9p04A9* +usb:v04A9p263E* libsane_matched=yes # Canon PIXMA MP375R -usb:v04A9p04A9* +usb:v04A9p263F* libsane_matched=yes # Canon PIXMA MP740 -usb:v04A9p04A9* +usb:v04A9p264C* libsane_matched=yes # Canon PIXMA MP710 -usb:v04A9p04A9* +usb:v04A9p264D* libsane_matched=yes # Canon imageCLASS MF5630 -usb:v04A9p04A9* +usb:v04A9p264E* libsane_matched=yes # Canon laserBase MF5650 -usb:v04A9p04A9* +usb:v04A9p264F* libsane_matched=yes # Canon imageCLASS MF8170c -usb:v04A9p04A9* +usb:v04A9p2659* libsane_matched=yes # Canon imageCLASS MF5730 -usb:v04A9p04A9* +usb:v04A9p265D* libsane_matched=yes # Canon imageCLASS MF5750 -usb:v04A9p04A9* +usb:v04A9p265E* libsane_matched=yes # Canon imageCLASS MF5770 -usb:v04A9p04A9* +usb:v04A9p265F* libsane_matched=yes # Canon imageCLASS MF3110 -usb:v04A9p04A9* +usb:v04A9p2660* libsane_matched=yes # Canon imageCLASS MF3240 -usb:v04A9p04A9* +usb:v04A9p2684* libsane_matched=yes # Canon imageCLASS MF6500 series | Canon imageCLASS MF6550 -usb:v04A9p04A9* +usb:v04A9p2686* libsane_matched=yes # Canon imageCLASS MF4120 | Canon imageCLASS MF4122 | Canon imageCLASS MF4140 # Canon imageCLASS MF4150 -usb:v04A9p04A9* +usb:v04A9p26A3* libsane_matched=yes # Canon imageCLASS MF4660 | Canon imageCLASS MF4690 -usb:v04A9p04A9* +usb:v04A9p26B0* libsane_matched=yes # Canon imageCLASS MF4010 | Canon imageCLASS MF4018 -usb:v04A9p04A9* +usb:v04A9p26B4* libsane_matched=yes # Canon imageCLASS MF4270 -usb:v04A9p04A9* +usb:v04A9p26B5* libsane_matched=yes # Canon imageRUNNER 1020/1024/1025 -usb:v04A9p04A9* +usb:v04A9p26E6* libsane_matched=yes # Canon imageCLASS MF4370dn | Canon imageCLASS MF4380dn -usb:v04A9p04A9* +usb:v04A9p26EC* libsane_matched=yes # Canon imageCLASS D480 -usb:v04A9p04A9* +usb:v04A9p26ED* libsane_matched=yes # Canon I-SENSYS MF4320d | Canon I-SENSYS MF4330d | Canon imageCLASS MF4350d -usb:v04A9p04A9* +usb:v04A9p26EE* libsane_matched=yes # Canon imageCLASS D420 -usb:v04A9p04A9* +usb:v04A9p26EF* libsane_matched=yes # Canon i-SENSYS MF5880dn -usb:v04A9p04A9* +usb:v04A9p26F9* libsane_matched=yes # Canon i-SENSYS MF6680dn -usb:v04A9p04A9* +usb:v04A9p26FA* libsane_matched=yes # Canon imageCLASS MF8030 -usb:v04A9p04A9* +usb:v04A9p2707* libsane_matched=yes # Canon i-SENSYS MF4550d -usb:v04A9p04A9* +usb:v04A9p2736* libsane_matched=yes # Canon imageCLASS MF4410 | Canon imageCLASS MF4430 -usb:v04A9p04A9* +usb:v04A9p2737* libsane_matched=yes # Canon i-SENSYS MF3010 -usb:v04A9p04A9* +usb:v04A9p2759* libsane_matched=yes # Nikon LS 40 ED | Nikon LS 40 ED | Nikon Coolspan IV -usb:v04B0p04B0* +usb:v04B0p4000* libsane_matched=yes # Nikon LS 50 ED | Nikon Coolscan V ED | Nikon LS 50 ED # Nikon Coolscan V ED -usb:v04B0p04B0* +usb:v04B0p4001* libsane_matched=yes # Nikon Super Coolscan LS-5000 ED | Nikon Super Coolscan LS-5000 ED -usb:v04B0p04B0* +usb:v04B0p4002* libsane_matched=yes # Epson Perfection 636U | Epson GT-7000U | Epson Perfection 636U -usb:v04B8p04B8* +usb:v04B8p0101* libsane_matched=yes # Epson Perfection 610 | Epson GT-6600U | Epson Perfection 610 -usb:v04B8p04B8* +usb:v04B8p0103* libsane_matched=yes # Epson Perfection 1200U | Epson Perfection 1200Photo | Epson GT-7600U # Epson GT-7600UF | Epson Perfection 1200U | Epson Perfection 1200U PHOTO -usb:v04B8p04B8* +usb:v04B8p0104* libsane_matched=yes # Epson Stylus Scan 2000 -usb:v04B8p04B8* +usb:v04B8p0105* libsane_matched=yes # Epson Stylus Scan 2500 -usb:v04B8p04B8* +usb:v04B8p0106* libsane_matched=yes # Epson Expression 1600 | Epson ES-2000 | Epson Expression 1600 -usb:v04B8p04B8* +usb:v04B8p0107* libsane_matched=yes # Epson ES-8500 | Epson Expression 1640XL -usb:v04B8p04B8* +usb:v04B8p0109* libsane_matched=yes # Epson Perfection 1640 | Epson GT-8700 | Epson GT-8700F # Epson Perfection 1640SU | Epson Perfection 1640SU PHOTO -usb:v04B8p04B8* +usb:v04B8p010A* libsane_matched=yes # Epson Perfection 1240 | Epson GT-7700U | Epson Perfection 1240U -usb:v04B8p04B8* +usb:v04B8p010B* libsane_matched=yes # Epson Perfection 640 | Epson GT-6700U | Epson Perfection 640U -usb:v04B8p04B8* +usb:v04B8p010C* libsane_matched=yes # Epson Expression 1680 | Epson ES-2200 | Epson Expression 1680 -usb:v04B8p04B8* +usb:v04B8p010E* libsane_matched=yes # Epson Perfection 1250 | Epson Perfection 1250Photo -usb:v04B8p04B8* +usb:v04B8p010F* libsane_matched=yes # Epson Perfection 1650 | Epson GT-8200U | Epson GT-8200UF # Epson Perfection 1650 | Epson Perfection 1650 PHOTO -usb:v04B8p04B8* +usb:v04B8p0110* libsane_matched=yes # Epson Perfection 2450 | Epson GT-9700F | Epson Perfection 2450 PHOTO -usb:v04B8p04B8* +usb:v04B8p0112* libsane_matched=yes # Epson Perfection 660 -usb:v04B8p04B8* +usb:v04B8p0114* libsane_matched=yes # Epson Perfection 2400 | Epson GT-9300UF | Epson Perfection 2400 PHOTO -usb:v04B8p04B8* +usb:v04B8p011B* libsane_matched=yes # Epson Perfection 3200 | Epson GT-9800F | Epson Perfection 3200 PHOTO -usb:v04B8p04B8* +usb:v04B8p011C* libsane_matched=yes # Epson Perfection 1260 | Epson Perfection 1260Photo -usb:v04B8p04B8* +usb:v04B8p011D* libsane_matched=yes # Epson Perfection 1660 | Epson GT-8300UF | Epson Perfection 1660 PHOTO -usb:v04B8p04B8* +usb:v04B8p011E* libsane_matched=yes # Epson Perfection 1670 -usb:v04B8p04B8* +usb:v04B8p011F* libsane_matched=yes # Epson Perfection 1270 -usb:v04B8p04B8* +usb:v04B8p0120* libsane_matched=yes # Epson Perfection 2480 | Epson Perfection 2580 -usb:v04B8p04B8* +usb:v04B8p0121* libsane_matched=yes # Epson Perfection 3490 | Epson Perfection 3590 -usb:v04B8p04B8* +usb:v04B8p0122* libsane_matched=yes # Epson ES-7000H | Epson GT-15000 -usb:v04B8p04B8* +usb:v04B8p0126* libsane_matched=yes # Epson Perfection 4870 | Epson GT-X700 | Epson Perfection 4870 PHOTO -usb:v04B8p04B8* +usb:v04B8p0128* libsane_matched=yes # Epson ES-10000G | Epson Expression 10000XL -usb:v04B8p04B8* +usb:v04B8p0129* libsane_matched=yes # Epson Perfection 4990 | Epson GT-X800 | Epson Perfection 4990 PHOTO -usb:v04B8p04B8* +usb:v04B8p012A* libsane_matched=yes # Epson ES-H300 | Epson GT-2500 -usb:v04B8p04B8* +usb:v04B8p012B* libsane_matched=yes # Epson V700 | Epson V750 | Epson GT-X900 # Epson Perfection V700 Photo | Epson Perfection V750 Photo -usb:v04B8p04B8* +usb:v04B8p012C* libsane_matched=yes # Epson GT-X970 -usb:v04B8p04B8* +usb:v04B8p0135* libsane_matched=yes # Epson CX-5200 | Epson CX-5400 | Epson CC-600PX # Epson Stylus CX5100 | Epson Stylus CX5200 -usb:v04B8p04B8* +usb:v04B8p0801* libsane_matched=yes # Epson CX-3200 | Epson CC-570L | Epson Stylus CX3100 # Epson Stylus CX3200 -usb:v04B8p04B8* +usb:v04B8p0802* libsane_matched=yes # Epson CX-6300 | Epson CX-6400 | Epson Stylus CX6300 # Epson Stylus CX6400 -usb:v04B8p04B8* +usb:v04B8p0805* libsane_matched=yes # Epson RX-600 | Epson PM-A850 | Epson Stylus Photo RX600 -usb:v04B8p04B8* +usb:v04B8p0806* libsane_matched=yes # Epson RX-500 | Epson Stylus Photo RX500 | Epson Stylus Photo RX510 -usb:v04B8p04B8* +usb:v04B8p0807* libsane_matched=yes # Epson CX-5400 | Epson Stylus CX5300 | Epson Stylus CX5400 -usb:v04B8p04B8* +usb:v04B8p0808* libsane_matched=yes # Epson Stylus CX-1500 -usb:v04B8p04B8* +usb:v04B8p080C* libsane_matched=yes # Epson CX-4600 | Epson Stylus CX4500 | Epson Stylus CX4600 -usb:v04B8p04B8* +usb:v04B8p080D* libsane_matched=yes # Epson CX-3600 | Epson CX-3650 | Epson PX-A550 # Epson Stylus CX3500 | Epson Stylus CX3600 | Epson Stylus CX3650 -usb:v04B8p04B8* +usb:v04B8p080E* libsane_matched=yes # Epson RX-425 | Epson Stylus Photo RX420 | Epson Stylus Photo RX425 # Epson Stylus Photo RX430 -usb:v04B8p04B8* +usb:v04B8p080F* libsane_matched=yes # Epson RX-700 | Epson PM-A900 | Epson Stylus Photo RX700 -usb:v04B8p04B8* +usb:v04B8p0810* libsane_matched=yes # Epson RX-620 | Epson PM-A870 | Epson Stylus Photo RX620 # Epson Stylus Photo RX630 -usb:v04B8p04B8* +usb:v04B8p0811* libsane_matched=yes # Epson CX-6500 | Epson CX-6600 | Epson Stylus CX6500 # Epson Stylus CX6600 -usb:v04B8p04B8* +usb:v04B8p0813* libsane_matched=yes # Epson PM-A700 -usb:v04B8p04B8* +usb:v04B8p0814* libsane_matched=yes # Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson AcuLaser CX11 # Epson AcuLaser CX11NF | Epson LP-A500 -usb:v04B8p04B8* +usb:v04B8p0815* libsane_matched=yes # Epson LP-M5500 | Epson LP-M5500F -usb:v04B8p04B8* +usb:v04B8p0817* libsane_matched=yes # Epson DX-3850 | Epson CX-3700 | Epson CX-3800 # Epson DX-3800 | Epson Stylus CX3700 | Epson Stylus CX3800 # Epson Stylus DX3800 -usb:v04B8p04B8* +usb:v04B8p0818* libsane_matched=yes # Epson CX-4800 | Epson PX-A650 | Epson Stylus CX4700 # Epson Stylus CX4800 | Epson Stylus DX4800 | Epson Stylus DX4850 -usb:v04B8p04B8* +usb:v04B8p0819* libsane_matched=yes # Epson PM-A750 | Epson Stylus Photo RX520 | Epson Stylus Photo RX530 -usb:v04B8p04B8* +usb:v04B8p081A* libsane_matched=yes # Epson PM-A890 | Epson Stylus Photo RX640 | Epson Stylus Photo RX650 -usb:v04B8p04B8* +usb:v04B8p081C* libsane_matched=yes # Epson PM-A950 -usb:v04B8p04B8* +usb:v04B8p081D* libsane_matched=yes # Epson Stylus CX7700 | Epson Stylus CX7800 -usb:v04B8p04B8* +usb:v04B8p081F* libsane_matched=yes # Epson CX-4200 | Epson Stylus CX4100 | Epson Stylus CX4200 # Epson Stylus DX4200 -usb:v04B8p04B8* +usb:v04B8p0820* libsane_matched=yes # Epson PM-A820 | Epson Stylus Photo RX560 | Epson Stylus Photo RX580 # Epson Stylus Photo RX590 -usb:v04B8p04B8* +usb:v04B8p0827* libsane_matched=yes # Epson PM-A970 -usb:v04B8p04B8* +usb:v04B8p0828* libsane_matched=yes # Epson PM-T990 -usb:v04B8p04B8* +usb:v04B8p0829* libsane_matched=yes # Epson PM-A920 -usb:v04B8p04B8* +usb:v04B8p082A* libsane_matched=yes # Epson CX-5000 | Epson DX-5000 | Epson DX-5050 # Epson Stylus CX4900 | Epson Stylus CX5000 | Epson Stylus DX5000 -usb:v04B8p04B8* +usb:v04B8p082B* libsane_matched=yes # Epson DX-6000 | Epson PX-A720 | Epson Stylus CX5900 # Epson Stylus CX6000 | Epson Stylus DX6000 -usb:v04B8p04B8* +usb:v04B8p082E* libsane_matched=yes # Epson DX-4050 | Epson PX-A620 | Epson Stylus CX3900 # Epson Stylus DX4000 -usb:v04B8p04B8* +usb:v04B8p082F* libsane_matched=yes # Epson ME 200 | Epson Stylus CX2800 | Epson Stylus CX2900 -usb:v04B8p04B8* +usb:v04B8p0830* libsane_matched=yes # Epson LP-M5600 -usb:v04B8p04B8* +usb:v04B8p0833* libsane_matched=yes # Epson LP-M6000 -usb:v04B8p04B8* +usb:v04B8p0834* libsane_matched=yes # Epson AcuLaser CX21 -usb:v04B8p04B8* +usb:v04B8p0835* libsane_matched=yes # Epson PM-T960 -usb:v04B8p04B8* +usb:v04B8p0836* libsane_matched=yes # Epson PM-A940 | Epson Stylus Photo RX680 | Epson Stylus Photo RX685 # Epson Stylus Photo RX690 -usb:v04B8p04B8* +usb:v04B8p0837* libsane_matched=yes # Epson DX-7400 | Epson PX-A640 | Epson Stylus CX7300 # Epson Stylus CX7400 | Epson Stylus DX7400 -usb:v04B8p04B8* +usb:v04B8p0838* libsane_matched=yes # Epson PX-A740 | Epson Stylus CX8300 | Epson Stylus CX8400 # Epson Stylus DX8400 -usb:v04B8p04B8* +usb:v04B8p0839* libsane_matched=yes # Epson PX-FA700 | Epson Stylus CX9300F | Epson Stylus CX9400Fax # Epson Stylus DX9400F -usb:v04B8p04B8* +usb:v04B8p083A* libsane_matched=yes # Epson PM-A840 | Epson PM-A840S | Epson Stylus Photo RX585 # Epson Stylus Photo RX595 | Epson Stylus Photo RX610 -usb:v04B8p04B8* +usb:v04B8p083C* libsane_matched=yes # Epson ME 300 | Epson PX-401A | Epson Stylus NX100 # Epson Stylus SX100 | Epson Stylus TX100 -usb:v04B8p04B8* +usb:v04B8p0841* libsane_matched=yes # Epson LP-M5000 -usb:v04B8p04B8* +usb:v04B8p0843* libsane_matched=yes # Epson Artisan 800 | Epson EP-901A | Epson EP-901F # Epson Stylus Photo PX800FW | Epson Stylus Photo TX800FW -usb:v04B8p04B8* +usb:v04B8p0844* libsane_matched=yes # Epson Artisan 700 | Epson EP-801A | Epson Stylus Photo PX700W # Epson Stylus Photo TX700W -usb:v04B8p04B8* +usb:v04B8p0846* libsane_matched=yes # Epson ME Office 700FW | Epson PX-601F | Epson Stylus Office BX600FW # Epson Stylus Office TX600FW | Epson Stylus SX600FW | Epson WorkForce 600 -usb:v04B8p04B8* +usb:v04B8p0847* libsane_matched=yes # Epson ME Office 600F | Epson Stylus Office BX300F | Epson Stylus Office TX300F # Epson Stylus NX300 -usb:v04B8p04B8* +usb:v04B8p0848* libsane_matched=yes # Epson Stylus NX200 | Epson Stylus SX200 | Epson Stylus SX205 # Epson Stylus TX200 | Epson Stylus TX203 | Epson Stylus TX209 -usb:v04B8p04B8* +usb:v04B8p0849* libsane_matched=yes # Epson PX-501A | Epson Stylus NX400 | Epson Stylus SX400 # Epson Stylus SX405 | Epson Stylus TX400 -usb:v04B8p04B8* +usb:v04B8p084A* libsane_matched=yes # Epson WorkForce 500 -usb:v04B8p04B8* +usb:v04B8p084C* libsane_matched=yes # Epson PX-402A | Epson Stylus NX110 Series | Epson Stylus SX110 Series # Epson Stylus TX110 Series -usb:v04B8p04B8* +usb:v04B8p084D* libsane_matched=yes # Epson ME OFFICE 510 | Epson Stylus NX210 Series | Epson Stylus SX210 Series # Epson Stylus TX210 Series -usb:v04B8p04B8* +usb:v04B8p084F* libsane_matched=yes # Epson Stylus NX410 Series | Epson Stylus SX410 Series | Epson Stylus TX410 Series -usb:v04B8p04B8* +usb:v04B8p0851* libsane_matched=yes # Epson ME OFFICE 650FN Series | Epson Stylus Office BX310FN Series | Epson Stylus Office TX510FN Series # Epson WorkForce 310 Series -usb:v04B8p04B8* +usb:v04B8p0854* libsane_matched=yes # Epson PX-502A | Epson Stylus NX510 Series | Epson Stylus SX510W Series # Epson Stylus TX550W Series -usb:v04B8p04B8* +usb:v04B8p0856* libsane_matched=yes # Epson Stylus SX125 -usb:v04B8p04B8* +usb:v04B8p085C* libsane_matched=yes # Fujitsu fi-4010CU -usb:v04C5p04C5* +usb:v04C5p1029* libsane_matched=yes # Fujitsu fi-4120C -usb:v04C5p04C5* +usb:v04C5p1041* libsane_matched=yes # Fujitsu fi-4220C -usb:v04C5p04C5* +usb:v04C5p1042* libsane_matched=yes # Fujitsu fi-4530C -usb:v04C5p04C5* +usb:v04C5p1078* libsane_matched=yes # Fujitsu fi-5750C -usb:v04C5p04C5* +usb:v04C5p1095* libsane_matched=yes # Fujitsu fi-5110EOX/2 -usb:v04C5p04C5* +usb:v04C5p1096* libsane_matched=yes # Fujitsu fi-5110C -usb:v04C5p04C5* +usb:v04C5p1097* libsane_matched=yes # Fujitsu fi-5650C -usb:v04C5p04C5* +usb:v04C5p10AD* libsane_matched=yes # Fujitsu fi-4120C2 -usb:v04C5p04C5* +usb:v04C5p10AE* libsane_matched=yes # Fujitsu fi-4220C2 -usb:v04C5p04C5* +usb:v04C5p10AF* libsane_matched=yes # Fujitsu fi-60F -usb:v04C5p04C5* +usb:v04C5p10C7* libsane_matched=yes # Fujitsu fi-4340C -usb:v04C5p04C5* +usb:v04C5p10CF* libsane_matched=yes # Fujitsu fi-5120C -usb:v04C5p04C5* +usb:v04C5p10E0* libsane_matched=yes # Fujitsu fi-5220C -usb:v04C5p04C5* +usb:v04C5p10E1* libsane_matched=yes # Fujitsu fi-5530C -usb:v04C5p04C5* +usb:v04C5p10E2* libsane_matched=yes # Fujitsu fi-5110EOX3 -usb:v04C5p04C5* +usb:v04C5p10E6* libsane_matched=yes # Fujitsu fi-5900C -usb:v04C5p04C5* +usb:v04C5p10E7* libsane_matched=yes # Fujitsu fi-5015C -usb:v04C5p04C5* +usb:v04C5p10EF* libsane_matched=yes # Fujitsu fi-5110EOXM -usb:v04C5p04C5* +usb:v04C5p10F2* libsane_matched=yes # Fujitsu ScanSnap S500 -usb:v04C5p04C5* +usb:v04C5p10FE* libsane_matched=yes # Fujitsu ScanSnap S500M -usb:v04C5p04C5* +usb:v04C5p1135* libsane_matched=yes # Fujitsu fi-5530C2 -usb:v04C5p04C5* +usb:v04C5p114A* libsane_matched=yes # Fujitsu fi-6140 -usb:v04C5p04C5* +usb:v04C5p114D* libsane_matched=yes # Fujitsu fi-6240 -usb:v04C5p04C5* +usb:v04C5p114E* libsane_matched=yes # Fujitsu fi-6130 -usb:v04C5p04C5* +usb:v04C5p114F* libsane_matched=yes # Fujitsu fi-6230 -usb:v04C5p04C5* +usb:v04C5p1150* libsane_matched=yes # Fujitsu ScanSnap S510 -usb:v04C5p04C5* +usb:v04C5p1155* libsane_matched=yes # Fujitsu ScanSnap S300 -usb:v04C5p04C5* +usb:v04C5p1156* libsane_matched=yes # Fujitsu ScanSnap S510M -usb:v04C5p04C5* +usb:v04C5p116F* libsane_matched=yes # Fujitsu fi-6770 -usb:v04C5p04C5* +usb:v04C5p1174* libsane_matched=yes # Fujitsu fi-6770A -usb:v04C5p04C5* +usb:v04C5p1175* libsane_matched=yes # Fujitsu fi-6670 -usb:v04C5p04C5* +usb:v04C5p1176* libsane_matched=yes # Fujitsu fi-6670A -usb:v04C5p04C5* +usb:v04C5p1177* libsane_matched=yes # Fujitsu fi-6750S -usb:v04C5p04C5* +usb:v04C5p1178* libsane_matched=yes # Fujitsu ScanSnap S300M -usb:v04C5p04C5* +usb:v04C5p117F* libsane_matched=yes # Fujitsu fi-6800 -usb:v04C5p04C5* +usb:v04C5p119D* libsane_matched=yes # Fujitsu fi-6800-CGA -usb:v04C5p04C5* +usb:v04C5p119E* libsane_matched=yes # Fujitsu ScanSnap S1500 | Fujitsu ScanSnap S1500M -usb:v04C5p04C5* +usb:v04C5p11A2* libsane_matched=yes # Fujitsu ScanSnap S1300 -usb:v04C5p04C5* +usb:v04C5p11ED* libsane_matched=yes # Fujitsu fi-6140Z -usb:v04C5p04C5* +usb:v04C5p11F1* libsane_matched=yes # Fujitsu fi-6240Z -usb:v04C5p04C5* +usb:v04C5p11F2* libsane_matched=yes # Fujitsu fi-6130Z -usb:v04C5p04C5* +usb:v04C5p11F3* libsane_matched=yes # Fujitsu fi-6230Z -usb:v04C5p04C5* +usb:v04C5p11F4* libsane_matched=yes # Fujitsu fi-6110 -usb:v04C5p04C5* +usb:v04C5p11FC* libsane_matched=yes # Fujitsu fi-5950 -usb:v04C5p04C5* +usb:v04C5p1213* libsane_matched=yes # Fujitsu ScanSnap iX500 -usb:v04C5p04C5* +usb:v04C5p132B* libsane_matched=yes # Konica e-mini -usb:v04C8p04C8* +usb:v04C8p0722* libsane_matched=yes # Panasonic KV-S2026C -usb:v04DAp04DA* +usb:v04DAp1000* libsane_matched=yes # Panasonic KV-S2046C -usb:v04DAp04DA* +usb:v04DAp1001* libsane_matched=yes # Panasonic KV-S1025C -usb:v04DAp04DA* +usb:v04DAp1006* libsane_matched=yes # Panasonic KV-S1020C -usb:v04DAp04DA* +usb:v04DAp1007* libsane_matched=yes # Panasonic KV-S2048C -usb:v04DAp04DA* +usb:v04DAp1009* libsane_matched=yes # Panasonic KV-S2028C -usb:v04DAp04DA* +usb:v04DAp100A* libsane_matched=yes # Panasonic KV-S4085C -usb:v04DAp04DA* +usb:v04DAp100C* libsane_matched=yes # Panasonic KV-S4065C -usb:v04DAp04DA* +usb:v04DAp100D* libsane_matched=yes # Panasonic KV-S7075C -usb:v04DAp04DA* +usb:v04DAp100E* libsane_matched=yes # Panasonic KV-SS080 -usb:v04DAp04DA* +usb:v04DAp100F* libsane_matched=yes # Panasonic KV-S1045C -usb:v04DAp04DA* +usb:v04DAp1010* libsane_matched=yes # Samsung SCX-4x16 -usb:v04E8p04E8* +usb:v04E8p3409* libsane_matched=yes # Samsung SCX-6x20 -usb:v04E8p04E8* +usb:v04E8p340D* libsane_matched=yes # Samsung MFP-560 -usb:v04E8p04E8* +usb:v04E8p340E* libsane_matched=yes # Samsung MFP-750 -usb:v04E8p04E8* +usb:v04E8p340F* libsane_matched=yes # Samsung SCX-4x20 -usb:v04E8p04E8* +usb:v04E8p3412* libsane_matched=yes # Samsung SCX-4100 -usb:v04E8p04E8* +usb:v04E8p3413* libsane_matched=yes # Samsung SCX-4x21 -usb:v04E8p04E8* +usb:v04E8p3419* libsane_matched=yes # Samsung SCX-5x30 -usb:v04E8p04E8* +usb:v04E8p341A* libsane_matched=yes # Samsung SCX-4200 -usb:v04E8p04E8* +usb:v04E8p341B* libsane_matched=yes # Samsung CLX-3160 -usb:v04E8p04E8* +usb:v04E8p341C* libsane_matched=yes # Samsung SCX-6x22 -usb:v04E8p04E8* +usb:v04E8p341D* libsane_matched=yes # Samsung SCX4725 | Samsung SCX4725-FN -usb:v04E8p04E8* +usb:v04E8p341F* libsane_matched=yes # Samsung SCX-6x45 -usb:v04E8p04E8* +usb:v04E8p3420* libsane_matched=yes # Samsung CLX-8380 -usb:v04E8p04E8* +usb:v04E8p3421* libsane_matched=yes # Samsung CLX-2160 -usb:v04E8p04E8* +usb:v04E8p3425* libsane_matched=yes # Samsung SCX-4500 -usb:v04E8p04E8* +usb:v04E8p3426* libsane_matched=yes # Samsung CLX-6200 -usb:v04E8p04E8* +usb:v04E8p3427* libsane_matched=yes # Samsung CLX-6240 -usb:v04E8p04E8* +usb:v04E8p3428* libsane_matched=yes # Samsung SCX-6x55 -usb:v04E8p04E8* +usb:v04E8p3429* libsane_matched=yes # Samsung CLX-3170fn (CLX-3170 Series) | Samsung CLX-3175FW -usb:v04E8p04E8* +usb:v04E8p342A* libsane_matched=yes # Samsung SCX-4500W -usb:v04E8p04E8* +usb:v04E8p342B* libsane_matched=yes # Samsung SCX-4824 (SCX-4x24 Series) -usb:v04E8p04E8* +usb:v04E8p342C* libsane_matched=yes # Samsung SCX-4828FN (SCX-4x28 Series) -usb:v04E8p04E8* +usb:v04E8p342D* libsane_matched=yes # Samsung SCX-4300 -usb:v04E8p04E8* +usb:v04E8p342E* libsane_matched=yes # Samsung SCX-5835_5935 -usb:v04E8p04E8* +usb:v04E8p342F* libsane_matched=yes # Samsung SCX-5635 -usb:v04E8p04E8* +usb:v04E8p3430* libsane_matched=yes # Samsung SCX-4x26 -usb:v04E8p04E8* +usb:v04E8p3432* libsane_matched=yes # Samsung SCX-4600 -usb:v04E8p04E8* +usb:v04E8p3433* libsane_matched=yes # Samsung SCX-4623 -usb:v04E8p04E8* +usb:v04E8p3434* libsane_matched=yes # Samsung MFP-65x -usb:v04E8p04E8* +usb:v04E8p3435* libsane_matched=yes # Samsung SCX-6545 -usb:v04E8p04E8* +usb:v04E8p3437* libsane_matched=yes # Samsung CLX-8385 -usb:v04E8p04E8* +usb:v04E8p3439* libsane_matched=yes # Samsung CLX-6220 -usb:v04E8p04E8* +usb:v04E8p343A* libsane_matched=yes # Samsung CLX-6250 -usb:v04E8p04E8* +usb:v04E8p343B* libsane_matched=yes # Samsung SCX-4825FN (SCX-4x25 Series) -usb:v04E8p04E8* +usb:v04E8p343C* libsane_matched=yes # Samsung CLX-3185 -usb:v04E8p04E8* +usb:v04E8p343D* libsane_matched=yes # Samsung CLX-8540 -usb:v04E8p04E8* +usb:v04E8p343F* libsane_matched=yes # Samsung SCX-4623FW -usb:v04E8p04E8* +usb:v04E8p3440* libsane_matched=yes # Samsung SCX-3205W (SCX-3200 Series) -usb:v04E8p04E8* +usb:v04E8p3441* libsane_matched=yes # Samsung SCX-6545X -usb:v04E8p04E8* +usb:v04E8p3442* libsane_matched=yes # Samsung SCX-6x55X -usb:v04E8p04E8* +usb:v04E8p3443* libsane_matched=yes # Samsung CLX-8385X -usb:v04E8p04E8* +usb:v04E8p3444* libsane_matched=yes # Samsung SCX-5835_5935X -usb:v04E8p04E8* +usb:v04E8p3446* libsane_matched=yes # Samsung SCX-4833FD | Samsung SCX-4835FD -usb:v04E8p04E8* +usb:v04E8p344B* libsane_matched=yes # Samsung SCX-3400 -usb:v04E8p04E8* +usb:v04E8p344F* libsane_matched=yes # Samsung SF-760 -usb:v04E8p04E8* +usb:v04E8p3450* libsane_matched=yes # Samsung SCX-4729FD -usb:v04E8p04E8* +usb:v04E8p3453* libsane_matched=yes # Samsung CLX-6260 -usb:v04E8p04E8* +usb:v04E8p3455* libsane_matched=yes # Samsung CLX-3300 Series -usb:v04E8p04E8* +usb:v04E8p3456* libsane_matched=yes # Samsung SCX-470x -usb:v04E8p04E8* +usb:v04E8p3457* libsane_matched=yes # Samsung CLX-4190 -usb:v04E8p04E8* +usb:v04E8p345A* libsane_matched=yes # Samsung SCX-4650 4x21S Series -usb:v04E8p04E8* +usb:v04E8p345B* libsane_matched=yes # Samsung M337x 387x 407x Series -usb:v04E8p04E8* +usb:v04E8p3460* libsane_matched=yes # Samsung M267x 287x Series -usb:v04E8p04E8* +usb:v04E8p3461* libsane_matched=yes # Samsung SCX-681x -usb:v04E8p04E8* +usb:v04E8p3466* libsane_matched=yes # Samsung C460 -usb:v04E8p04E8* +usb:v04E8p3468* libsane_matched=yes # Pentax DSmobile 600 -usb:v04F9p04F9* +usb:v04F9p2038* libsane_matched=yes # Aiptek Aiptek Pencam -usb:v0553p0553* +usb:v0553p0202* libsane_matched=yes # Mustek ScanExpress 1200 CU -usb:v055Fp055F* +usb:v055Fp0001* libsane_matched=yes # Mustek ScanExpress 600 CU -usb:v055Fp055F* +usb:v055Fp0002* libsane_matched=yes # Mustek ScanExpress 1200 UB | Trust Compact Scan USB 19200 -usb:v055Fp055F* +usb:v055Fp0006* libsane_matched=yes # Mustek ScanExpress 1200 CU Plus -usb:v055Fp055F* +usb:v055Fp0008* libsane_matched=yes # Mustek BearPaw 1200 F -usb:v055Fp055F* +usb:v055Fp0010* libsane_matched=yes # Mustek ScanExpress A3 USB -usb:v055Fp055F* +usb:v055Fp0210* libsane_matched=yes # Mustek BearPaw 2400 CS | Mustek BearPaw 2400 TA | Trust 240TH Easy Webscan Gold -usb:v055Fp055F* +usb:v055Fp0218* libsane_matched=yes # Mustek BearPaw 2400 CS Plus | Mustek BearPaw 2400 TA Plus | Mustek Plug-n-Scan 2400 MT # Mustek Plug-n-Scan 2400 M | Packard Bell Diamond 2450 -usb:v055Fp055F* +usb:v055Fp0219* libsane_matched=yes # Mustek BearPaw 2448 CS Plus | Mustek BearPaw 2448 TA Plus -usb:v055Fp055F* +usb:v055Fp021A* libsane_matched=yes # Mustek BearPaw 1200 CU Plus | Packard Bell Diamond 1200 Plus -usb:v055Fp055F* +usb:v055Fp021B* libsane_matched=yes # Mustek BearPaw 1200 CU Plus | Mustek BearPaw 1248 CU | Packard Bell Diamond 1200 Plus # Trust Direct WebScan 19200 -usb:v055Fp055F* +usb:v055Fp021C* libsane_matched=yes # Mustek BearPaw 2400 CU Plus -usb:v055Fp055F* +usb:v055Fp021D* libsane_matched=yes # Mustek BearPaw 1200 CS | Mustek BearPaw 1200 TA -usb:v055Fp055F* +usb:v055Fp021E* libsane_matched=yes # Mustek ScanExpress 1248 UB -usb:v055Fp055F* +usb:v055Fp021F* libsane_matched=yes # Mustek BearPaw 2448TA Pro -usb:v055Fp055F* +usb:v055Fp0409* libsane_matched=yes # Artec/Ultima Ultima 2000 | Artec/Ultima Ultima 2000 e+ | Boeder Sm@rtScan Slim Edition @@ -2173,564 +2173,564 @@ usb:v055Fp055F* # Medion/Lifetec/Tevion/Cytron MD 9458 | Mustek BearPaw 1200 CU | Mustek BearPaw 2400 CU # Mustek ScanExpress 1200 UB Plus | Mustek ScanExpress 2400 USB | Mustek ScanMagic 1200 UB Plus # Packard Bell Diamond 1200 | Trust Compact Scan USB 19200 | Trust Flat Scan USB 19200 -usb:v05D8p05D8* +usb:v05D8p4002* libsane_matched=yes # Artec/Ultima E+ 48U | Medion/Lifetec/Tevion/Cytron MD9693 | Medion/Lifetec/Tevion/Cytron MD9705 # Medion/Lifetec/Tevion/Cytron MD4394 | Microstar MR 9791 -usb:v05D8p05D8* +usb:v05D8p4003* libsane_matched=yes # Artec/Ultima E+ Pro -usb:v05D8p05D8* +usb:v05D8p4004* libsane_matched=yes # Memorex MEM 48U -usb:v05D8p05D8* +usb:v05D8p4005* libsane_matched=yes # Trust Easy Webscan 19200 -usb:v05D8p05D8* +usb:v05D8p4006* libsane_matched=yes # Trust 240H Easy Webscan Gold -usb:v05D8p05D8* +usb:v05D8p4007* libsane_matched=yes # UMAX AstraSlim SE -usb:v05D8p05D8* +usb:v05D8p4009* libsane_matched=yes # UMAX AstraSlim 1200 SE -usb:v05D8p05D8* +usb:v05D8p4010* libsane_matched=yes # Yakumo Scan50 -usb:v05D8p05D8* +usb:v05D8p4011* libsane_matched=yes # Microtek ScanMaker X6USB -usb:v05DAp05DA* +usb:v05DAp0099* libsane_matched=yes # Microtek SlimScan C6 -usb:v05DAp05DA* +usb:v05DAp009A* libsane_matched=yes # Microtek ScanMaker V6USL -usb:v05DAp05DA* +usb:v05DAp00A3* libsane_matched=yes # Microtek ScanMaker V6UPL -usb:v05DAp05DA* +usb:v05DAp00B6* libsane_matched=yes # Microtek ScanMaker 4800 -usb:v05DAp05DA* +usb:v05DAp30CF* libsane_matched=yes # Microtek ScanMaker 3840 -usb:v05DAp05DA* +usb:v05DAp30D4* libsane_matched=yes # Microtek ScanMaker 3600 -usb:v05DAp05DA* +usb:v05DAp40B3* libsane_matched=yes # Microtek ScanMaker 3700 -usb:v05DAp05DA* +usb:v05DAp40B8* libsane_matched=yes # Microtek ScanMaker 3600 -usb:v05DAp05DA* +usb:v05DAp40CA* libsane_matched=yes # Microtek ScanMaker 3700 -usb:v05DAp05DA* +usb:v05DAp40CB* libsane_matched=yes # Microtek ScanMaker 3750 -usb:v05DAp05DA* +usb:v05DAp40DD* libsane_matched=yes # Microtek ScanMaker 3600 -usb:v05DAp05DA* +usb:v05DAp40FF* libsane_matched=yes # Microtek ScanMaker V6USL -usb:v05DAp05DA* +usb:v05DAp80A3* libsane_matched=yes # iVina 1200U -usb:v0638p0638* +usb:v0638p0268* libsane_matched=yes # Minolta Dimage Scan Dual II -usb:v0638p0638* +usb:v0638p026A* libsane_matched=yes # Avision AV600U -usb:v0638p0638* +usb:v0638p0A13* libsane_matched=yes # Minolta-QMS SC-110 -usb:v0638p0638* +usb:v0638p0A15* libsane_matched=yes # Avision DS610CU Scancopier | Minolta-QMS SC-215 | OKI S700 Scancopier -usb:v0638p0638* +usb:v0638p0A16* libsane_matched=yes # Avision AV610 | Avision AV600U Plus -usb:v0638p0638* +usb:v0638p0A18* libsane_matched=yes # Avision AV220 -usb:v0638p0638* +usb:v0638p0A23* libsane_matched=yes # Avision AV210 -usb:v0638p0638* +usb:v0638p0A24* libsane_matched=yes # Avision AV210 -usb:v0638p0638* +usb:v0638p0A25* libsane_matched=yes # Avision AV120 -usb:v0638p0638* +usb:v0638p0A27* libsane_matched=yes # Avision AV220C2 -usb:v0638p0638* +usb:v0638p0A2A* libsane_matched=yes # Avision AV220D2 -usb:v0638p0638* +usb:v0638p0A2B* libsane_matched=yes # Avision AV220+ -usb:v0638p0638* +usb:v0638p0A2C* libsane_matched=yes # Avision AV220C2-G -usb:v0638p0638* +usb:v0638p0A2D* libsane_matched=yes # Avision AV220C2-B -usb:v0638p0638* +usb:v0638p0A2E* libsane_matched=yes # Avision AV210C2-G -usb:v0638p0638* +usb:v0638p0A2F* libsane_matched=yes # Avision AV122 -usb:v0638p0638* +usb:v0638p0A33* libsane_matched=yes # Avision AV210C2 -usb:v0638p0638* +usb:v0638p0A3A* libsane_matched=yes # Avision AV121 -usb:v0638p0638* +usb:v0638p0A3C* libsane_matched=yes # Avision AV8300 -usb:v0638p0638* +usb:v0638p0A40* libsane_matched=yes # Avision AM3000 Series -usb:v0638p0638* +usb:v0638p0A41* libsane_matched=yes # Avision @V5100 -usb:v0638p0638* +usb:v0638p0A45* libsane_matched=yes # Avision AV8050U -usb:v0638p0638* +usb:v0638p0A4D* libsane_matched=yes # Avision AV3200SU -usb:v0638p0638* +usb:v0638p0A4E* libsane_matched=yes # Avision AV3730SU -usb:v0638p0638* +usb:v0638p0A4F* libsane_matched=yes # Avision AV610C2 -usb:v0638p0638* +usb:v0638p0A5E* libsane_matched=yes # Avision IT8300 -usb:v0638p0638* +usb:v0638p0A61* libsane_matched=yes # Avision AV3750SU -usb:v0638p0638* +usb:v0638p0A65* libsane_matched=yes # Avision AV3850SU -usb:v0638p0638* +usb:v0638p0A66* libsane_matched=yes # Avision AV8350 -usb:v0638p0638* +usb:v0638p0A68* libsane_matched=yes # Avision FB6080E -usb:v0638p0638* +usb:v0638p0A82* libsane_matched=yes # Avision FB2080E -usb:v0638p0638* +usb:v0638p0A84* libsane_matched=yes # Avision AV122 C2 -usb:v0638p0638* +usb:v0638p0A93* libsane_matched=yes # Avision AV220-G -usb:v0638p0638* +usb:v0638p0A94* libsane_matched=yes # Avision @V2500 -usb:v0638p0638* +usb:v0638p0AA1* libsane_matched=yes # Avision AV210D2+ -usb:v0638p0638* +usb:v0638p1A35* libsane_matched=yes # Minolta Elite II -usb:v0686p0686* +usb:v0686p4004* libsane_matched=yes # Minolta Dimage Scan Dual III -usb:v0686p0686* +usb:v0686p400D* libsane_matched=yes # Minolta Dimage Scan Elite 5400 -usb:v0686p0686* +usb:v0686p400E* libsane_matched=yes # AGFA SnapScan 1212U -usb:v06BDp06BD* +usb:v06BDp0001* libsane_matched=yes # AGFA SnapScan 1236u -usb:v06BDp06BD* +usb:v06BDp0002* libsane_matched=yes # Agfa Snapscan Touch -usb:v06BDp06BD* +usb:v06BDp0100* libsane_matched=yes # AGFA SnapScan 1212U_2 -usb:v06BDp06BD* +usb:v06BDp2061* libsane_matched=yes # AGFA SnapScan e40 -usb:v06BDp06BD* +usb:v06BDp208D* libsane_matched=yes # AGFA SnapScan e50 -usb:v06BDp06BD* +usb:v06BDp208F* libsane_matched=yes # AGFA SnapScan e20 -usb:v06BDp06BD* +usb:v06BDp2091* libsane_matched=yes # AGFA SnapScan e10 -usb:v06BDp06BD* +usb:v06BDp2093* libsane_matched=yes # AGFA SnapScan e25 -usb:v06BDp06BD* +usb:v06BDp2095* libsane_matched=yes # AGFA SnapScan e26 -usb:v06BDp06BD* +usb:v06BDp2097* libsane_matched=yes # AGFA SnapScan e52 -usb:v06BDp06BD* +usb:v06BDp20FD* libsane_matched=yes # AGFA SnapScan e42 -usb:v06BDp06BD* +usb:v06BDp20FF* libsane_matched=yes # UMAX Astra 4900 -usb:v06DCp06DC* +usb:v06DCp0020* libsane_matched=yes # Plustek OpticPro U12 | Plustek OpticPro UT12 | Plustek OpticPro 1212U # RevScan RevScan Orange R48Ti | Genius ColorPage Vivid III USB -usb:v07B3p07B3* +usb:v07B3p0001* libsane_matched=yes # Plustek OpticPro U12 -usb:v07B3p07B3* +usb:v07B3p0010* libsane_matched=yes # Plustek OpticPro U24 -usb:v07B3p07B3* +usb:v07B3p0011* libsane_matched=yes # Plustek OpticPro UT12 -usb:v07B3p07B3* +usb:v07B3p0013* libsane_matched=yes # Plustek OpticPro U24 -usb:v07B3p07B3* +usb:v07B3p0015* libsane_matched=yes # Plustek OpticPro UT12 | Plustek OpticPro UT16 | Plustek OpticPro UT24 -usb:v07B3p07B3* +usb:v07B3p0017* libsane_matched=yes # Plustek OpticPro 1248U | RevScan 19200i -usb:v07B3p07B3* +usb:v07B3p0400* libsane_matched=yes # Plustek OpticPro 1248U -usb:v07B3p07B3* +usb:v07B3p0401* libsane_matched=yes # Plustek OpticPro U16B -usb:v07B3p07B3* +usb:v07B3p0402* libsane_matched=yes # Plustek OpticPro U16B+ | Plustek OpticPro UT16B -usb:v07B3p07B3* +usb:v07B3p0403* libsane_matched=yes # Nortek MyScan 1200 | Plustek OpticPro S12 | Plustek OpticPro ST12 -usb:v07B3p07B3* +usb:v07B3p040B* libsane_matched=yes # Plustek OpticPro S24 -usb:v07B3p07B3* +usb:v07B3p040E* libsane_matched=yes # NeatReceipts Scanalizer Professional 2.5 | Plustek OpticSlim M12 -usb:v07B3p07B3* +usb:v07B3p0412* libsane_matched=yes # Plustek OpticSlim 1200 -usb:v07B3p07B3* +usb:v07B3p0413* libsane_matched=yes # Plustek OpticSlim 2400 -usb:v07B3p07B3* +usb:v07B3p0422* libsane_matched=yes # Plustek OpticSlim 2400 plus -usb:v07B3p07B3* +usb:v07B3p0454* libsane_matched=yes # Plustek Iriscan Express 2 -usb:v07B3p07B3* +usb:v07B3p045F* libsane_matched=yes # NeatReceipts Mobile Scanner -usb:v07B3p07B3* +usb:v07B3p0462* libsane_matched=yes # Plustek OpticBook 3600 -usb:v07B3p07B3* +usb:v07B3p0900* libsane_matched=yes # Corex 600c -usb:v08F0p08F0* +usb:v08F0p0002* libsane_matched=yes # Corex 800c -usb:v08F0p08F0* +usb:v08F0p0005* libsane_matched=yes # Xerox Phaser 6110MFP -usb:v0924p0924* +usb:v0924p3D5D* libsane_matched=yes # Xerox Phaser 3200MFP -usb:v0924p0924* +usb:v0924p3DA4* libsane_matched=yes # Xerox WorkCentre 4118 Series -usb:v0924p0924* +usb:v0924p420C* libsane_matched=yes # Xerox WorkCentre 3119 Series -usb:v0924p0924* +usb:v0924p4265* libsane_matched=yes # Xerox WorkCentre 3210 -usb:v0924p0924* +usb:v0924p4293* libsane_matched=yes # Xerox WorkCentre 3220 -usb:v0924p0924* +usb:v0924p4294* libsane_matched=yes # Pentax DSmobile 600 -usb:v0A17p0A17* +usb:v0A17p3210* libsane_matched=yes # Portable Peripheral Co., Ltd. Q-Scan USB001 (A4 portable scanner) -usb:v0A53p0A53* +usb:v0A53p1000* libsane_matched=yes # Portable Peripheral Co., Ltd. Q-Scan USB201 (A6 portable scanner) -usb:v0A53p0A53* +usb:v0A53p2000* libsane_matched=yes # Syscan TravelScan 460/464 | Ambir Visigo A4 -usb:v0A82p0A82* +usb:v0A82p4600* libsane_matched=yes # Syscan DocketPort 465 -usb:v0A82p0A82* +usb:v0A82p4802* libsane_matched=yes # Syscan DocketPort 665 -usb:v0A82p0A82* +usb:v0A82p4803* libsane_matched=yes # Syscan DocketPort 685/ Ambir DS685 -usb:v0A82p0A82* +usb:v0A82p480C* libsane_matched=yes # Syscan DocketPort 485 -usb:v0A82p0A82* +usb:v0A82p4810* libsane_matched=yes # Syscan TravelScan 662 -usb:v0A82p0A82* +usb:v0A82p6620* libsane_matched=yes # Canon CR-55 -usb:v1083p1083* +usb:v1083p160C* libsane_matched=yes # Canon DR-1210C -usb:v1083p1083* +usb:v1083p160F* libsane_matched=yes # Canon DR-4010C -usb:v1083p1083* +usb:v1083p1614* libsane_matched=yes # Canon DR-2510C -usb:v1083p1083* +usb:v1083p1617* libsane_matched=yes # Canon DR-X10C -usb:v1083p1083* +usb:v1083p1618* libsane_matched=yes # Canon CR-25 -usb:v1083p1083* +usb:v1083p161A* libsane_matched=yes # Canon DR-2010C -usb:v1083p1083* +usb:v1083p161B* libsane_matched=yes # Canon DR-3010C -usb:v1083p1083* +usb:v1083p161D* libsane_matched=yes # Canon DR-7090C -usb:v1083p1083* +usb:v1083p1620* libsane_matched=yes # Canon DR-9050C -usb:v1083p1083* +usb:v1083p1622* libsane_matched=yes # Canon DR-7550C -usb:v1083p1083* +usb:v1083p1623* libsane_matched=yes # Canon DR-6050C -usb:v1083p1083* +usb:v1083p1624* libsane_matched=yes # Canon DR-6010C -usb:v1083p1083* +usb:v1083p1626* libsane_matched=yes # Canon CR-190i -usb:v1083p1083* +usb:v1083p162B* libsane_matched=yes # Canon DR-6030C -usb:v1083p1083* +usb:v1083p1638* libsane_matched=yes # Canon CR-135i -usb:v1083p1083* +usb:v1083p1639* libsane_matched=yes # Digital Dream l' espion XS -usb:v1183p1183* +usb:v1183p0001* libsane_matched=yes # KONICA MINOLTA magicolor 1690MF -usb:v132Bp132B* +usb:v132Bp2089* libsane_matched=yes # UMAX Astra 1220U -usb:v1606p1606* +usb:v1606p0010* libsane_matched=yes # UMAX Astra 1600U | UMAX Astra 2000U -usb:v1606p1606* +usb:v1606p0030* libsane_matched=yes # Umax UMAX 3400 -usb:v1606p1606* +usb:v1606p0050* libsane_matched=yes # Umax UMAX 3400 | Umax UMAX Astranet ia101 | Umax UMAX 3450 -usb:v1606p1606* +usb:v1606p0060* libsane_matched=yes # UMAX Astra 4400 | UMAX Astra 4450 -usb:v1606p1606* +usb:v1606p0070* libsane_matched=yes # UMAX Astra 2100U -usb:v1606p1606* +usb:v1606p0130* libsane_matched=yes # Umax UMAX 5400 -usb:v1606p1606* +usb:v1606p0160* libsane_matched=yes # UMAX Astra 2200 (SU) -usb:v1606p1606* +usb:v1606p0230* libsane_matched=yes # DCT DocketPort 487 -usb:v1DCCp1DCC* +usb:v1DCCp4810* libsane_matched=yes # Dell A920 -usb:v413Cp413C* +usb:v413Cp5105* libsane_matched=yes # Dell Dell MFP Laser Printer 1815dn -usb:v413Cp413C* +usb:v413Cp5124* libsane_matched=yes # Dell 1600n -usb:v413Cp413C* +usb:v413Cp5250* libsane_matched=yes diff --git a/testsuite/tools/data/udev+acl.ref b/testsuite/tools/data/udev+acl.ref index dc21606..167cf56 100644 --- a/testsuite/tools/data/udev+acl.ref +++ b/testsuite/tools/data/udev+acl.ref @@ -1430,7 +1430,8 @@ ENV{libsane_matched}=="yes", RUN+="/bin/sh -c 'if test -e /sys/$env{DEVPATH}/pow LABEL="libsane_usb_rules_end" -SUBSYSTEMS!="scsi", GOTO="libsane_scsi_rules_end" +SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" +GOTO="libsane_scsi_rules_end" LABEL="libsane_scsi_rules_begin" # Generic: SCSI device type 6 indicates a scanner diff --git a/testsuite/tools/data/udev+hwdb.ref b/testsuite/tools/data/udev+hwdb.ref index 7e25b80..aec3129 100644 --- a/testsuite/tools/data/udev+hwdb.ref +++ b/testsuite/tools/data/udev+hwdb.ref @@ -25,7 +25,10 @@ ACTION!="add", GOTO="libsane_rules_end" # The following rule will disable USB autosuspend for the device ENV{DEVTYPE}=="usb_device", ENV{libsane_matched}=="yes", TEST=="power/control", ATTR{power/control}="on" -SUBSYSTEMS!="scsi", GOTO="libsane_rules_end" +SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" +GOTO="libsane_rules_end" + +LABEL="libsane_scsi_rules_begin" KERNEL!="sg[0-9]*", GOTO="libsane_rules_end" # Generic: SCSI device type 6 indicates a scanner diff --git a/testsuite/tools/data/udev.ref b/testsuite/tools/data/udev.ref index 859a0dc..12db0e4 100644 --- a/testsuite/tools/data/udev.ref +++ b/testsuite/tools/data/udev.ref @@ -1430,7 +1430,8 @@ ENV{libsane_matched}=="yes", RUN+="/bin/sh -c 'if test -e /sys/$env{DEVPATH}/pow LABEL="libsane_usb_rules_end" -SUBSYSTEMS!="scsi", GOTO="libsane_scsi_rules_end" +SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" +GOTO="libsane_scsi_rules_end" LABEL="libsane_scsi_rules_begin" # Generic: SCSI device type 6 indicates a scanner diff --git a/tools/check-usb-chip.c b/tools/check-usb-chip.c index 68b8f79..e851855 100644 --- a/tools/check-usb-chip.c +++ b/tools/check-usb-chip.c @@ -4063,6 +4063,213 @@ check_genesys (libusb_device_handle * handle, return "GL646_HP"; } +/********** the lm983x section **********/ + +static int +lm983x_wb (libusb_device_handle *handle, unsigned char reg, unsigned char val) +{ + unsigned char buf[5]; + int written; + int result; + + buf[0] = 0; + buf[1] = reg; + buf[2] = 0; + buf[3] = 1; + buf[4] = val; + + result = libusb_bulk_transfer(handle, 0x03, buf, 5, &written, TIMEOUT); + if (result < 0) + return 0; + + if (written != 5) + return 0; + + return 1; +} + +static int +lm983x_rb (libusb_device_handle *handle, unsigned char reg, unsigned char *val) +{ + unsigned char buf[5]; + int result; + int tfx; + + buf[0] = 1; + buf[1] = reg; + buf[2] = 0; + buf[3] = 1; + + result = libusb_bulk_transfer(handle, 0x03, buf, 4, &tfx, TIMEOUT); + if (result < 0) + return 0; + + if (tfx != 4) + return 0; + + result = libusb_bulk_transfer(handle, 0x82, val, 1, &tfx, TIMEOUT); + if (result < 0) + return 0; + + if (tfx != 1) + return 0; + + return 1; +} + +/** @brief check for known LM983x chip (aka Merlin) + * + * Try to check if the scanner uses a LM983x ASIC. + * + * @param dev libusb device + * @param hdl libusb opened handle + * @param config0 configuration 0 from get config _descriptor + * @return a string with ASIC name, or NULL if not recognized + */ +static char * +check_merlin(libusb_device_handle * handle, + struct libusb_device_descriptor desc, + struct libusb_config_descriptor *config0) +{ + unsigned char val; + int result; + + if (verbose > 2) + printf (" checking for LM983[1,2,3] ...\n"); + + /* Check device descriptor */ + if (((desc.bDeviceClass != LIBUSB_CLASS_VENDOR_SPEC) + && (desc.bDeviceClass != 0)) + || (config0->interface[0].altsetting[0].bInterfaceClass != + LIBUSB_CLASS_VENDOR_SPEC)) + { + if (verbose > 2) + printf + (" this is not a LM983x (bDeviceClass = %d, bInterfaceClass = %d)\n", + desc.bDeviceClass, + config0->interface[0].altsetting[0].bInterfaceClass); + return 0; + } + if ((desc.bcdUSB != 0x110) + && (desc.bcdUSB != 0x101) + && (desc.bcdUSB != 0x100)) + { + if (verbose > 2) + printf (" this is not a LM983x (bcdUSB = 0x%x)\n", desc.bcdUSB); + return 0; + } + if (desc.bDeviceSubClass != 0x00) + { + if (verbose > 2) + printf (" this is not a LM983x (bDeviceSubClass = 0x%x)\n", + desc.bDeviceSubClass); + return 0; + } + if ((desc.bDeviceProtocol != 0) && + (desc.bDeviceProtocol != 0xff)) + { + if (verbose > 2) + printf (" this is not a LM983x (bDeviceProtocol = 0x%x)\n", + desc.bDeviceProtocol); + return 0; + } + + /* Check endpoints */ + if (config0->interface[0].altsetting[0].bNumEndpoints != 3) + { + if (verbose > 2) + printf (" this is not a LM983x (bNumEndpoints = %d)\n", + config0->interface[0].altsetting[0].bNumEndpoints); + return 0; + } + + if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) + || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x03) + || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x1) + || (config0->interface[0].altsetting[0].endpoint[0].bInterval != 0x10)) + { + if (verbose > 2) + printf + (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " + "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", + config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[0].bmAttributes, + config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[0].bInterval); + return 0; + } + + if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != 0x82) + || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != 0x02) + || (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != 0x40) + /* Currently disabled as we have some problems in detection here ! */ + /*|| (config0->interface[0].altsetting[0].endpoint[1].bInterval != 0) */ + ) + { + if (verbose > 2) + printf + (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " + "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", + config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[1].bmAttributes, + config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[1].bInterval); + return 0; + } + + if ((config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress != 0x03) + || (config0->interface[0].altsetting[0].endpoint[2].bmAttributes != 0x02) + || (config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize != 0x40) + /* Currently disabled as we have some problems in detection here ! */ + /* || (config0->interface[0].altsetting[0].endpoint[2].bInterval != 0) */ + ) + { + if (verbose > 2) + printf + (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " + "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", + config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[2].bmAttributes, + config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[2].bInterval); + return 0; + } + + result = lm983x_wb (handle, 0x07, 0x00); + if (1 == result) + result = lm983x_wb (handle, 0x08, 0x02); + if (1 == result) + result = lm983x_rb (handle, 0x07, &val); + if (1 == result) + result = lm983x_rb (handle, 0x08, &val); + if (1 == result) + result = lm983x_rb (handle, 0x69, &val); + + if (0 == result) + { + if (verbose > 2) + printf (" Couldn't access LM983x registers.\n"); + return 0; + } + + switch (val) + { + case 4: + return "LM9832/3"; + break; + case 3: + return "LM9831"; + break; + case 2: + return "LM9830"; + break; + default: + return "LM983x?"; + break; + } +} + + char * check_usb_chip (int verbosity, struct libusb_device_descriptor desc, @@ -4101,6 +4308,9 @@ check_usb_chip (int verbosity, /* now USB is opened and set up, actual chip detection */ + if (!chip_name) + chip_name = check_merlin (hdl, desc, config0); + if (!chip_name) chip_name = check_gt6801 (hdl, desc, config0); diff --git a/tools/epson2usb.pl b/tools/epson2usb.pl new file mode 100755 index 0000000..afd6ebd --- /dev/null +++ b/tools/epson2usb.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl -w + +# Creates an USB device list from the description file +# +# epson2usb.pl doc/descriptions/epson2.desc +# +# Copyright (C) 2010 Tower Technologies +# Author: Alessandro Zummo +# +# This file is part of the SANE package. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation, version 2. + +use strict; +use warnings; + + my %ids; + my @models; + my $i = 0; + + while (<>) { + + my $flip = /^:model/ ... /^$/; + + $models[$i]{$1} = $2 + if /^:(\w+)\s+(.+)/; + + $i++ + if $flip =~ /E0$/; + } + + foreach my $m (@models) { + + next unless defined $m->{'usbid'}; + next if $m->{'status'} eq ':unsupported'; + +# print $m->{'model'} , "\n"; +# print "-", $m->{'usbid'} , "-\n"; + + next unless $m->{'usbid'} =~ /"0x04b8"\s+"(0x[[:xdigit:]]+)"/; + + my $id = $1; + +# print $id, "\n"; + + $id =~ s/0x0/0x/; + + $m->{'model'} =~ s/;.+$//; + $m->{'model'} =~ s/\"//g; + $m->{'model'} =~ s/\s+$//; + + push(@{$ids{$id}}, $m->{'model'}); + } + + foreach (sort keys %ids) { + print ' ', $_, ', /* '; + print join(', ', @{$ids{$_}}); + print " */\n"; + } + + diff --git a/tools/sane-desc.c b/tools/sane-desc.c index 3cc4407..c8b50ad 100644 --- a/tools/sane-desc.c +++ b/tools/sane-desc.c @@ -3568,7 +3568,8 @@ print_udev (void) printf ("\nLABEL=\"libsane_usb_rules_end\"\n\n"); - printf ("SUBSYSTEMS!=\"scsi\", GOTO=\"libsane_scsi_rules_end\"\n\n"); + printf ("SUBSYSTEMS==\"scsi\", GOTO=\"libsane_scsi_rules_begin\"\n"); + printf ("GOTO=\"libsane_scsi_rules_end\"\n\n"); printf ("LABEL=\"libsane_scsi_rules_begin\"\n"); printf ("# Generic: SCSI device type 6 indicates a scanner\n"); @@ -3695,7 +3696,9 @@ print_udevhwdb (void) printf("# The following rule will disable USB autosuspend for the device\n"); printf("ENV{DEVTYPE}==\"usb_device\", ENV{libsane_matched}==\"yes\", TEST==\"power/control\", ATTR{power/control}=\"on\"\n\n"); - printf ("SUBSYSTEMS!=\"scsi\", GOTO=\"libsane_rules_end\"\n"); + printf ("SUBSYSTEMS==\"scsi\", GOTO=\"libsane_scsi_rules_begin\"\n"); + printf ("GOTO=\"libsane_rules_end\"\n\n"); + printf ("LABEL=\"libsane_scsi_rules_begin\"\n"); printf ("KERNEL!=\"sg[0-9]*\", GOTO=\"libsane_rules_end\"\n\n"); printf ("# Generic: SCSI device type 6 indicates a scanner\n"); @@ -3827,7 +3830,7 @@ print_hwdb (void) for(j = 0; j < 4; j++) { vendor_id[j] = toupper(vendor_id[j]); - product_id[j] = toupper(vendor_id[j]); + product_id[j] = toupper(product_id[j]); } printf ("usb:v%sp%s*\n libsane_matched=yes\n\n", diff --git a/tools/sane-find-scanner.c b/tools/sane-find-scanner.c index dbfd0da..ae0e116 100644 --- a/tools/sane-find-scanner.c +++ b/tools/sane-find-scanner.c @@ -757,8 +757,6 @@ sfs_libusb_strerror (int errcode) default: return "Unknown libusb-1.0 error code"; } - - return "Unknown libusb-1.0 error code"; } static char * -- cgit v1.2.3