summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/Makefile.am19
-rw-r--r--backend/Makefile.in228
-rw-r--r--backend/avision.c397
-rw-r--r--backend/avision.h84
-rw-r--r--backend/canon_dr.c36
-rw-r--r--backend/canon_dr.conf.in1
-rw-r--r--backend/dll.conf.in1
-rw-r--r--backend/epjitsu.c26
-rw-r--r--backend/epson2-commands.c4
-rw-r--r--backend/epson2-io.c9
-rw-r--r--backend/epson2-ops.c34
-rw-r--r--backend/epson2.c63
-rw-r--r--backend/epson2.h2
-rw-r--r--backend/epsonds-cmd.c899
-rw-r--r--backend/epsonds-cmd.h29
-rw-r--r--backend/epsonds-io.c177
-rw-r--r--backend/epsonds-io.h33
-rw-r--r--backend/epsonds-jpeg.c221
-rw-r--r--backend/epsonds-jpeg.h19
-rw-r--r--backend/epsonds-ops.c474
-rw-r--r--backend/epsonds-ops.h41
-rw-r--r--backend/epsonds-usb.c33
-rw-r--r--backend/epsonds-usb.h24
-rw-r--r--backend/epsonds.c1434
-rw-r--r--backend/epsonds.conf.in12
-rw-r--r--backend/epsonds.h198
-rw-r--r--backend/genesys.c56
-rw-r--r--backend/genesys.conf.in6
-rw-r--r--backend/genesys.h1
-rw-r--r--backend/genesys_devices.c155
-rw-r--r--backend/genesys_gl124.c39
-rw-r--r--backend/genesys_gl124.h14
-rw-r--r--backend/genesys_low.c43
-rw-r--r--backend/genesys_low.h5
-rw-r--r--backend/hp5590.c8
-rw-r--r--backend/pixma.c2
-rw-r--r--backend/pixma.h4
-rw-r--r--backend/pixma_common.c2
-rw-r--r--backend/pixma_common.h2
-rw-r--r--backend/pixma_imageclass.c12
-rw-r--r--backend/pixma_io_sanei.c2
-rw-r--r--backend/pixma_mp150.c11
-rw-r--r--backend/pixma_mp730.c2
-rw-r--r--backend/pixma_mp750.c2
-rw-r--r--backend/pixma_mp810.c25
45 files changed, 4464 insertions, 425 deletions
diff --git a/backend/Makefile.am b/backend/Makefile.am
index f84d23e..40ec6c6 100644
--- a/backend/Makefile.am
+++ b/backend/Makefile.am
@@ -83,7 +83,7 @@ BACKEND_CONFS= abaton.conf agfafocus.conf apple.conf artec.conf \
canon_pp.conf cardscan.conf coolscan2.conf coolscan3.conf \
coolscan.conf dc210.conf dc240.conf dc25.conf \
dell1600n_net.conf dmc.conf epjitsu.conf epson2.conf \
- epson.conf fujitsu.conf genesys.conf gphoto2.conf \
+ epson.conf epsonds.conf fujitsu.conf genesys.conf gphoto2.conf \
gt68xx.conf hp3900.conf hp4200.conf hp5400.conf \
hp.conf hpsj5s.conf hs2p.conf ibm.conf kodak.conf kodakaio.conf\
leo.conf lexmark.conf ma1509.conf magicolor.conf \
@@ -171,7 +171,7 @@ be_convenience_libs = libabaton.la libagfafocus.la \
libcoolscan2.la libcoolscan3.la libdc25.la \
libdc210.la libdc240.la libdell1600n_net.la \
libdmc.la libdll.la libdll_preload.la libepjitsu.la libepson.la \
- libepson2.la libfujitsu.la libgenesys.la \
+ libepson2.la libepsonds.la libfujitsu.la libgenesys.la \
libgphoto2_i.la libgt68xx.la libhp.la \
libhp3500.la libhp3900.la libhp4200.la \
libhp5400.la libhp5590.la libhpljm1005.la \
@@ -204,7 +204,7 @@ be_dlopen_libs = libsane-abaton.la libsane-agfafocus.la \
libsane-coolscan2.la libsane-coolscan3.la libsane-dc25.la \
libsane-dc210.la libsane-dc240.la libsane-dell1600n_net.la \
libsane-dmc.la libsane-epjitsu.la libsane-epson.la \
- libsane-epson2.la libsane-fujitsu.la libsane-genesys.la \
+ libsane-epson2.la libsane-epsonds.la libsane-fujitsu.la libsane-genesys.la \
libsane-gphoto2.la libsane-gt68xx.la libsane-hp.la \
libsane-hp3500.la libsane-hp3900.la libsane-hp4200.la \
libsane-hp5400.la libsane-hp5590.la libsane-hpljm1005.la \
@@ -471,6 +471,19 @@ libsane_epson2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_epson2_la_LIBADD = $(COMMON_LIBS) libepson2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(SCSI_LIBS) $(USB_LIBS) $(SOCKET_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
EXTRA_DIST += epson2.conf.in
+libepsonds_la_SOURCES = epsonds.c epsonds.h epsonds-usb.c epsonds-usb.h epsonds-io.c epsonds-io.h \
+ epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h
+libepsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
+
+nodist_libsane_epsonds_la_SOURCES = epsonds-s.c
+libsane_epsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
+libsane_epsonds_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
+libsane_epsonds_la_LIBADD = $(COMMON_LIBS) libepsonds.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
+ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo \
+ ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \
+ @SANEI_SANEI_JPEG_LO@ $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
+EXTRA_DIST += epsonds.conf.in
+
libfujitsu_la_SOURCES = fujitsu.c fujitsu.h fujitsu-scsi.h
libfujitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=fujitsu
diff --git a/backend/Makefile.in b/backend/Makefile.in
index 3f7fa12..b688e93 100644
--- a/backend/Makefile.in
+++ b/backend/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -211,6 +211,12 @@ am_libepson2_la_OBJECTS = libepson2_la-epson2.lo \
libepson2_la-epson2-commands.lo libepson2_la-epson2-ops.lo \
libepson2_la-epson2-cct.lo
libepson2_la_OBJECTS = $(am_libepson2_la_OBJECTS)
+libepsonds_la_LIBADD =
+am_libepsonds_la_OBJECTS = libepsonds_la-epsonds.lo \
+ libepsonds_la-epsonds-usb.lo libepsonds_la-epsonds-io.lo \
+ libepsonds_la-epsonds-cmd.lo libepsonds_la-epsonds-ops.lo \
+ libepsonds_la-epsonds-jpeg.lo
+libepsonds_la_OBJECTS = $(am_libepsonds_la_OBJECTS)
libfujitsu_la_LIBADD =
am_libfujitsu_la_OBJECTS = libfujitsu_la-fujitsu.lo
libfujitsu_la_OBJECTS = $(am_libfujitsu_la_OBJECTS)
@@ -654,6 +660,18 @@ libsane_epson2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libsane_epson2_la_LDFLAGS) $(LDFLAGS) \
-o $@
+libsane_epsonds_la_DEPENDENCIES = $(COMMON_LIBS) libepsonds.la \
+ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
+ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \
+ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+nodist_libsane_epsonds_la_OBJECTS = libsane_epsonds_la-epsonds-s.lo
+libsane_epsonds_la_OBJECTS = $(nodist_libsane_epsonds_la_OBJECTS)
+libsane_epsonds_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libsane_epsonds_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
libsane_fujitsu_la_DEPENDENCIES = $(COMMON_LIBS) libfujitsu.la \
../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
../sanei/sanei_config.lo ../sanei/sanei_config2.lo \
@@ -1505,24 +1523,24 @@ SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_la_SOURCES) \
$(libdll_la_SOURCES) $(libdll_preload_la_SOURCES) \
$(libdmc_la_SOURCES) $(libepjitsu_la_SOURCES) \
$(libepson_la_SOURCES) $(libepson2_la_SOURCES) \
- $(libfujitsu_la_SOURCES) $(libgenesys_la_SOURCES) \
- $(libgphoto2_i_la_SOURCES) $(libgt68xx_la_SOURCES) \
- $(libhp_la_SOURCES) $(libhp3500_la_SOURCES) \
- $(libhp3900_la_SOURCES) $(libhp4200_la_SOURCES) \
- $(libhp5400_la_SOURCES) $(libhp5590_la_SOURCES) \
- $(libhpljm1005_la_SOURCES) $(libhpsj5s_la_SOURCES) \
- $(libhs2p_la_SOURCES) $(libibm_la_SOURCES) \
- $(libkodak_la_SOURCES) $(libkodakaio_la_SOURCES) \
- $(libkvs1025_la_SOURCES) $(libkvs20xx_la_SOURCES) \
- $(libkvs40xx_la_SOURCES) $(libleo_la_SOURCES) \
- $(liblexmark_la_SOURCES) $(libma1509_la_SOURCES) \
- $(libmagicolor_la_SOURCES) $(libmatsushita_la_SOURCES) \
- $(libmicrotek_la_SOURCES) $(libmicrotek2_la_SOURCES) \
- $(libmustek_la_SOURCES) $(libmustek_pp_la_SOURCES) \
- $(libmustek_usb_la_SOURCES) $(libmustek_usb2_la_SOURCES) \
- $(libnec_la_SOURCES) $(libnet_la_SOURCES) \
- $(libniash_la_SOURCES) $(libp5_la_SOURCES) \
- $(libpie_la_SOURCES) $(libpint_la_SOURCES) \
+ $(libepsonds_la_SOURCES) $(libfujitsu_la_SOURCES) \
+ $(libgenesys_la_SOURCES) $(libgphoto2_i_la_SOURCES) \
+ $(libgt68xx_la_SOURCES) $(libhp_la_SOURCES) \
+ $(libhp3500_la_SOURCES) $(libhp3900_la_SOURCES) \
+ $(libhp4200_la_SOURCES) $(libhp5400_la_SOURCES) \
+ $(libhp5590_la_SOURCES) $(libhpljm1005_la_SOURCES) \
+ $(libhpsj5s_la_SOURCES) $(libhs2p_la_SOURCES) \
+ $(libibm_la_SOURCES) $(libkodak_la_SOURCES) \
+ $(libkodakaio_la_SOURCES) $(libkvs1025_la_SOURCES) \
+ $(libkvs20xx_la_SOURCES) $(libkvs40xx_la_SOURCES) \
+ $(libleo_la_SOURCES) $(liblexmark_la_SOURCES) \
+ $(libma1509_la_SOURCES) $(libmagicolor_la_SOURCES) \
+ $(libmatsushita_la_SOURCES) $(libmicrotek_la_SOURCES) \
+ $(libmicrotek2_la_SOURCES) $(libmustek_la_SOURCES) \
+ $(libmustek_pp_la_SOURCES) $(libmustek_usb_la_SOURCES) \
+ $(libmustek_usb2_la_SOURCES) $(libnec_la_SOURCES) \
+ $(libnet_la_SOURCES) $(libniash_la_SOURCES) \
+ $(libp5_la_SOURCES) $(libpie_la_SOURCES) $(libpint_la_SOURCES) \
$(libpixma_la_SOURCES) $(libplustek_la_SOURCES) \
$(libplustek_pp_la_SOURCES) $(libpnm_la_SOURCES) \
$(libqcam_la_SOURCES) $(libricoh_la_SOURCES) \
@@ -1552,6 +1570,7 @@ SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_la_SOURCES) \
$(nodist_libsane_epjitsu_la_SOURCES) \
$(nodist_libsane_epson_la_SOURCES) \
$(nodist_libsane_epson2_la_SOURCES) \
+ $(nodist_libsane_epsonds_la_SOURCES) \
$(nodist_libsane_fujitsu_la_SOURCES) \
$(nodist_libsane_genesys_la_SOURCES) \
$(nodist_libsane_gphoto2_la_SOURCES) \
@@ -1638,24 +1657,24 @@ DIST_SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_la_SOURCES) \
$(libdll_la_SOURCES) $(libdll_preload_la_SOURCES) \
$(libdmc_la_SOURCES) $(libepjitsu_la_SOURCES) \
$(libepson_la_SOURCES) $(libepson2_la_SOURCES) \
- $(libfujitsu_la_SOURCES) $(libgenesys_la_SOURCES) \
- $(libgphoto2_i_la_SOURCES) $(libgt68xx_la_SOURCES) \
- $(libhp_la_SOURCES) $(libhp3500_la_SOURCES) \
- $(libhp3900_la_SOURCES) $(libhp4200_la_SOURCES) \
- $(libhp5400_la_SOURCES) $(libhp5590_la_SOURCES) \
- $(libhpljm1005_la_SOURCES) $(libhpsj5s_la_SOURCES) \
- $(libhs2p_la_SOURCES) $(libibm_la_SOURCES) \
- $(libkodak_la_SOURCES) $(libkodakaio_la_SOURCES) \
- $(libkvs1025_la_SOURCES) $(libkvs20xx_la_SOURCES) \
- $(libkvs40xx_la_SOURCES) $(libleo_la_SOURCES) \
- $(liblexmark_la_SOURCES) $(libma1509_la_SOURCES) \
- $(libmagicolor_la_SOURCES) $(libmatsushita_la_SOURCES) \
- $(libmicrotek_la_SOURCES) $(libmicrotek2_la_SOURCES) \
- $(libmustek_la_SOURCES) $(libmustek_pp_la_SOURCES) \
- $(libmustek_usb_la_SOURCES) $(libmustek_usb2_la_SOURCES) \
- $(libnec_la_SOURCES) $(libnet_la_SOURCES) \
- $(libniash_la_SOURCES) $(libp5_la_SOURCES) \
- $(libpie_la_SOURCES) $(libpint_la_SOURCES) \
+ $(libepsonds_la_SOURCES) $(libfujitsu_la_SOURCES) \
+ $(libgenesys_la_SOURCES) $(libgphoto2_i_la_SOURCES) \
+ $(libgt68xx_la_SOURCES) $(libhp_la_SOURCES) \
+ $(libhp3500_la_SOURCES) $(libhp3900_la_SOURCES) \
+ $(libhp4200_la_SOURCES) $(libhp5400_la_SOURCES) \
+ $(libhp5590_la_SOURCES) $(libhpljm1005_la_SOURCES) \
+ $(libhpsj5s_la_SOURCES) $(libhs2p_la_SOURCES) \
+ $(libibm_la_SOURCES) $(libkodak_la_SOURCES) \
+ $(libkodakaio_la_SOURCES) $(libkvs1025_la_SOURCES) \
+ $(libkvs20xx_la_SOURCES) $(libkvs40xx_la_SOURCES) \
+ $(libleo_la_SOURCES) $(liblexmark_la_SOURCES) \
+ $(libma1509_la_SOURCES) $(libmagicolor_la_SOURCES) \
+ $(libmatsushita_la_SOURCES) $(libmicrotek_la_SOURCES) \
+ $(libmicrotek2_la_SOURCES) $(libmustek_la_SOURCES) \
+ $(libmustek_pp_la_SOURCES) $(libmustek_usb_la_SOURCES) \
+ $(libmustek_usb2_la_SOURCES) $(libnec_la_SOURCES) \
+ $(libnet_la_SOURCES) $(libniash_la_SOURCES) \
+ $(libp5_la_SOURCES) $(libpie_la_SOURCES) $(libpint_la_SOURCES) \
$(libpixma_la_SOURCES) $(libplustek_la_SOURCES) \
$(libplustek_pp_la_SOURCES) $(libpnm_la_SOURCES) \
$(libqcam_la_SOURCES) $(libricoh_la_SOURCES) \
@@ -1916,31 +1935,32 @@ EXTRA_DIST = sane_strstatus.c stubs.c saned.conf.in abaton.conf.in \
cardscan.conf.in coolscan.conf.in coolscan2.conf.in \
coolscan3.conf.in dc25.conf.in dc210.conf.in dc240.conf.in \
dell1600n_net.conf.in dmc.conf.in epjitsu.conf.in \
- epson.conf.in epson2.conf.in fujitsu.conf.in genesys.conf.in \
- genesys_conv.c genesys_conv_hlp.c genesys_devices.c \
- gphoto2.conf.in gt68xx.conf.in gt68xx_devices.c \
- gt68xx_generic.c gt68xx_generic.h gt68xx_gt6801.c \
- gt68xx_gt6801.h gt68xx_gt6816.c gt68xx_gt6816.h gt68xx_high.c \
- gt68xx_high.h gt68xx_low.c gt68xx_low.h gt68xx_mid.c \
- gt68xx_mid.h gt68xx_shm_channel.c gt68xx_shm_channel.h \
- hp.conf.in hp.README hp.TODO hp3900.conf.in hp3900_config.c \
- hp3900_debug.c hp3900_rts8822.c hp3900_sane.c hp3900_types.c \
- hp3900_usb.c hp4200.conf.in hp4200_lm9830.c hp4200_lm9830.h \
- hp5400.conf.in hp5400_debug.c hp5400_debug.h hp5400_internal.c \
- hp5400_internal.h hp5400_sane.c hp5400_sanei.c hp5400_sanei.h \
- hp5400_xfer.h hp5590_cmds.c hp5590_cmds.h hp5590_low.c \
- hp5590_low.h hpsj5s.conf.in hs2p.conf.in hs2p-scsi.c \
- hs2p-scsi.h ibm.conf.in ibm-scsi.c kodak.conf.in \
- kodakaio.conf.in leo.conf.in lexmark.conf.in lexmark_models.c \
- lexmark_sensors.c ma1509.conf.in magicolor.conf.in \
- matsushita.conf.in microtek.conf.in microtek2.conf.in \
- mustek.conf.in mustek_scsi_pp.c mustek_scsi_pp.h \
- mustek_pp.conf.in mustek_pp_ccd300.c mustek_pp_ccd300.h \
- mustek_pp_cis.c mustek_pp_cis.h mustek_pp_null.c \
- mustek_usb.conf.in mustek_usb_high.c mustek_usb_high.h \
- mustek_usb_low.c mustek_usb_low.h mustek_usb_mid.c \
- mustek_usb_mid.h mustek_usb2_asic.c mustek_usb2_asic.h \
- mustek_usb2_high.c mustek_usb2_high.h mustek_usb2_reflective.c \
+ epson.conf.in epson2.conf.in epsonds.conf.in fujitsu.conf.in \
+ genesys.conf.in genesys_conv.c genesys_conv_hlp.c \
+ genesys_devices.c gphoto2.conf.in gt68xx.conf.in \
+ gt68xx_devices.c gt68xx_generic.c gt68xx_generic.h \
+ gt68xx_gt6801.c gt68xx_gt6801.h gt68xx_gt6816.c \
+ gt68xx_gt6816.h gt68xx_high.c gt68xx_high.h gt68xx_low.c \
+ gt68xx_low.h gt68xx_mid.c gt68xx_mid.h gt68xx_shm_channel.c \
+ gt68xx_shm_channel.h hp.conf.in hp.README hp.TODO \
+ hp3900.conf.in hp3900_config.c hp3900_debug.c hp3900_rts8822.c \
+ hp3900_sane.c hp3900_types.c hp3900_usb.c hp4200.conf.in \
+ hp4200_lm9830.c hp4200_lm9830.h hp5400.conf.in hp5400_debug.c \
+ hp5400_debug.h hp5400_internal.c hp5400_internal.h \
+ hp5400_sane.c hp5400_sanei.c hp5400_sanei.h hp5400_xfer.h \
+ hp5590_cmds.c hp5590_cmds.h hp5590_low.c hp5590_low.h \
+ hpsj5s.conf.in hs2p.conf.in hs2p-scsi.c hs2p-scsi.h \
+ ibm.conf.in ibm-scsi.c kodak.conf.in kodakaio.conf.in \
+ leo.conf.in lexmark.conf.in lexmark_models.c lexmark_sensors.c \
+ ma1509.conf.in magicolor.conf.in matsushita.conf.in \
+ microtek.conf.in microtek2.conf.in mustek.conf.in \
+ mustek_scsi_pp.c mustek_scsi_pp.h mustek_pp.conf.in \
+ mustek_pp_ccd300.c mustek_pp_ccd300.h mustek_pp_cis.c \
+ mustek_pp_cis.h mustek_pp_null.c mustek_usb.conf.in \
+ mustek_usb_high.c mustek_usb_high.h mustek_usb_low.c \
+ mustek_usb_low.h mustek_usb_mid.c mustek_usb_mid.h \
+ mustek_usb2_asic.c mustek_usb2_asic.h mustek_usb2_high.c \
+ mustek_usb2_high.h mustek_usb2_reflective.c \
mustek_usb2_transparent.c nec.conf.in net.conf.in niash_core.c \
niash_core.h niash_xfer.c niash_xfer.h pie.conf.in p5.conf.in \
p5_device.c pixma.conf.in pixma_sane_options.c \
@@ -1984,7 +2004,7 @@ BACKEND_CONFS = abaton.conf agfafocus.conf apple.conf artec.conf \
canon_pp.conf cardscan.conf coolscan2.conf coolscan3.conf \
coolscan.conf dc210.conf dc240.conf dc25.conf \
dell1600n_net.conf dmc.conf epjitsu.conf epson2.conf \
- epson.conf fujitsu.conf genesys.conf gphoto2.conf \
+ epson.conf epsonds.conf fujitsu.conf genesys.conf gphoto2.conf \
gt68xx.conf hp3900.conf hp4200.conf hp5400.conf \
hp.conf hpsj5s.conf hs2p.conf ibm.conf kodak.conf kodakaio.conf\
leo.conf lexmark.conf ma1509.conf magicolor.conf \
@@ -2020,7 +2040,7 @@ be_convenience_libs = libabaton.la libagfafocus.la \
libcoolscan2.la libcoolscan3.la libdc25.la \
libdc210.la libdc240.la libdell1600n_net.la \
libdmc.la libdll.la libdll_preload.la libepjitsu.la libepson.la \
- libepson2.la libfujitsu.la libgenesys.la \
+ libepson2.la libepsonds.la libfujitsu.la libgenesys.la \
libgphoto2_i.la libgt68xx.la libhp.la \
libhp3500.la libhp3900.la libhp4200.la \
libhp5400.la libhp5590.la libhpljm1005.la \
@@ -2054,7 +2074,7 @@ be_dlopen_libs = libsane-abaton.la libsane-agfafocus.la \
libsane-coolscan2.la libsane-coolscan3.la libsane-dc25.la \
libsane-dc210.la libsane-dc240.la libsane-dell1600n_net.la \
libsane-dmc.la libsane-epjitsu.la libsane-epson.la \
- libsane-epson2.la libsane-fujitsu.la libsane-genesys.la \
+ libsane-epson2.la libsane-epsonds.la libsane-fujitsu.la libsane-genesys.la \
libsane-gphoto2.la libsane-gt68xx.la libsane-hp.la \
libsane-hp3500.la libsane-hp3900.la libsane-hp4200.la \
libsane-hp5400.la libsane-hp5590.la libsane-hpljm1005.la \
@@ -2244,6 +2264,18 @@ nodist_libsane_epson2_la_SOURCES = epson2-s.c
libsane_epson2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson2
libsane_epson2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_epson2_la_LIBADD = $(COMMON_LIBS) libepson2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(SCSI_LIBS) $(USB_LIBS) $(SOCKET_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
+libepsonds_la_SOURCES = epsonds.c epsonds.h epsonds-usb.c epsonds-usb.h epsonds-io.c epsonds-io.h \
+ epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h
+
+libepsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
+nodist_libsane_epsonds_la_SOURCES = epsonds-s.c
+libsane_epsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
+libsane_epsonds_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
+libsane_epsonds_la_LIBADD = $(COMMON_LIBS) libepsonds.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
+ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo \
+ ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \
+ @SANEI_SANEI_JPEG_LO@ $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
+
libfujitsu_la_SOURCES = fujitsu.c fujitsu.h fujitsu-scsi.h
libfujitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=fujitsu
nodist_libsane_fujitsu_la_SOURCES = fujitsu-s.c
@@ -2848,6 +2880,9 @@ libepson.la: $(libepson_la_OBJECTS) $(libepson_la_DEPENDENCIES) $(EXTRA_libepson
libepson2.la: $(libepson2_la_OBJECTS) $(libepson2_la_DEPENDENCIES) $(EXTRA_libepson2_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(libepson2_la_OBJECTS) $(libepson2_la_LIBADD) $(LIBS)
+libepsonds.la: $(libepsonds_la_OBJECTS) $(libepsonds_la_DEPENDENCIES) $(EXTRA_libepsonds_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libepsonds_la_OBJECTS) $(libepsonds_la_LIBADD) $(LIBS)
+
libfujitsu.la: $(libfujitsu_la_OBJECTS) $(libfujitsu_la_DEPENDENCIES) $(EXTRA_libfujitsu_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(libfujitsu_la_OBJECTS) $(libfujitsu_la_LIBADD) $(LIBS)
@@ -3055,6 +3090,9 @@ libsane-epson.la: $(libsane_epson_la_OBJECTS) $(libsane_epson_la_DEPENDENCIES) $
libsane-epson2.la: $(libsane_epson2_la_OBJECTS) $(libsane_epson2_la_DEPENDENCIES) $(EXTRA_libsane_epson2_la_DEPENDENCIES)
$(AM_V_CCLD)$(libsane_epson2_la_LINK) $(libsane_epson2_la_OBJECTS) $(libsane_epson2_la_LIBADD) $(LIBS)
+libsane-epsonds.la: $(libsane_epsonds_la_OBJECTS) $(libsane_epsonds_la_DEPENDENCIES) $(EXTRA_libsane_epsonds_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libsane_epsonds_la_LINK) $(libsane_epsonds_la_OBJECTS) $(libsane_epsonds_la_LIBADD) $(LIBS)
+
libsane-fujitsu.la: $(libsane_fujitsu_la_OBJECTS) $(libsane_fujitsu_la_DEPENDENCIES) $(EXTRA_libsane_fujitsu_la_DEPENDENCIES)
$(AM_V_CCLD)$(libsane_fujitsu_la_LINK) $(libsane_fujitsu_la_OBJECTS) $(libsane_fujitsu_la_LIBADD) $(LIBS)
@@ -3347,6 +3385,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson_la-epson.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson_la-epson_scsi.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson_la-epson_usb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-cmd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-io.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-jpeg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-ops.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-usb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfujitsu_la-fujitsu.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_gl124.Plo@am__quote@
@@ -3446,6 +3490,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epjitsu_la-epjitsu-s.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epson2_la-epson2-s.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epson_la-epson-s.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epsonds_la-epsonds-s.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_genesys_la-genesys-s.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_gphoto2_la-gphoto2-s.Plo@am__quote@
@@ -3539,14 +3584,14 @@ distclean-compile:
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -3814,6 +3859,48 @@ libepson2_la-epson2-cct.lo: epson2-cct.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2-cct.lo `test -f 'epson2-cct.c' || echo '$(srcdir)/'`epson2-cct.c
+libepsonds_la-epsonds.lo: epsonds.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds.Tpo -c -o libepsonds_la-epsonds.lo `test -f 'epsonds.c' || echo '$(srcdir)/'`epsonds.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds.Tpo $(DEPDIR)/libepsonds_la-epsonds.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds.c' object='libepsonds_la-epsonds.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds.lo `test -f 'epsonds.c' || echo '$(srcdir)/'`epsonds.c
+
+libepsonds_la-epsonds-usb.lo: epsonds-usb.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-usb.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-usb.Tpo -c -o libepsonds_la-epsonds-usb.lo `test -f 'epsonds-usb.c' || echo '$(srcdir)/'`epsonds-usb.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-usb.Tpo $(DEPDIR)/libepsonds_la-epsonds-usb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-usb.c' object='libepsonds_la-epsonds-usb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-usb.lo `test -f 'epsonds-usb.c' || echo '$(srcdir)/'`epsonds-usb.c
+
+libepsonds_la-epsonds-io.lo: epsonds-io.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-io.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-io.Tpo -c -o libepsonds_la-epsonds-io.lo `test -f 'epsonds-io.c' || echo '$(srcdir)/'`epsonds-io.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-io.Tpo $(DEPDIR)/libepsonds_la-epsonds-io.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-io.c' object='libepsonds_la-epsonds-io.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-io.lo `test -f 'epsonds-io.c' || echo '$(srcdir)/'`epsonds-io.c
+
+libepsonds_la-epsonds-cmd.lo: epsonds-cmd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-cmd.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-cmd.Tpo -c -o libepsonds_la-epsonds-cmd.lo `test -f 'epsonds-cmd.c' || echo '$(srcdir)/'`epsonds-cmd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-cmd.Tpo $(DEPDIR)/libepsonds_la-epsonds-cmd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-cmd.c' object='libepsonds_la-epsonds-cmd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-cmd.lo `test -f 'epsonds-cmd.c' || echo '$(srcdir)/'`epsonds-cmd.c
+
+libepsonds_la-epsonds-ops.lo: epsonds-ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-ops.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-ops.Tpo -c -o libepsonds_la-epsonds-ops.lo `test -f 'epsonds-ops.c' || echo '$(srcdir)/'`epsonds-ops.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-ops.Tpo $(DEPDIR)/libepsonds_la-epsonds-ops.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-ops.c' object='libepsonds_la-epsonds-ops.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-ops.lo `test -f 'epsonds-ops.c' || echo '$(srcdir)/'`epsonds-ops.c
+
+libepsonds_la-epsonds-jpeg.lo: epsonds-jpeg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-jpeg.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-jpeg.Tpo -c -o libepsonds_la-epsonds-jpeg.lo `test -f 'epsonds-jpeg.c' || echo '$(srcdir)/'`epsonds-jpeg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-jpeg.Tpo $(DEPDIR)/libepsonds_la-epsonds-jpeg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-jpeg.c' object='libepsonds_la-epsonds-jpeg.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-jpeg.lo `test -f 'epsonds-jpeg.c' || echo '$(srcdir)/'`epsonds-jpeg.c
+
libfujitsu_la-fujitsu.lo: fujitsu.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfujitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libfujitsu_la-fujitsu.lo -MD -MP -MF $(DEPDIR)/libfujitsu_la-fujitsu.Tpo -c -o libfujitsu_la-fujitsu.lo `test -f 'fujitsu.c' || echo '$(srcdir)/'`fujitsu.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfujitsu_la-fujitsu.Tpo $(DEPDIR)/libfujitsu_la-fujitsu.Plo
@@ -4507,6 +4594,13 @@ libsane_epson2_la-epson2-s.lo: epson2-s.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_epson2_la-epson2-s.lo `test -f 'epson2-s.c' || echo '$(srcdir)/'`epson2-s.c
+libsane_epsonds_la-epsonds-s.lo: epsonds-s.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_epsonds_la-epsonds-s.lo -MD -MP -MF $(DEPDIR)/libsane_epsonds_la-epsonds-s.Tpo -c -o libsane_epsonds_la-epsonds-s.lo `test -f 'epsonds-s.c' || echo '$(srcdir)/'`epsonds-s.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_epsonds_la-epsonds-s.Tpo $(DEPDIR)/libsane_epsonds_la-epsonds-s.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-s.c' object='libsane_epsonds_la-epsonds-s.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_epsonds_la-epsonds-s.lo `test -f 'epsonds-s.c' || echo '$(srcdir)/'`epsonds-s.c
+
libsane_fujitsu_la-fujitsu-s.lo: fujitsu-s.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_fujitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_fujitsu_la-fujitsu-s.lo -MD -MP -MF $(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Tpo -c -o libsane_fujitsu_la-fujitsu-s.lo `test -f 'fujitsu-s.c' || echo '$(srcdir)/'`fujitsu-s.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Tpo $(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Plo
diff --git a/backend/avision.c b/backend/avision.c
index 74ffe80..146125c 100644
--- a/backend/avision.c
+++ b/backend/avision.c
@@ -39,25 +39,22 @@
*****************************************************************************
- This backend is based upon the Tamarack backend and adapted to the Avision
- scanners by René Rebe and Meino Cramer.
-
This file implements a SANE backend for the Avision SCSI Scanners (like the
AV 630 / 620 (CS) ...) and some Avision (OEM) USB scanners (like the HP 53xx,
74xx, Minolta FS-V1 ...) or Fujitsu ScanPartner with the AVISION SCSI-2/3
- or USB command set.
+ or USB command set and written by René Rebe and Meino Cramer.
+
+ Copyright 2002 - 2015 by
+ "Ren Rebe" <rene@exactcode.de>
+
Copyright 1999, 2000, 2001 by
"René Rebe" <rene@exactcode.de>
"Meino Christian Cramer" <mccramer@s.netic.de>
Copyright 2002 by
- "René Rebe" <rene@exactcode.de>
"Jose Paulo Moitinho de Almeida" <moitinho@civil.ist.utl.pt>
- Copyright 2003, 2004, 2005, 2006, 2007 by
- "René Rebe" <rene@exactcode.de>
-
Copyright 2010, 2011 by
"Mike Kelly" <mike@piratehaven.org>
@@ -167,444 +164,451 @@ static Avision_HWEntry Avision_Device_List [] =
{ "AVISION", "AV100CS",
0, 0,
"Avision", "AV100CS",
- 0,0},
+ 0},
/* status="untested" */
{ "AVISION", "AV100IIICS",
0, 0,
"Avision", "AV100IIICS",
- 0,0},
+ 0},
/* status="untested" */
{ "AVISION", "AV100S",
0, 0,
"Avision", "AV100S",
- 0,0},
+ 0},
/* status="untested" */
{ NULL, NULL,
0x0638, 0x0A27,
"Avision", "AV120",
- AV_INT_STATUS,0},
+ AV_INT_STATUS},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A3C,
"Avision", "AV121",
- AV_INT_BUTTON | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA,0},
+ AV_INT_BUTTON | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA},
/* comment="sheetfed scanner" */
/* status="good" */
{ NULL, NULL,
0x0638, 0x0A33,
"Avision", "AV122",
- AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET,0},
+ AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET},
/* comment="sheetfed duplex scanner" */
/* status="good" */
{ NULL, NULL,
0x0638, 0x0A93,
"Avision", "AV122 C2",
- AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_NOT_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET,0},
+ AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_NOT_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET},
/* comment="sheetfed duplex scanner" */
/* status="good" */
{ NULL, NULL,
0x0638, 0x0A24,
"Avision", "AV210",
- AV_INT_BUTTON | AV_ACCEL_TABLE,0},
+ AV_INT_BUTTON | AV_ACCEL_TABLE},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A25,
"Avision", "AV210",
- AV_INT_BUTTON | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN,0},
+ AV_INT_BUTTON | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A3A,
"Avision", "AV210C2",
- AV_INT_BUTTON | AV_GRAY_MODES,0},
+ AV_INT_BUTTON | AV_GRAY_MODES},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A2F,
"Avision", "AV210C2-G",
- AV_INT_BUTTON | AV_GRAY_MODES,0},
+ AV_INT_BUTTON | AV_GRAY_MODES},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x1A35,
"Avision", "AV210D2+",
- AV_INT_BUTTON, AV_USE_GRAY_FILTER},
+ AV_INT_BUTTON | AV_USE_GRAY_FILTER},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A23,
"Avision", "AV220",
- AV_INT_BUTTON | AV_GRAY_MODES,0},
+ AV_INT_BUTTON | AV_GRAY_MODES},
/* comment="duplex! sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A2A,
"Avision", "AV220C2",
- AV_INT_BUTTON | AV_CANCEL_BUTTON,0},
+ AV_INT_BUTTON | AV_CANCEL_BUTTON},
/* comment="duplex! sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A2B,
"Avision", "AV220D2",
- AV_INT_BUTTON | AV_CANCEL_BUTTON,0},
+ AV_INT_BUTTON | AV_CANCEL_BUTTON},
+ /* comment="duplex! sheetfed scanner" */
+ /* status="complete" */
+
+ { NULL, NULL,
+ 0x0638, 0x1A31,
+ "Avision", "AV220D2+",
+ AV_INT_BUTTON | AV_CANCEL_BUTTON | AV_USE_GRAY_FILTER},
/* comment="duplex! sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A2C,
"Avision", "AV220+",
- AV_INT_BUTTON | AV_CANCEL_BUTTON,0},
+ AV_INT_BUTTON | AV_CANCEL_BUTTON},
/* comment="duplex! sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A2D,
"Avision", "AV220C2-G",
- AV_INT_BUTTON | AV_CANCEL_BUTTON,0},
+ AV_INT_BUTTON | AV_CANCEL_BUTTON},
/* comment="duplex! sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A2E,
"Avision", "AV220C2-B",
- AV_INT_BUTTON | AV_CANCEL_BUTTON,0},
+ AV_INT_BUTTON | AV_CANCEL_BUTTON},
/* comment="duplex! sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A94,
"Avision", "AV220-G",
- AV_INT_BUTTON | AV_2ND_LINE_INTERLACED, AV_FIRMWARE},
+ AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_FIRMWARE},
/* comment="duplex! sheetfed scanner" */
/* status="complete" */
{ "AVISION", "AV240SC",
0, 0,
"Avision", "AV240SC",
- 0,0},
+ 0},
/* status="untested" */
{ "AVISION", "AV260CS",
0, 0,
"Avision", "AV260CS",
- 0,0},
+ 0},
/* status="untested" */
{ "AVISION", "AV360CS",
0, 0,
"Avision", "AV360CS",
- 0,0},
+ 0},
/* status="untested" */
{ "AVISION", "AV363CS",
0, 0,
"Avision", "AV363CS",
- 0,0},
+ 0},
/* status="untested" */
{ "AVISION", "AV420CS",
0, 0,
"Avision", "AV420CS",
- 0,0},
+ 0},
/* status="untested" */
{ "AVISION", "AV6120",
0, 0,
"Avision", "AV6120",
- 0,0},
+ 0},
/* status="untested" */
{ NULL, "AV610",
0x0638, 0x0a18,
"Avision", "AV610",
- AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_BUTTON, 0},
+ AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x0638, 0x0a18,
"Avision", "AV600U Plus",
/* If this unit requires the AV_INT_STATUS flag, then we'll need to alter the code to deal with two different devices with the same USB id (AV610 above) */
- AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | /* AV_INT_STATUS | */ AV_INT_BUTTON,0},
+ AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | /* AV_INT_STATUS | */ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x0638, 0x0a5e,
"Avision", "AV610C2",
- AV_NO_BACKGROUND | AV_INT_BUTTON,0}, /* cancel button -> sense abort! */
+ AV_NO_BACKGROUND | AV_INT_BUTTON}, /* cancel button -> sense abort! */
/* status="good" */
{ NULL, NULL,
0x0638, 0x0a41,
"Avision", "AM3000 Series",
- 0,0},
+ 0},
/* comment="MFD" */
/* status="basic" */
{ NULL, NULL,
0x0638, 0x0a16,
"Avision", "DS610CU Scancopier",
- AV_INT_STATUS,0},
+ AV_INT_STATUS},
/* comment="1 pass, 600 dpi, A4" */
/* status="good" */
{ "AVISION", "AV620CS",
0, 0,
"Avision", "AV620CS",
- 0,0},
+ 0},
/* comment="1 pass, 600 dpi" */
/* status="complete" */
{ "AVISION", "AV620CS Plus",
0, 0,
"Avision", "AV620CS Plus",
- 0,0},
+ 0},
/* comment="1 pass, 1200 dpi" */
/* status="complete" */
{ "AVISION", "AV630CS",
0, 0,
"Avision", "AV630CS",
- 0,0},
+ 0},
/* comment="1 pass, 1200 dpi" */
/* status="complete" */
{ "AVISION", "AV630CSL",
0, 0,
"Avision", "AV630CSL",
- 0,0},
+ 0},
/* comment="1 pass, 1200 dpi" */
/* status="untested" */
{ "AVISION", "AV6240",
0, 0,
"Avision", "AV6240",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A13,
"Avision", "AV600U",
- AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_SOFT_SCALE | AV_INT_STATUS | AV_NO_BUTTON,0},
+ AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_SOFT_SCALE | AV_INT_STATUS | AV_NO_BUTTON},
/* comment="1 pass, 600 dpi" */
/* status="good" */
{ "AVISION", "AV660S",
0, 0,
"Avision", "AV660S",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV680S",
0, 0,
"Avision", "AV680S",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV690U",
0, 0,
"Avision", "AV690U",
- 0,0},
+ 0},
/* comment="1 pass, 2400 dpi" */
/* status="untested" */
{ "AVISION", "AV800S",
0, 0,
"Avision", "AV800S",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV810C",
0, 0,
"Avision", "AV810C",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV820",
0, 0,
"Avision", "AV820",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV820C",
0, 0,
"Avision", "AV820C",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV820C Plus",
0, 0,
"Avision", "AV820C Plus",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV830C",
0, 0,
"Avision", "AV830C",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV830C Plus",
0, 0,
"Avision", "AV830C Plus",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV880",
0, 0,
"Avision", "AV880",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV880C",
0, 0,
"Avision", "AV880C",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="untested" */
{ "AVISION", "AV3200C",
0, 0,
"Avision", "AV3200C",
- AV_NON_INTERLACED_DUPLEX_300 | AV_FASTER_WITH_FILTER,0},
+ AV_NON_INTERLACED_DUPLEX_300 | AV_FASTER_WITH_FILTER},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV3200SU",
0x0638, 0x0A4E,
"Avision", "AV3200SU",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV3730SU",
0x0638, 0x0A4F,
"Avision", "AV3730SU",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV3750SU",
0x0638, 0x0A65,
"Avision", "AV3750SU",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV3800C",
0, 0,
"Avision", "AV3800C",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "AV3850SU",
0x0638, 0x0a66,
"Avision", "AV3850SU",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi" */
/* status="complete" */
{ "AVISION", "FB6000E",
0, 0,
"Avision", "FB6000E",
- AV_NON_INTERLACED_DUPLEX_300,0},
+ AV_NON_INTERLACED_DUPLEX_300},
/* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0a82,
"Avision", "FB6080E",
- AV_NON_INTERLACED_DUPLEX_300,0},
+ AV_NON_INTERLACED_DUPLEX_300},
/* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0a84,
"Avision", "FB2080E",
- 0,0},
+ 0},
/* comment="1 pass, 600 dpi, zero-edge" ASIC 7 */
/* status="basic" */
{ "AVISION", "AV8000S",
0, 0,
"Avision", "AV8000S",
- AV_DOES_NOT_KEEP_WINDOW,0},
+ AV_DOES_NOT_KEEP_WINDOW},
/* comment="1 pass, 1200 dpi, A3" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0a4d,
"Avision", "AV8050U",
- AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA,0},
+ AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA},
/* comment="1 pass, 1200 dpi, A3 - duplex!" */
/* status="complete" */
{ "AVISION", "AV8300",
0x0638, 0x0A40,
"Avision", "AV8300",
- AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA,0},
+ AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA},
/* comment="1 pass, 1200 dpi, A3 - duplex!" */
/* status="complete" */
{ "AVISION", "AV8350",
0x0638, 0x0A68,
"Avision", "AV8350",
- AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA,0},
+ AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA},
/* comment="1 pass, 1200 dpi, A3 - duplex!" */
/* status="complete" */
{ NULL, NULL,
0x0638, 0x0A61,
"Avision", "IT8300",
- AV_NON_INTERLACED_DUPLEX_300 | AV_ACCEL_TABLE,0},
+ AV_NON_INTERLACED_DUPLEX_300 | AV_ACCEL_TABLE},
/* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */
/* status="good" */
{ NULL, NULL,
0x0638, 0x0AA1,
"Avision", "@V2500",
- 0,0},
+ 0},
/* comment="" */
/* status="untested" */
{ NULL, NULL,
0x0638, 0x0A45,
"Avision", "@V5100",
- 0,0},
+ 0},
/* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */
/* status="good" */
{ "AVISION", "AVA3",
0, 0,
"Avision", "AVA3",
- AV_FORCE_A3,0},
+ AV_FORCE_A3},
/* comment="1 pass, 600 dpi, A3" */
/* status="basic" */
@@ -613,21 +617,21 @@ static Avision_HWEntry Avision_Device_List [] =
{ "HP", "ScanJet 5300C",
0x03f0, 0x0701,
"Hewlett-Packard", "ScanJet 5300C",
- AV_INT_STATUS,0},
+ AV_INT_STATUS},
/* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */
/* status="complete" */
{ "HP", "ScanJet 5370C",
0x03f0, 0x0701,
"Hewlett-Packard", "ScanJet 5370C",
- AV_MULTI_CALIB_CMD | AV_INT_STATUS, 0 },
+ AV_MULTI_CALIB_CMD | AV_INT_STATUS},
/* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */
/* status="good" */
{ "hp", "scanjet 7400c",
0x03f0, 0x0801,
"Hewlett-Packard", "ScanJet 7400c",
- AV_LIGHT_CHECK_BOGUS | AV_NO_64BYTE_ALIGN | AV_INT_STATUS,0},
+ AV_LIGHT_CHECK_BOGUS | AV_NO_64BYTE_ALIGN | AV_INT_STATUS},
/* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */
/* status="good" */
@@ -635,14 +639,14 @@ static Avision_HWEntry Avision_Device_List [] =
{ "hp", "scanjet 7450c",
0x03f0, 0x0801,
"Hewlett-Packard", "ScanJet 7450c",
- AV_NO_64BYTE_ALIGN | AV_INT_STATUS,0},
+ AV_NO_64BYTE_ALIGN | AV_INT_STATUS},
/* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */
/* status="good" */
{ "hp", "scanjet 7490c",
0x03f0, 0x0801,
"Hewlett-Packard", "ScanJet 7490c",
- AV_NO_64BYTE_ALIGN | AV_INT_STATUS,0},
+ AV_NO_64BYTE_ALIGN | AV_INT_STATUS},
/* comment="1 pass, 1200 dpi - dual USB/SCSI interface" */
/* status="good" */
@@ -650,7 +654,7 @@ static Avision_HWEntry Avision_Device_List [] =
{ "HP", "C9930A",
0x03f0, 0x0b01,
"Hewlett-Packard", "ScanJet 8200",
- 0, AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE },
+ AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE},
/* comment="1 pass, 4800 (?) dpi - USB 2.0" */
/* status="good" */
@@ -658,7 +662,7 @@ static Avision_HWEntry Avision_Device_List [] =
{ "HP", "C9930A",
0x03f0, 0x0b01,
"Hewlett-Packard", "ScanJet 8250",
- 0, AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE },
+ AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE},
/* comment="1 pass, 4800 (?) dpi - USB 2.0" */
/* status="good" */
#endif
@@ -666,7 +670,7 @@ static Avision_HWEntry Avision_Device_List [] =
{ "HP", "C9930A",
0x03f0, 0x3905,
"Hewlett-Packard", "ScanJet 8270",
- 0, AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE },
+ AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE},
/* comment="1 pass, 4800 (?) dpi - USB 2.0" */
/* status="good" */
@@ -674,7 +678,7 @@ static Avision_HWEntry Avision_Device_List [] =
{ "HP", "C9930A",
0x03f0, 0x0b01,
"Hewlett-Packard", "ScanJet 8290",
- 0, AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE },
+ AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE},
/* comment="1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far" */
/* status="good" */
@@ -682,7 +686,7 @@ static Avision_HWEntry Avision_Device_List [] =
{ "HP", "C9930A",
0x03f0, 0x3805,
"Hewlett-Packard", "ScanJet 8300",
- 0,0},
+ 0},
/* comment="1 pass, 4800 (?) dpi - USB 2.0" */
/* status="good" */
@@ -690,14 +694,14 @@ static Avision_HWEntry Avision_Device_List [] =
{ "HP", "C9930A",
0x03f0, 0x3805,
"Hewlett-Packard", "ScanJet 8350",
- 0,0},
+ 0},
/* comment="1 pass, 4800 (?) dpi - USB 2.0" */
/* status="good" */
{ "HP", "C9930A",
0x03f0, 0x3805,
"Hewlett-Packard", "ScanJet 8390",
- 0,0},
+ 0},
/* comment="1 pass, 4800 (?) dpi - USB 2.0" */
/* status="good" */
@@ -705,79 +709,79 @@ static Avision_HWEntry Avision_Device_List [] =
{ "Minolta", "#2882",
0, 0,
"Minolta", "Dimage Scan Dual I",
- AV_FORCE_FILM | AV_NO_START_SCAN,0}, /* not AV_FILMSCANNER (no frame control) */
+ AV_FORCE_FILM | AV_NO_START_SCAN}, /* not AV_FILMSCANNER (no frame control) */
/* status="basic" */
{ "Minolta", "#2887",
0, 0,
"Minolta", "Scan Multi Pro",
- AV_FORCE_FILM | AV_NO_START_SCAN,0}, /* AV_FILMSCANNER (frame control)? */
+ AV_FORCE_FILM | AV_NO_START_SCAN}, /* AV_FILMSCANNER (frame control)? */
/* status="untested" */
{ "MINOLTA", "FS-V1",
0x0638, 0x026a,
"Minolta", "Dimage Scan Dual II",
- AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_12_BIT_MODE,0},
+ AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_12_BIT_MODE},
/* comment="1 pass, film-scanner" */
/* status="good" */
{ "MINOLTA", "Elite II",
0x0686, 0x4004,
"Minolta", "Elite II",
- AV_FILMSCANNER | AV_ONE_CALIB_CMD,0},
+ AV_FILMSCANNER | AV_ONE_CALIB_CMD},
/* comment="1 pass, film-scanner" */
/* status="untested" */
{ "MINOLTA", "FS-V3",
0x0686, 0x400d,
"Minolta", "Dimage Scan Dual III",
- AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_ACCEL_TABLE ,0},
+ AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_ACCEL_TABLE},
/* comment="1 pass, film-scanner" */
/* status="good" */
{ "MINOLTA", "FS-V4",
0x0686, 0x400e,
"Minolta", "Dimage Scan Elite 5400",
- AV_FILMSCANNER | AV_ONE_CALIB_CMD | /*AV_ACCEL_TABLE |*/ AV_NO_START_SCAN,0},
+ AV_FILMSCANNER | AV_ONE_CALIB_CMD | /*AV_ACCEL_TABLE |*/ AV_NO_START_SCAN},
/* comment="1 pass, film-scanner" */
/* status="good" */
{ "QMS", "SC-110",
0x0638, 0x0a15,
"Minolta-QMS", "SC-110",
- 0,0},
+ 0},
/* comment="" */
/* status="untested" */
{ "QMS", "SC-215",
0x0638, 0x0a16,
"Minolta-QMS", "SC-215",
- 0,0},
+ 0},
/* comment="" */
/* status="good" */
{ "MITSBISH", "MCA-ADFC",
0, 0,
"Mitsubishi", "MCA-ADFC",
- 0,0},
+ 0},
/* status="untested" */
{ "MITSBISH", "MCA-S1200C",
0, 0,
"Mitsubishi", "S1200C",
- 0,0},
+ 0},
/* status="untested" */
{ "MITSBISH", "MCA-S600C",
0, 0,
"Mitsubishi", "S600C",
- 0,0},
+ 0},
/* status="untested" */
{ "MITSBISH", "SS600",
0, 0,
"Mitsubishi", "SS600",
- 0,0},
+ 0},
/* status="good" */
/* The next are all untested ... */
@@ -785,209 +789,209 @@ static Avision_HWEntry Avision_Device_List [] =
{ "FCPA", "ScanPartner",
0, 0,
"Fujitsu", "ScanPartner",
- AV_FUJITSU,0},
+ AV_FUJITSU},
/* status="untested" */
{ "FCPA", "ScanPartner 10",
0, 0,
"Fujitsu", "ScanPartner 10",
- AV_FUJITSU,0},
+ AV_FUJITSU},
/* status="untested" */
{ "FCPA", "ScanPartner 10C",
0, 0,
"Fujitsu", "ScanPartner 10C",
- AV_FUJITSU,0},
+ AV_FUJITSU},
/* status="untested" */
{ "FCPA", "ScanPartner 15C",
0, 0,
"Fujitsu", "ScanPartner 15C",
- AV_FUJITSU,0},
+ AV_FUJITSU},
/* status="untested" */
{ "FCPA", "ScanPartner 300C",
0, 0,
"Fujitsu", "ScanPartner 300C",
- 0,0},
+ 0},
/* status="untested" */
{ "FCPA", "ScanPartner 600C",
0, 0,
"Fujitsu", "ScanPartner 600C",
- 0,0},
+ 0},
/* status="untested" */
{ "FCPA", "ScanPartner 620C",
0, 0,
"Fujitsu", "ScanPartner 620C",
- AV_LIGHT_CHECK_BOGUS,0},
+ AV_LIGHT_CHECK_BOGUS},
/* status="good" */
{ "FCPA", "ScanPartner Jr",
0, 0,
"Fujitsu", "ScanPartner Jr",
- 0,0},
+ 0},
/* status="untested" */
{ "FCPA", "ScanStation",
0, 0,
"Fujitsu", "ScanStation",
- 0,0},
+ 0},
/* status="untested" */
{ NULL, NULL,
0x04c5, 0x1029,
"Fujitsu", "fi-4010CU",
- 0,0},
+ 0},
/* status="untested" */
{ NULL, NULL,
0x04c5, 0x10ef,
"Fujitsu", "fi-5015C",
- 0,0},
+ 0},
/* status="good" */
{ NULL, NULL,
0x040a, 0x6001,
"Kodak", "i30",
- AV_INT_BUTTON | AV_GRAY_MODES,0},
+ AV_INT_BUTTON | AV_GRAY_MODES},
/* status="untested" */
{ NULL, NULL,
0x040a, 0x6002,
"Kodak", "i40",
- AV_INT_BUTTON | AV_GRAY_MODES,0},
+ AV_INT_BUTTON | AV_GRAY_MODES},
/* status="basic" */
{ NULL, NULL,
0x040a, 0x6003,
"Kodak", "i50",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
#ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
{ NULL, NULL,
0x040a, 0x6003,
"Kodak", "i55",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
#endif
{ NULL, NULL,
0x040a, 0x6004,
"Kodak", "i60",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
#ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
{ NULL, NULL,
0x040a, 0x6004,
"Kodak", "i65",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
#endif
{ NULL, NULL,
0x040a, 0x6005,
"Kodak", "i80",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ "iVina", "1200U",
0x0638, 0x0268,
"iVina", "1200U",
- 0,0},
+ 0},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x0424,
"Visioneer", "Strobe XP 450",
- AV_INT_BUTTON | AV_ACCEL_TABLE,0},
+ AV_INT_BUTTON | AV_ACCEL_TABLE},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0491,
"Visioneer", "Strobe XP 450-G",
- AV_INT_BUTTON | AV_ACCEL_TABLE,0},
+ AV_INT_BUTTON | AV_ACCEL_TABLE},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0479,
"Visioneer", "Strobe XP 470",
- AV_INT_BUTTON | AV_ACCEL_TABLE,0},
+ AV_INT_BUTTON | AV_ACCEL_TABLE},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x048F,
"Visioneer", "Strobe XP 470-G",
- AV_INT_BUTTON | AV_ACCEL_TABLE,0},
+ AV_INT_BUTTON | AV_ACCEL_TABLE},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0420,
"Visioneer", "9320",
- 0,0},
+ 0},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0421,
"Visioneer", "9450",
- AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_NO_BUTTON, AV_NO_TUNE_SCAN_LENGTH},
+ AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_NO_BUTTON | AV_NO_TUNE_SCAN_LENGTH},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x047A,
"Visioneer", "9450-G",
- 0,0},
+ 0},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0422,
"Visioneer", "9550",
- 0,0},
+ 0},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0390,
"Visioneer", "9650",
- 0,0},
+ 0},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x047B,
"Visioneer", "9650-G",
- 0,0},
+ 0},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0423,
"Visioneer", "9750",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0493,
"Visioneer", "9750-G",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0497,
"Visioneer", "Patriot 430",
- AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET,0},
+ AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET},
/* comment="sheetfed scanner" */
/* status="complete" */
@@ -995,7 +999,7 @@ static Avision_HWEntry Avision_Device_List [] =
{ NULL, NULL,
0x04a7, 0x048F,
"Visioneer", "Patriot 470",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* comment="sheetfed scanner" */
/* status="complete" */
#endif
@@ -1003,150 +1007,150 @@ static Avision_HWEntry Avision_Device_List [] =
{ NULL, NULL,
0x04a7, 0x0498,
"Visioneer", "Patriot 680",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x0499,
"Visioneer", "Patriot 780",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* comment="sheetfed scanner" */
/* status="complete" */
{ NULL, NULL,
0x04a7, 0x049C,
"Xerox", "DocuMate150",
- AV_INT_BUTTON | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK,0},
+ AV_INT_BUTTON | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x0477,
"Xerox", "DocuMate152",
- AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK,0},
+ AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x049D,
"Xerox", "DocuMate162",
- AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK,0},
+ AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x0448,
"Xerox", "DocuMate250",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x0490,
"Xerox", "DocuMate250-G",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x0449,
"Xerox", "DocuMate252",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x048C,
"Xerox", "DocuMate252-G",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x0476,
"Xerox", "DocuMate232",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x044c,
"Xerox", "DocuMate262",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x048D,
"Xerox", "DocuMate262-G",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x04a7,
"Xerox", "DocuMate262i",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="good" */
{ NULL, NULL,
0x04a7, 0x0475,
"Xerox", "DocuMate272",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x048E,
"Xerox", "DocuMate272-G",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x0446,
"Xerox", "DocuMate510",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x0495,
"Xerox", "DocuMate512",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x047c,
"Xerox", "DocuMate510-G",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x0447,
"Xerox", "DocuMate520",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x0492,
"Xerox", "DocuMate520-G",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
#ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
{ NULL, NULL,
0x04a7, 0x0498,
"Xerox", "DocuMate632",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
#endif
{ NULL, NULL,
0x04a7, 0x0478,
"Xerox", "DocuMate752",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
{ NULL, NULL,
0x04a7, 0x049A,
"Xerox", "DocuMate752",
- AV_INT_BUTTON,0},
+ AV_INT_BUTTON},
/* status="untested" */
#ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
{ NULL, NULL,
0x0638, 0x0a16,
"OKI", "S700 Scancopier",
- 0,0},
+ 0},
/* comment="1 pass, 600 dpi, A4" */
/* status="good" */
#endif
@@ -1154,14 +1158,14 @@ static Avision_HWEntry Avision_Device_List [] =
{ "B+H", "2000F",
0, 0,
"Bell+Howell", "2000F",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi, A4" */
/* status="basic" */
{ NULL, NULL,
0x0482, 0x0335,
"Kyocera", "FS-1016MFP",
- 0,0},
+ 0},
/* comment="1 pass, ??? dpi, A4" */
/* status="untested" */
@@ -1203,7 +1207,7 @@ Lexmark X4500 MFP
{ NULL, NULL,
0, 0,
NULL, NULL,
- 0,0}
+ 0}
};
#if 0
@@ -3208,7 +3212,7 @@ get_accessories_info (Avision_Scanner* s)
dev->inquiry_adf |= result [0];
- if (dev->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX)
+ if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX)
{
if (result[0] == 1)
{
@@ -3765,14 +3769,14 @@ attach (SANE_String_Const devname, Avision_ConnectionType con_type,
if (!found) {
DBG (0, "attach: \"%s\" - \"%s\" not yet in whitelist!\n", mfg, model);
DBG (0, "attach: You might want to report this output.\n");
- DBG (0, "attach: To: mike@piratehaven.org (the Avision backend maintainer)\n");
+ DBG (0, "attach: To: rene@exactcode.de (the Avision backend author)\n");
status = SANE_STATUS_INVAL;
goto close_scanner_and_return;
}
/* second: maybe ask for the firmware status and flash ram info */
- if (Avision_Device_List [model_num].feature_type2 & AV_FIRMWARE)
+ if (Avision_Device_List [model_num].feature_type & AV_FIRMWARE)
{
DBG (3, "attach: reading firmware status\n");
status = get_firmware_status (&av_con);
@@ -4211,7 +4215,7 @@ get_double ( &(result[48] ) ));
}
dev->inquiry_tune_scan_length = BIT(result[94],2);
- if (Avision_Device_List [model_num].feature_type2 & AV_NO_TUNE_SCAN_LENGTH)
+ if (Avision_Device_List [model_num].feature_type & AV_NO_TUNE_SCAN_LENGTH)
dev->inquiry_tune_scan_length = 0;
dev->inquiry_background_raster = BIT(result[95],2);
@@ -4278,7 +4282,9 @@ get_double ( &(result[48] ) ));
else
dev->scsi_buffer_size = sanei_scsi_max_request_size;
- if (dev->inquiry_asic_type >= AV_ASIC_C5)
+ if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980)
+ dev->read_stripe_size = 16;
+ else if (dev->inquiry_asic_type >= AV_ASIC_C5)
dev->read_stripe_size = 32;
else /* tested on AV3200 with it's max of 300dpi @color */
dev->read_stripe_size = 8; /* maybe made dynamic on scan res ... */
@@ -5142,7 +5148,7 @@ send_gamma (Avision_Scanner* s)
switch (dev->inquiry_asic_type)
{
case AV_ASIC_Cx:
- case AV_ASIC_C1: /* from avision code */
+ case AV_ASIC_C1:
gamma_table_raw_size = 4096;
gamma_table_size = 2048;
break;
@@ -5150,10 +5156,6 @@ send_gamma (Avision_Scanner* s)
gamma_table_raw_size = 256;
gamma_table_size = 256;
break;
- case AV_ASIC_C6: /* SPEC claims: 256 ... ? */
- case AV_ASIC_C7:
- gamma_table_raw_size = 512;
- gamma_table_size = 512;
break;
case AV_ASIC_OA980:
gamma_table_raw_size = 4096;
@@ -5164,7 +5166,8 @@ send_gamma (Avision_Scanner* s)
gamma_table_size = 256;
break;
default:
- gamma_table_raw_size = gamma_table_size = 4096;
+ gamma_table_raw_size = 512; /* SPEC claims: 256 ... ? */
+ gamma_table_size = 512;
}
gamma_values = gamma_table_size / 256;
@@ -5678,8 +5681,9 @@ set_window (Avision_Scanner* s)
}
}
- if (s->val[OPT_PAPERLEN].w)
+ if (s->val[OPT_PAPERLEN].w != SANE_FALSE) {
set_double (cmd.window.descriptor.paper_length, (int)((double)30.0*1200));
+ }
if ( !(dev->hw->feature_type & AV_FUJITSU) )
{
@@ -5780,7 +5784,7 @@ set_window (Avision_Scanner* s)
else {
if (dev->hw->feature_type & AV_FASTER_WITH_FILTER)
cmd.window.avision.bitset1 |= AVISION_FILTER_GREEN;
- else if (dev->hw->feature_type2 & AV_USE_GRAY_FILTER)
+ else if (dev->hw->feature_type & AV_USE_GRAY_FILTER)
cmd.window.avision.bitset1 |= AVISION_FILTER_GRAY;
else
cmd.window.avision.bitset1 |= AVISION_FILTER_NONE;
@@ -6182,7 +6186,7 @@ do_eof (Avision_Scanner *s)
/* we can now mark the rear data as valid */
if (s->avdimen.interlaced_duplex ||
- (s->hw->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX)) {
+ (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX)) {
DBG (3, "do_eof: toggling duplex rear data valid\n");
s->duplex_rear_valid = !s->duplex_rear_valid;
DBG (3, "do_eof: duplex rear data valid: %x\n",
@@ -6262,11 +6266,6 @@ init_options (Avision_Scanner* s)
/* Init the SANE option from the scanner inquiry data */
- dev->x_range.max = SANE_FIX ( (int)dev->inquiry_x_ranges[s->source_mode_dim]);
- dev->x_range.quant = 0;
- dev->y_range.max = SANE_FIX ( (int)dev->inquiry_y_ranges[s->source_mode_dim]);
- dev->y_range.quant = 0;
-
switch (dev->inquiry_asic_type) {
case AV_ASIC_C2:
dev->dpi_range.min = 100;
@@ -6331,6 +6330,11 @@ init_options (Avision_Scanner* s)
s->source_mode = match_source_mode (dev, s->val[OPT_SOURCE].s);
s->source_mode_dim = match_source_mode_dim (s->source_mode);
+ dev->x_range.max = SANE_FIX ( (int)dev->inquiry_x_ranges[s->source_mode_dim]);
+ dev->x_range.quant = 0;
+ dev->y_range.max = SANE_FIX ( (int)dev->inquiry_y_ranges[s->source_mode_dim]);
+ dev->y_range.quant = 0;
+
/* resolution */
s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
@@ -6667,7 +6671,7 @@ init_options (Avision_Scanner* s)
/* ADF page flipping */
s->opt[OPT_ADF_FLIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
- if (!(s->hw->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX))
+ if (!(s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX))
s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_ADF_FLIP].name = "flip-page";
s->opt[OPT_ADF_FLIP].title = "Flip document after duplex scanning";
@@ -6782,7 +6786,7 @@ reader_process (void *data)
return SANE_STATUS_NO_MEM;
/* start scan ? */
- if ((deinterlace == NONE && !((dev->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->duplex_rear_valid)) ||
+ if ((deinterlace == NONE && !((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->duplex_rear_valid)) ||
(deinterlace != NONE && !s->duplex_rear_valid))
{
/* reserve unit - in the past we did this in open - but the
@@ -6820,7 +6824,7 @@ reader_process (void *data)
/* setup file i/o for deinterlacing scans or if we are the back page with a flipping duplexer */
if (deinterlace != NONE ||
- (dev->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2)))
+ (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2)))
{
if (!s->duplex_rear_valid) { /* create new file for writing */
DBG (3, "reader_process: opening duplex rear file for writing.\n");
@@ -6954,11 +6958,15 @@ reader_process (void *data)
/* only EOF on the second stripe, as otherwise the rear page
is shorter */
if (status == SANE_STATUS_EOF && deinterlace == STRIPE) {
- static int already_eof = 0;
- if (!already_eof) {
- DBG (5, "reader_process: first EOF on stripe interlace: hiding.\n");
- status = SANE_STATUS_GOOD;
- already_eof = 1;
+ if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980) {
+ this_read = 0;
+ } else {
+ static int already_eof = 0;
+ if (!already_eof) {
+ DBG (5, "reader_process: first EOF on stripe interlace: hiding.\n");
+ status = SANE_STATUS_GOOD;
+ already_eof = 1;
+ }
}
}
@@ -7047,7 +7055,7 @@ reader_process (void *data)
DBG (9, "reader_process: after deinterlacing: useful_bytes: %d, stripe_fill: %d\n",
useful_bytes, stripe_fill);
}
- if (dev->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && !s->duplex_rear_valid) {
+ if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && !s->duplex_rear_valid) {
/* Here we flip the image by writing the lines from the end of the file to the beginning. */
unsigned int absline = (processed_bytes - stripe_fill) / s->avdimen.hw_bytes_per_line;
unsigned int abslines = absline + useful_bytes / s->avdimen.hw_bytes_per_line;
@@ -7454,7 +7462,7 @@ reader_process (void *data)
/* Eject film holder and/or release_unit - but only for
non-duplex-rear / non-virtual scans. */
if ((deinterlace != NONE && s->duplex_rear_valid) ||
- ((dev->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && s->duplex_rear_valid))
+ ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && s->duplex_rear_valid))
{
DBG (1, "reader_process: virtual duplex scan - no device cleanup!\n");
}
@@ -7477,7 +7485,7 @@ reader_process (void *data)
}
}
- if ((dev->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->page % 2) {
+ if ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->page % 2) {
/* front page of flipping duplex */
if (exit_status == SANE_STATUS_EOF) {
if (s->val[OPT_ADF_FLIP].w) {
@@ -7891,7 +7899,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle *handle)
init_options (s);
if (dev->inquiry_duplex_interlaced || dev->scanner_type == AV_FILM ||
- dev->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX) {
+ dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) {
/* Might need at least *DOS (Windows flavour and OS/2) portability fix
However, I was told Cygwin (et al.) takes care of it. */
strncpy(s->duplex_rear_fname, "/tmp/avision-rear-XXXXXX", PATH_MAX);
@@ -8188,7 +8196,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
dev->y_range.max =
SANE_FIX ( dev->inquiry_y_ranges[s->source_mode_dim]);
- if (s->hw->hw->feature_type2 & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX) {
+ if (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX) {
s->opt[OPT_ADF_FLIP].cap &= ~SANE_CAP_INACTIVE;
} else {
s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
@@ -8284,16 +8292,9 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters* params)
}
if (params) {
+ *params = s->params;
/* add background raster lines */
- s->params.lines += s->val[OPT_BACKGROUND].w;
-
- /* copy structure members */
- params->format = s->params.format;
- params->last_frame = s->params.last_frame;
- params->bytes_per_line = s->params.bytes_per_line;
- params->pixels_per_line = s->params.pixels_per_line;
- params->lines = s->params.lines;
- params->depth = s->params.depth;
+ params->lines += s->val[OPT_BACKGROUND].w;
}
return SANE_STATUS_GOOD;
diff --git a/backend/avision.h b/backend/avision.h
index 14134e1..2122e09 100644
--- a/backend/avision.h
+++ b/backend/avision.h
@@ -93,123 +93,119 @@ typedef struct Avision_HWEntry {
/* feature overwrites - as embedded CPUs have 16bit enums - this
would need a change ... */
- enum {
/* force no calibration */
- AV_NO_CALIB = (1<<0),
+ #define AV_NO_CALIB ((uint64_t)1<<0)
/* force all in one command calibration */
- AV_ONE_CALIB_CMD = (1<<1),
+ #define AV_ONE_CALIB_CMD ((uint64_t)1<<1)
/* no gamma table */
- AV_NO_GAMMA = (1<<2),
+ #define AV_NO_GAMMA ((uint64_t)1<<2)
/* light check is bogus */
- AV_LIGHT_CHECK_BOGUS = (1<<3),
+ #define AV_LIGHT_CHECK_BOGUS ((uint64_t)1<<3)
/* no button though the device advertise it */
- AV_NO_BUTTON = (1<<4),
+ #define AV_NO_BUTTON ((uint64_t)1<<4)
/* if the scan area needs to be forced to A3 */
- AV_FORCE_A3 = (1<<5),
+ #define AV_FORCE_A3 ((uint64_t)1<<5)
/* if the scan area and resolution needs to be forced for films */
- AV_FORCE_FILM = (1<<6),
+ #define AV_FORCE_FILM ((uint64_t)1<<6)
/* does not suport, or very broken background (added for AV610C2) */
- AV_NO_BACKGROUND = (1<<7),
+ #define AV_NO_BACKGROUND ((uint64_t)1<<7)
/* is film scanner - no detection yet */
- AV_FILMSCANNER = (1<<8),
+ #define AV_FILMSCANNER ((uint64_t)1<<8)
/* fujitsu adaption */
- AV_FUJITSU = (1<<9),
+ #define AV_FUJITSU ((uint64_t)1<<9)
/* gray calibration data has to be uploaded on the blue channel ... ? */
- AV_GRAY_CALIB_BLUE = (1<<10),
+ #define AV_GRAY_CALIB_BLUE ((uint64_t)1<<10)
/* Interrupt endpoint button readout (so far AV220) */
- AV_INT_BUTTON = (1<<11),
+ #define AV_INT_BUTTON ((uint64_t)1<<11)
/* send acceleration table ... */
- AV_ACCEL_TABLE = (1<<12),
+ #define AV_ACCEL_TABLE ((uint64_t)1<<12)
/* non-interlaced scanns up to 300 dpi (AV32xx / AV83xx) */
- AV_NON_INTERLACED_DUPLEX_300 = (1<<13),
+ #define AV_NON_INTERLACED_DUPLEX_300 ((uint64_t)1<<13)
/* do not read multiples of 64 bytes - stalls the USB chip */
- AV_NO_64BYTE_ALIGN = (1<<14),
+ #define AV_NO_64BYTE_ALIGN ((uint64_t)1<<14)
/* force channel-by-channel calibration */
- AV_MULTI_CALIB_CMD = (1<<15),
+ #define AV_MULTI_CALIB_CMD ((uint64_t)1<<15)
/* non color scans are faster with a filter applied (AV32xx) */
- AV_FASTER_WITH_FILTER = (1<<16),
+ #define AV_FASTER_WITH_FILTER ((uint64_t)1<<16)
/* interlaced data with 1 line distance */
- AV_2ND_LINE_INTERLACED = (1<<17),
+ #define AV_2ND_LINE_INTERLACED ((uint64_t)1<<17)
/* does not keep the window though it advertices so */
- AV_DOES_NOT_KEEP_WINDOW = (1<<18),
+ #define AV_DOES_NOT_KEEP_WINDOW ((uint64_t)1<<18)
/* does not keep the gamma though it advertices so */
- AV_DOES_NOT_KEEP_GAMMA = (1<<19),
+ #define AV_DOES_NOT_KEEP_GAMMA ((uint64_t)1<<19)
/* advertises ADF is BGR order, but isn't (or vice versa) */
- AV_ADF_BGR_ORDER_INVERT = (1<<20),
+ #define AV_ADF_BGR_ORDER_INVERT ((uint64_t)1<<20)
/* allows 12bit mode, though not flagged */
- AV_12_BIT_MODE = (1<<21),
+ #define AV_12_BIT_MODE ((uint64_t)1<<21)
/* very broken background raster */
- AV_BACKGROUND_QUIRK = (1<<22),
+ #define AV_BACKGROUND_QUIRK ((uint64_t)1<<22)
/* though marked as GRAY only the scanner can do GRAY modes */
- AV_GRAY_MODES = (1<<23),
+ #define AV_GRAY_MODES ((uint64_t)1<<23)
/* no seperate, single REAR scan (AV122, DM152, ...) */
- AV_NO_REAR = (1<<24),
+ #define AV_NO_REAR ((uint64_t)1<<24)
/* only scan with some known good hardware resolutions, as the
scanner fails to properly interpoloate in between (e.g. AV121,
DM152 on duplex scans - but also the AV600), software scale and
interpolate to all the others */
- AV_SOFT_SCALE = (1<<25),
+ #define AV_SOFT_SCALE ((uint64_t)1<<25)
/* does keep window though it does not advertice it - the AV122/DM152
mess up image data if window is resend between ADF pages */
- AV_DOES_KEEP_WINDOW = (1<<26),
+ #define AV_DOES_KEEP_WINDOW ((uint64_t)1<<26)
/* does keep gamma though it does not advertice it */
- AV_DOES_KEEP_GAMMA = (1<<27),
+ #define AV_DOES_KEEP_GAMMA ((uint64_t)1<<27)
/* does the scanner contain a Cancel button? */
- AV_CANCEL_BUTTON = (1<<28),
+ #define AV_CANCEL_BUTTON ((uint64_t)1<<28)
/* is the rear image offset? */
- AV_REAR_OFFSET = (1<<29),
+ #define AV_REAR_OFFSET ((uint64_t)1<<29)
/* some devices do not need a START_SCAN, even hang with it */
- AV_NO_START_SCAN = (1<<30),
-
- AV_INT_STATUS = (1<<31)
+ #define AV_NO_START_SCAN ((uint64_t)1<<30)
- /* maybe more ...*/
- } feature_type;
-
- /*second enum cause 32 bit int above is full*/
- enum {
+ #define AV_INT_STATUS ((uint64_t)1<<31)
+
/* force no calibration */
- AV_NO_TUNE_SCAN_LENGTH = (1<<0),
+ #define AV_NO_TUNE_SCAN_LENGTH ((uint64_t)1<<32)
/* for gray scans, set grey filter */
- AV_USE_GRAY_FILTER = (1<<1),
+ #define AV_USE_GRAY_FILTER ((uint64_t)1<<33)
/* For (HP) scanners with flipping duplexers */
- AV_ADF_FLIPPING_DUPLEX = (1<<2),
+ #define AV_ADF_FLIPPING_DUPLEX ((uint64_t)1<<34)
/* For scanners which need to have their firmware read to properly function. */
- AV_FIRMWARE = (1<<3)
- } feature_type2;
+ #define AV_FIRMWARE ((uint64_t)1<<35)
+
+ /* maybe more ...*/
+ uint64_t feature_type;
} Avision_HWEntry;
diff --git a/backend/canon_dr.c b/backend/canon_dr.c
index 15dcc59..0b120fa 100644
--- a/backend/canon_dr.c
+++ b/backend/canon_dr.c
@@ -309,6 +309,8 @@
- set another unknown byte in buffermode for ssm2
- add another gettimeofday call at end of do_usb_cmd
- don't print 0 length line in hexdump
+ v49 2015-03-18, MAN
+ - initial support for DR-C125
SANE FLOW DIAGRAM
@@ -358,7 +360,7 @@
#include "canon_dr.h"
#define DEBUG 1
-#define BUILD 48
+#define BUILD 49
/* values for SANE_DEBUG_CANON_DR env var:
- errors 5
@@ -1542,6 +1544,38 @@ init_model (struct scanner *s)
s->can_monochrome=0;
}
+ else if (strstr (s->model_name,"DR-C125")
+ || strstr (s->model_name,"DR-C225")
+ ){
+
+ /*confirmed settings*/
+ s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_2510;
+ s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_2510;
+ s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_2510;
+ s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_2510;
+ s->duplex_interlace = DUPLEX_INTERLACE_2510;
+ s->unknown_byte2 = 0x88;
+ s->need_ccal = 1;
+ s->ccal_version = 3;
+ s->need_fcal = 1;
+ s->invert_tly = 1;
+ s->can_color = 1;
+ s->rgb_format = 1;
+ /*s->duplex_offset = 400; now set in config file*/
+
+ /*only in Y direction, so we trash them in X*/
+ s->std_res_x[DPI_100]=0;
+ s->std_res_x[DPI_150]=0;
+ s->std_res_x[DPI_200]=0;
+ s->std_res_x[DPI_240]=0;
+ s->std_res_x[DPI_400]=0;
+
+ /*suspected settings*/
+ s->always_op = 0;
+ s->fixed_width = 1;
+ s->valid_x = 8.5 * 1200;
+ }
+
DBG (10, "init_model: finish\n");
return SANE_STATUS_GOOD;
diff --git a/backend/canon_dr.conf.in b/backend/canon_dr.conf.in
index e946d9b..453065b 100644
--- a/backend/canon_dr.conf.in
+++ b/backend/canon_dr.conf.in
@@ -150,6 +150,7 @@ option duplex-offset 400
usb 0x1083 0x163f
# DR-C125
+option duplex-offset 400
usb 0x1083 0x1640
# DR-P215
diff --git a/backend/dll.conf.in b/backend/dll.conf.in
index a7e4b3e..ee6f2f1 100644
--- a/backend/dll.conf.in
+++ b/backend/dll.conf.in
@@ -24,6 +24,7 @@ dmc
epjitsu
#epson
epson2
+epsonds
fujitsu
#gphoto2
genesys
diff --git a/backend/epjitsu.c b/backend/epjitsu.c
index 08e78b2..7d987dc 100644
--- a/backend/epjitsu.c
+++ b/backend/epjitsu.c
@@ -146,6 +146,11 @@
- fix 150 dpi settings for fi-60F and fi-65F
- make adf_height_padding variable
- make white_factor variable
+ v27 2015-01-24, MAN
+ - don't override br_x and br_y
+ - call change_params after changing page_width
+ v28 2015-03-23, MAN
+ - call get_hardware_status before starting scan
SANE FLOW DIAGRAM
@@ -194,7 +199,7 @@
#include "epjitsu-cmd.h"
#define DEBUG 1
-#define BUILD 26
+#define BUILD 28
#ifndef MAX3
#define MAX3(a,b,c) ((a) > (b) ? ((a) > (c) ? a : c) : ((b) > (c) ? b : c))
@@ -1712,8 +1717,8 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
return SANE_STATUS_GOOD;
s->page_width = FIXED_MM_TO_SCANNER_UNIT(val_c);
- *info |= SANE_INFO_RELOAD_OPTIONS;
- return SANE_STATUS_GOOD;
+ *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
+ return change_params(s);
case OPT_PAGE_HEIGHT:
if (s->page_height == FIXED_MM_TO_SCANNER_UNIT(val_c))
@@ -1970,11 +1975,6 @@ change_params(struct scanner *s)
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 );
- /* wrong place for this?*/
- s->page_width = s->max_x;
- s->br_x = s->max_x;
- s->br_y = s->max_y;
-
/*current dpi*/
s->setWindowCoarseCal = settings[i].sw_coarsecal;
s->setWindowCoarseCalLen = SET_WINDOW_LEN;
@@ -2018,13 +2018,14 @@ change_params(struct scanner *s)
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 ;
+ s->tl_y = s->max_y - s->adf_height_padding - s->page_height;
+ if (s->tl_y < 0)
+ s->tl_y = 0;
if (s->page_height > 0) {
s->br_y = s->tl_y + s->page_height;
}
- else
- {
+ else {
s->br_y = s->max_y;
}
@@ -2370,6 +2371,9 @@ sane_start (SANE_Handle handle)
s->side = !s->side;
}
+ /* recent scanners need ghs called before scanning */
+ ret = get_hardware_status(s);
+
/* ingest paper with adf */
if( s->source == SOURCE_ADF_BACK || s->source == SOURCE_ADF_FRONT
|| (s->source == SOURCE_ADF_DUPLEX && s->side == SIDE_FRONT) ){
diff --git a/backend/epson2-commands.c b/backend/epson2-commands.c
index 0c28eab..eccd4ba 100644
--- a/backend/epson2-commands.c
+++ b/backend/epson2-commands.c
@@ -680,8 +680,10 @@ esci_set_scanning_parameter(SANE_Handle handle, unsigned char *buf)
return status;
status = e2_cmd_simple(s, buf, 64);
- if (status != SANE_STATUS_GOOD)
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: invalid scanning parameters\n", __func__);
return status;
+ }
return SANE_STATUS_GOOD;
}
diff --git a/backend/epson2-io.c b/backend/epson2-io.c
index 13adef4..4477963 100644
--- a/backend/epson2-io.c
+++ b/backend/epson2-io.c
@@ -110,8 +110,8 @@ e2_send(Epson_Scanner * s, void *buf, size_t buf_size, size_t reply_len,
}
ssize_t
-e2_recv(Epson_Scanner * s, void *buf, ssize_t buf_size,
- SANE_Status * status)
+e2_recv(Epson_Scanner *s, void *buf, ssize_t buf_size,
+ SANE_Status *status)
{
ssize_t n = 0;
@@ -142,8 +142,9 @@ e2_recv(Epson_Scanner * s, void *buf, ssize_t buf_size,
}
if (n < buf_size) {
- DBG(1, "%s: expected = %lu, got = %ld\n", __func__,
- (u_long) buf_size, (long) n);
+ DBG(1, "%s: expected = %lu, got = %ld, canceling: %d\n", __func__,
+ (u_long) buf_size, (long) n, s->canceling);
+
*status = SANE_STATUS_IO_ERROR;
}
diff --git a/backend/epson2-ops.c b/backend/epson2-ops.c
index d81deaf..5d8c84d 100644
--- a/backend/epson2-ops.c
+++ b/backend/epson2-ops.c
@@ -472,8 +472,10 @@ e2_set_tpu2_area(struct Epson_Scanner *s, int x, int y, int unit)
}
void
-e2_add_depth(Epson_Device * dev, SANE_Word depth)
+e2_add_depth(Epson_Device *dev, SANE_Int depth)
{
+ DBG(10, "%s: add (bpp): %d\n", __func__, depth);
+
if (depth > dev->maxDepth)
dev->maxDepth = depth;
@@ -765,7 +767,7 @@ e2_discover_capabilities(Epson_Scanner *s)
* Check for the max. supported color depth and assign
* the values to the bitDepthList.
*/
- dev->depth_list = malloc(sizeof(SANE_Word) * 4);
+ dev->depth_list = malloc(sizeof(SANE_Int) * (4 + 1));
if (dev->depth_list == NULL) {
DBG(1, "out of memory (line %d)\n", __LINE__);
return SANE_STATUS_NO_MEM;
@@ -776,9 +778,12 @@ e2_discover_capabilities(Epson_Scanner *s)
/* maximum depth discovery */
DBG(3, "discovering max depth, NAKs are expected\n");
- if (dev->maxDepth >= 16 || dev->maxDepth == 0) {
- if (esci_set_data_format(s, 16) == SANE_STATUS_GOOD)
- e2_add_depth(dev, 16);
+ /* add default depth */
+ e2_add_depth(dev, 8);
+
+ if (dev->maxDepth >= 12 || dev->maxDepth == 0) {
+ if (esci_set_data_format(s, 12) == SANE_STATUS_GOOD)
+ e2_add_depth(dev, 12);
}
if (dev->maxDepth >= 14 || dev->maxDepth == 0) {
@@ -786,14 +791,11 @@ e2_discover_capabilities(Epson_Scanner *s)
e2_add_depth(dev, 14);
}
- if (dev->maxDepth >= 12 || dev->maxDepth == 0) {
- if (esci_set_data_format(s, 12) == SANE_STATUS_GOOD)
- e2_add_depth(dev, 12);
+ if (dev->maxDepth >= 16 || dev->maxDepth == 0) {
+ if (esci_set_data_format(s, 16) == SANE_STATUS_GOOD)
+ e2_add_depth(dev, 16);
}
- /* add default depth */
- e2_add_depth(dev, 8);
-
DBG(1, "maximum supported color depth: %d\n", dev->maxDepth);
/*
@@ -1742,6 +1744,8 @@ e2_ext_read(struct Epson_Scanner *s)
SANE_Status status = SANE_STATUS_GOOD;
ssize_t buf_len = 0, read;
+ DBG(18, "%s: begin\n", __func__);
+
/* did we passed everything we read to sane? */
if (s->ptr == s->end) {
@@ -1765,10 +1769,12 @@ e2_ext_read(struct Epson_Scanner *s)
/* receive image data + error code */
read = e2_recv(s, s->buf, buf_len + 1, &status);
- DBG(18, "%s: read %lu bytes\n", __func__, (unsigned long) read);
+ DBG(18, "%s: read %lu bytes, status: %d\n", __func__, (unsigned long) read, status);
- if (read != buf_len + 1)
- return SANE_STATUS_IO_ERROR;
+ if (status != SANE_STATUS_GOOD) {
+ e2_cancel(s);
+ return status;
+ }
if (e2_dev_model(dev, "GT-8200") || e2_dev_model(dev, "Perfection1650")) {
/* See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=597922#127 */
diff --git a/backend/epson2.c b/backend/epson2.c
index e023010..b1eda33 100644
--- a/backend/epson2.c
+++ b/backend/epson2.c
@@ -977,7 +977,7 @@ init_options(Epson_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 */
+ s->val[OPT_MODE].w = 0; /* Lineart */
/* disable infrared on unsupported scanners */
if (!e2_model(s, "GT-X800") && !e2_model(s, "GT-X700") && !e2_model(s, "GT-X900"))
@@ -988,14 +988,13 @@ init_options(Epson_Scanner *s)
s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
- s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE;
+ s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT;
s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->depth_list;
- s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
- s->val[OPT_BIT_DEPTH].w = s->hw->depth_list[1]; /* the first "real" element is the default */
+ s->val[OPT_BIT_DEPTH].w = 8; /* default to 8 bit */
- if (s->hw->depth_list[0] == 1) /* only one element in the list -> hide the option */
- s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
+ /* default is Lineart, disable depth selection */
+ s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
/* halftone */
s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE;
@@ -1535,6 +1534,8 @@ sane_close(SANE_Handle handle)
int i;
Epson_Scanner *s;
+ DBG(1, "* %s\n", __func__);
+
/*
* XXX Test if there is still data pending from
* the scanner. If so, then do a cancel
@@ -1909,6 +1910,8 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
sval->w = optindex;
+ DBG(17, "%s: setting mode to %d\n", __func__, optindex);
+
/* halftoning available only on bw scans */
if (s->hw->cmd->set_halftoning != 0)
setOptionState(s, mode_params[optindex].depth == 1,
@@ -1923,16 +1926,18 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
/* if binary, then disable the bit depth selection */
if (optindex == 0) {
+ DBG(17, "%s: disabling bit depth selection\n", __func__);
s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
} else {
- if (s->hw->depth_list[0] == 1)
- 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->depth_list[0] == 1) {
+ DBG(17, "%s: only one depth is available\n", __func__);
+ s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
+ } else {
+
+ DBG(17, "%s: enabling bit depth selection\n", __func__);
+
+ s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE;
+ s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth;
}
}
@@ -2077,7 +2082,10 @@ sane_start(SANE_Handle handle)
Epson_Device *dev = s->hw;
SANE_Status status;
- DBG(5, "%s\n", __func__);
+ DBG(5, "* %s\n", __func__);
+
+ s->eof = SANE_FALSE;
+ s->canceling = SANE_FALSE;
/* check if we just have finished working with the ADF */
status = e2_check_adf(s);
@@ -2202,9 +2210,7 @@ sane_start(SANE_Handle handle)
if (s->buf == NULL)
return SANE_STATUS_NO_MEM;
- s->eof = SANE_FALSE;
s->ptr = s->end = s->buf;
- s->canceling = SANE_FALSE;
/* feed the first sheet in the ADF */
if (dev->ADF && dev->use_extension && dev->cmd->feed) {
@@ -2275,8 +2281,14 @@ sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
SANE_Status status;
Epson_Scanner *s = (Epson_Scanner *) handle;
- if (s->buf == NULL || s->canceling)
- return SANE_STATUS_CANCELLED;
+ DBG(18, "* %s: eof: %d, canceling: %d\n",
+ __func__, s->eof, s->canceling);
+
+ /* sane_read called before sane_start? */
+ if (s->buf == NULL) {
+ DBG(1, "%s: buffer is NULL", __func__);
+ return SANE_STATUS_INVAL;
+ }
*length = 0;
@@ -2285,9 +2297,12 @@ sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
else
status = e2_block_read(s);
- if (status == SANE_STATUS_CANCELLED) {
+ /* The scanning operation might be canceled by the scanner itself
+ * or the fronted program
+ */
+ if (status == SANE_STATUS_CANCELLED || s->canceling) {
e2_scan_finish(s);
- return status;
+ return SANE_STATUS_CANCELLED;
}
/* XXX if FS G and STATUS_IOERR, use e2_check_extended_status */
@@ -2298,9 +2313,9 @@ sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
e2_copy_image_data(s, data, max_length, length);
- DBG(18, "%d lines read, eof: %d, status: %d\n",
+ DBG(18, "%d lines read, eof: %d, canceling: %d, status: %d\n",
*length / s->params.bytes_per_line,
- s->eof, status);
+ s->canceling, s->eof, status);
/* continue reading if appropriate */
if (status == SANE_STATUS_GOOD)
@@ -2323,6 +2338,8 @@ sane_cancel(SANE_Handle handle)
{
Epson_Scanner *s = (Epson_Scanner *) handle;
+ DBG(1, "* %s\n", __func__);
+
s->canceling = SANE_TRUE;
}
diff --git a/backend/epson2.h b/backend/epson2.h
index bb6c9e0..8650f01 100644
--- a/backend/epson2.h
+++ b/backend/epson2.h
@@ -346,7 +346,7 @@ struct Epson_Device
SANE_Bool color_shuffle; /* does this scanner need color shuffling */
SANE_Int maxDepth; /* max. color depth */
- SANE_Word *depth_list;
+ SANE_Int *depth_list;
SANE_Int optical_res; /* optical resolution */
SANE_Int max_line_distance;
diff --git a/backend/epsonds-cmd.c b/backend/epsonds-cmd.c
new file mode 100644
index 0000000..5fb1f9d
--- /dev/null
+++ b/backend/epsonds-cmd.c
@@ -0,0 +1,899 @@
+/*
+ * epsonds-cmd.c - Epson ESC/I-2 routines.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#define DEBUG_DECLARE_ONLY
+
+#include "sane/config.h"
+#include <ctype.h>
+#include <unistd.h> /* sleep */
+
+#include "epsonds.h"
+#include "epsonds-io.h"
+#include "epsonds-cmd.h"
+#include "epsonds-ops.h"
+
+static SANE_Status
+esci2_parse_block(char *buf, int len, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len))
+{
+ SANE_Status status = SANE_STATUS_GOOD;
+ SANE_Status delayed_status = SANE_STATUS_GOOD;
+
+
+ char *start = buf;
+ char *end = (buf + len) - 1;
+
+ /* 0 : #
+ * 1-3: param
+ * 4- : data
+ */
+
+ while (1) {
+
+ char param[4];
+
+ while (*start != '#' && start < end)
+ start++;
+
+ if (*start != '#')
+ break;
+
+ param[0] = *++start;
+ param[1] = *++start;
+ param[2] = *++start;
+ param[3] = '\0';
+
+ if (strncmp("---", param, 3) == 0)
+ break;
+
+ /* ugly hack to skip over GMT in RESA */
+ if (strncmp("GMT", param, 3) == 0 && *(start + 5) == 'h') {
+ start = start + 4 + 0x100;
+ continue;
+ }
+
+ /* find the end of the token */
+ {
+ int tlen;
+ char *next = start;
+
+ while (*next != '#' && *next != 0x00 && next < end)
+ next++;
+
+ tlen = next - start - 1;
+
+ if (cb) {
+ status = cb(userdata, start - 2, tlen);
+ if (status != SANE_STATUS_GOOD) {
+ delayed_status = status;
+ }
+ }
+
+ start = next;
+ }
+ }
+
+ if (delayed_status != SANE_STATUS_GOOD)
+ return delayed_status;
+
+ return status;
+}
+
+static SANE_Bool
+esci2_check_header(const char *cmd, const char *buf, unsigned int *more)
+{
+ int err;
+
+ *more = 0;
+
+ if (strncmp(cmd, buf, 4) != 0) {
+
+ if (strncmp("UNKN", buf, 4) == 0) {
+ DBG(1, "UNKN reply code received\n");
+ } else if (strncmp("INVD", buf, 4) == 0) {
+ DBG(1, "INVD reply code received\n");
+ } else {
+ DBG(1, "%c%c%c%c, unexpected reply code\n", buf[0], buf[1], buf[2], buf[3]);
+ }
+
+ return 0;
+ }
+
+ /* INFOx0000100#.... */
+
+ /* read the answer len */
+ if (buf[4] != 'x') {
+ DBG(1, "unknown type in header: %c\n", buf[4]);
+ return 0;
+ }
+
+ err = sscanf(&buf[5], "%x#", more);
+ if (err != 1) {
+ DBG(1, "cannot decode length from header\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static SANE_Status esci2_cmd(epsonds_scanner* s,
+ char *cmd, size_t len,
+ char *payload, size_t plen,
+ void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len))
+{
+ SANE_Status status;
+ unsigned int more;
+ char rbuf[64];
+
+ DBG(8, "%s: %4s len %lu, payload len: %lu\n", __func__, cmd, len, plen);
+
+ if (len < 12) {
+ DBG(1, "%s: command is too short (%lu)\n", __func__, len);
+ return SANE_STATUS_INVAL;
+ }
+
+ /* merge the payload size and send the RequestBlock */
+ if (payload && plen) {
+
+ sprintf(rbuf, "%4.4sx%07x", cmd, (unsigned int)plen);
+
+ DBG(8, " %s (%d)\n", rbuf, plen);
+
+ eds_send(s, rbuf, 12, &status);
+
+ } else {
+ eds_send(s, cmd, len, &status);
+ }
+
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ /* send ParameterBlock */
+ if (payload && plen) {
+
+ eds_send(s, payload, plen, &status);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+ }
+
+ /* receive DataHeaderBlock */
+ memset(rbuf, 0x00, sizeof(rbuf));
+
+ eds_recv(s, rbuf, 64, &status);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ /* rxbuf holds the DataHeaderBlock, which should be
+ * parsed to know if we need to read more data
+ */
+ if (!esci2_check_header(cmd, rbuf, &more)) {
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ /* parse the received header block */
+ if (cb) {
+ status = esci2_parse_block(rbuf + 12, 64 - 12, userdata, cb);
+ if (status != SANE_STATUS_GOOD && status != SANE_STATUS_DEVICE_BUSY) {
+ DBG(1, "%s: %4s error while parsing received header\n", __func__, cmd);
+ }
+ }
+
+ /* header valid, get the data block if present */
+ if (more) {
+
+ char *pbuf = malloc(more);
+ if (pbuf) {
+
+ ssize_t read = eds_recv(s, pbuf, more, &status);
+ if (read != more) {
+ }
+
+ /* parse the received data block */
+ if (cb) {
+ status = esci2_parse_block(pbuf, more, userdata, cb);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: %4s error while parsing received data block\n", __func__, cmd);
+ }
+ }
+
+ free(pbuf);
+
+ } else {
+ return SANE_STATUS_NO_MEM;
+ }
+ }
+
+ return status;
+}
+
+static SANE_Status esci2_cmd_simple(epsonds_scanner* s, char *cmd, SANE_Status (*cb)(void *userdata, char *token, int len))
+{
+ return esci2_cmd(s, cmd, 12, NULL, 0, s, cb);
+}
+
+SANE_Status esci2_fin(epsonds_scanner *s)
+{
+ DBG(5, "%s\n", __func__);
+
+ SANE_Status status = esci2_cmd_simple(s, "FIN x0000000", NULL);
+ s->locked = 0;
+ return status;
+}
+
+SANE_Status esci2_can(epsonds_scanner *s)
+{
+ return esci2_cmd_simple(s, "CAN x0000000", NULL);
+}
+
+static int decode_value(char *buf, int len)
+{
+ char tmp[10];
+
+ memcpy(tmp, buf, len);
+ tmp[len] = '\0';
+
+ if (buf[0] == 'd' && len == 4) {
+ return strtol(buf + 1, NULL, 10);
+ } else if (buf[0] == 'i' && len == 8) {
+ return strtol(buf + 1, NULL, 10);
+ } else if (buf[0] == 'x' && len == 8) {
+ return strtol(buf + 1, NULL, 16);
+ } else if (buf[0] == 'h' && len == 4) {
+ return strtol(buf + 1, NULL, 16);
+ }
+
+ return -1;
+}
+
+/* h000 */
+static char *decode_binary(char *buf)
+{
+ char tmp[6];
+
+ memcpy(tmp, buf, 4);
+ tmp[4] = '\0';
+
+ if (buf[0] != 'h')
+ return NULL;
+
+ int hl = strtol(tmp + 1, NULL, 16);
+ if (hl) {
+
+ char *v = malloc(hl + 1);
+ memcpy(v, buf + 4, hl);
+ v[hl] = '\0';
+
+ return v;
+ }
+
+ return NULL;
+}
+
+static char *decode_string(char *buf)
+{
+ char *s = decode_binary(buf);
+ if (s == NULL)
+ return NULL;
+
+ /* trim white space at the end */
+ char *p = s + strlen(s);
+ while (*--p == ' ')
+ *p = '\0';
+
+ return s;
+}
+
+static void debug_token(int level, const char *func, char *token, int len)
+{
+ char *tdata = malloc(len + 1);
+ memcpy(tdata, token + 3, len);
+ tdata[len] = '\0';
+
+ DBG(level, "%s: %3.3s / %s / %d\n", func, token, tdata, len);
+
+ free(tdata);
+}
+
+static SANE_Status info_cb(void *userdata, char *token, int len)
+{
+ epsonds_scanner *s = (epsonds_scanner *)userdata;
+
+ if (DBG_LEVEL >= 11) {
+ debug_token(DBG_LEVEL, __func__, token, len);
+ }
+
+ /* pointer to the token's value */
+ char *value = token + 3;
+
+ /* nrd / nrdBUSY */
+
+ if (strncmp("nrd", token, 3) == 0) {
+ if (strncmp("BUSY", value, 4) == 0) {
+ return SANE_STATUS_DEVICE_BUSY;
+ }
+ }
+
+ if (strncmp("PRD", token, 3) == 0) {
+ free(s->hw->model);
+ s->hw->model = decode_string(value);
+ s->hw->sane.model = s->hw->model;
+ DBG(1, " product: %s\n", s->hw->model);
+ /* we will free the string later */
+ }
+
+ if (strncmp("VER", token, 3) == 0) {
+ char *v = decode_string(value);
+ DBG(1, " version: %s\n", v);
+ free(v);
+ }
+
+ if (strncmp("S/N", token, 3) == 0) {
+ char *v = decode_string(value);
+ DBG(1, " serial: %s\n", v);
+ free(v);
+ }
+
+ if (strncmp("ADF", token, 3) == 0) {
+
+ s->hw->has_adf = 1;
+
+ if (len == 8) {
+
+ if (strncmp("TYPEPAGE", value, len) == 0) {
+ DBG(1, " ADF: page type\n");
+ }
+
+ if (strncmp("TYPEFEED", value, len) == 0) {
+ DBG(1, " ADF: sheet feed type\n");
+ }
+
+ if (strncmp("DPLX1SCN", value, len) == 0) {
+ DBG(1, " ADF: duplex single pass\n");
+ s->hw->adf_singlepass = 1;
+ }
+
+ if (strncmp("DPLX2SCN", value, len) == 0) {
+ DBG(1, " ADF: duplex double pass\n");
+ s->hw->adf_singlepass = 0;
+ }
+
+ if (strncmp("FORDPF1N", value, len) == 0) {
+ DBG(1, " ADF: order is 1 to N\n");
+ }
+
+ if (strncmp("FORDPFN1", value, len) == 0) {
+ DBG(1, " ADF: order is N to 1\n");
+ }
+
+ if (strncmp("ALGNLEFT", value, len) == 0) {
+ DBG(1, " ADF: left aligned\n");
+ s->hw->adf_alignment = 0;
+ }
+
+ if (strncmp("ALGNCNTR", value, len) == 0) {
+ DBG(1, " ADF: center aligned\n");
+ s->hw->adf_alignment = 1;
+ }
+
+ if (strncmp("ALGNRIGT", value, len) == 0) {
+ DBG(1, " ADF: right aligned (not supported!)\n");
+ s->hw->adf_alignment = 2;
+ }
+ }
+
+ if (len == 4) {
+
+ if (strncmp("PREF", value, len) == 0) {
+ DBG(1, " ADF: auto pre-feed\n");
+ }
+
+ if (strncmp("ASCN", value, len) == 0) {
+ DBG(1, " ADF: auto scan\n");
+ }
+
+ if (strncmp("RCVR", value, len) == 0) {
+ DBG(1, " ADF: auto recovery\n");
+ }
+ }
+
+ if (len == 20) {
+
+ /* ADFAREAi0000850i0001400 */
+
+ if (strncmp("AREA", value, 4) == 0) {
+
+ int min = decode_value(value + 4, 8);
+ int max = decode_value(value + 4 + 8, 8);
+
+ DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max);
+ }
+
+ if (strncmp("AMIN", value, 4) == 0) {
+
+ int min = decode_value(value + 4, 8);
+ int max = decode_value(value + 4 + 8, 8);
+
+ DBG(1, " ADF: min %dx%d @ 100dpi\n", min, max);
+ }
+
+ if (strncmp("AMAX", value, 4) == 0) {
+
+ int min = decode_value(value + 4, 8);
+ int max = decode_value(value + 4 + 8, 8);
+
+ DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max);
+
+ eds_set_adf_area(s->hw, min, max, 100);
+ }
+ }
+
+ if (len == 12) {
+
+ /* RESOi0000600 */
+
+ if (strncmp("RESO", value, 4) == 0) {
+
+ int res = decode_value(value + 4, 8);
+
+ DBG(1, " ADF: basic resolution is %d dpi\n", res);
+ }
+
+ /* OVSNd025d035 */
+
+ if (strncmp("OVSN", value, 4) == 0) {
+
+ int x = decode_value(value + 4, 4);
+ int y = decode_value(value + 4 + 4, 4);
+
+ DBG(1, " ADF: overscan %dx%d @ 100dpi\n", x, y);
+ }
+ }
+ }
+
+ if (strncmp("FB ", token, 3) == 0) {
+
+ s->hw->has_fb = 1;
+
+ if (len == 20) {
+
+ /* AREAi0000850i0001400 */
+ if (strncmp("AREA", value, 4) == 0) {
+
+ int min = decode_value(value + 4, 8);
+ int max = decode_value(value + 4 + 8, 8);
+
+ DBG(1, " FB: area %dx%d @ 100dpi\n", min, max);
+
+ eds_set_fbf_area(s->hw, min, max, 100);
+ }
+ }
+
+ if (len == 8) {
+
+ if (strncmp("ALGNLEFT", value, len) == 0) {
+ DBG(1, " FB: left aligned\n");
+ s->hw->fbf_alignment = 0;
+ }
+
+ if (strncmp("ALGNCNTR", value, len) == 0) {
+ DBG(1, " FB: center aligned\n");
+ s->hw->fbf_alignment = 1;
+ }
+
+ if (strncmp("ALGNRIGT", value, len) == 0) {
+ DBG(1, " FB: right aligned (not supported!)\n");
+ s->hw->fbf_alignment = 2;
+ }
+ }
+
+ if (len == 12) {
+
+ /* RESOi0000600 */
+
+ if (strncmp("RESO", value, 4) == 0) {
+
+ int res = decode_value(value + 4, 8);
+
+ DBG(1, " FB: basic resolution is %d dpi\n", res);
+ }
+
+ /* OVSNd025d035 */
+
+ if (strncmp("OVSN", value, 4) == 0) {
+
+ int x = decode_value(value + 4, 4);
+ int y = decode_value(value + 4 + 4, 4);
+
+ DBG(1, " FB: overscan %dx%d @ 100dpi\n", x, y);
+ }
+ }
+
+ if (len == 4) {
+
+ if (strncmp("DETX", value, len) == 0) {
+ DBG(1, " FB: paper width detection\n");
+ }
+
+ if (strncmp("DETY", value, len) == 0) {
+ DBG(1, " FB: paper height detection\n");
+ }
+ }
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status esci2_info(epsonds_scanner *s)
+{
+ DBG(1, "= gathering device information\n");
+
+ SANE_Status status;
+ int i = 4;
+
+ do {
+ status = esci2_cmd_simple(s, "INFOx0000000", &info_cb);
+ if (status == SANE_STATUS_DEVICE_BUSY) {
+ sleep(2);
+ }
+
+ i--;
+
+ } while (status == SANE_STATUS_DEVICE_BUSY && i);
+
+ return status;
+}
+
+/* CAPA */
+
+static SANE_Status capa_cb(void *userdata, char *token, int len)
+{
+ epsonds_scanner *s = (epsonds_scanner *)userdata;
+
+ char *value = token + 3;
+
+ if (DBG_LEVEL >= 11) {
+ debug_token(DBG_LEVEL, __func__, token, len);
+ }
+
+ if (len == 4) {
+
+ if (strncmp("ADFDPLX", token, 3 + 4) == 0) {
+ DBG(1, " ADF: duplex\n");
+ s->hw->adf_is_duplex = 1;
+ }
+
+ if (strncmp("ADFSKEW", token, 3 + 4) == 0) {
+ DBG(1, " ADF: skew correction\n");
+ s->hw->adf_has_skew = 1;
+ }
+
+ if (strncmp("ADFOVSN", token, 3 + 4) == 0) {
+ DBG(1, " ADF: overscan\n");
+ }
+
+ if (strncmp("ADFPEDT", token, 3 + 4) == 0) {
+ DBG(1, " ADF: paper end detection\n");
+ }
+
+ if (strncmp("ADFLOAD", token, 3 + 4) == 0) {
+ DBG(1, " ADF: paper load\n");
+ s->hw->adf_has_load = 1;
+ }
+
+ if (strncmp("ADFEJCT", token, 3 + 4) == 0) {
+ DBG(1, " ADF: paper eject\n");
+ s->hw->adf_has_eject = 1;
+ }
+
+ if (strncmp("ADFCRP ", token, 3 + 4) == 0) {
+ DBG(1, " ADF: image cropping\n");
+ }
+
+ if (strncmp("ADFFAST", token, 3 + 4) == 0) {
+ DBG(1, " ADF: fast mode available\n");
+ }
+
+ if (strncmp("ADFDFL1", token, 3 + 4) == 0) {
+ DBG(1, " ADF: double feed detection\n");
+ }
+ }
+
+ if (len == 8 && strncmp("ADFDFL1DFL2", token, 3 + 4) == 0) {
+ DBG(1, " ADF: double feed detection (high sensitivity)\n");
+ }
+
+ if (strncmp("FMT", token, 3) == 0) {
+
+ /* a bit ugly... */
+
+ if (len >= 8) {
+ if (strncmp("RAW ", value + 4, 4) == 0) {
+ s->hw->has_raw = 1;
+ }
+ }
+
+ if (len >= 12) {
+ if (strncmp("RAW ", value + 8, 4) == 0) {
+ s->hw->has_raw = 1;
+ }
+ }
+ }
+
+ /* RSMRANGi0000050i0000600 */
+
+ if (strncmp("RSMRANG", token, 3 + 4) == 0) {
+
+ char *p = token + 3 + 4;
+
+ if (p[0] == 'i') {
+
+ int min = decode_value(p, 8);
+ int max = decode_value(p + 8, 8);
+
+ eds_set_resolution_range(s->hw, min, max);
+
+ DBG(1, "resolution min/max %d/%d\n", min, max);
+ }
+ }
+
+ /* RSMLISTi0000300i0000600 */
+
+ if (strncmp("RSMLIST", token, 3 + 4) == 0) {
+
+ char *p = token + 3 + 4;
+
+ if (p[0] == 'i') {
+
+ int i;
+ int count = (len - 4) / 8;
+
+ for (i = 0; i < count; i++) {
+
+ eds_add_resolution(s->hw, decode_value(p, 8));
+ p += 8;
+ }
+ }
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status esci2_capa(epsonds_scanner *s)
+{
+ return esci2_cmd_simple(s, "CAPAx0000000", &capa_cb);
+}
+
+/* STAT */
+
+static SANE_Status stat_cb(void *userdata, char *token, int len)
+{
+/*
+ epsonds_scanner *s = (epsonds_scanner *)userdata;
+ char *value = token + 3;
+*/
+ userdata = userdata;
+
+ if (DBG_LEVEL >= 11) {
+ debug_token(DBG_LEVEL, __func__, token, len);
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status esci2_stat(epsonds_scanner *s)
+{
+ return esci2_cmd_simple(s, "STATx0000000", &stat_cb);
+}
+
+/* RESA */
+
+static SANE_Status resa_cb(void *userdata, char *token, int len)
+{
+ /* epsonds_scanner *s = (epsonds_scanner *)userdata; */
+
+ userdata = userdata;
+
+ if (DBG_LEVEL >= 11) {
+ debug_token(DBG_LEVEL, __func__, token, len);
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status esci2_resa(epsonds_scanner *s)
+{
+ return esci2_cmd_simple(s, "RESAx0000000", &resa_cb);
+}
+
+/* PARA */
+
+static SANE_Status para_cb(void *userdata, char *token, int len)
+{
+ if (DBG_LEVEL >= 11) {
+ debug_token(DBG_LEVEL, __func__, token, len);
+ }
+
+ userdata = userdata;
+
+ if (strncmp("par", token, 3) == 0) {
+ if (strncmp("FAIL", token + 3, 4) == 0) {
+ DBG(1, "%s: parameter setting failed\n", __func__);
+ return SANE_STATUS_INVAL;
+ }
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status esci2_para(epsonds_scanner *s, char *parameters)
+{
+ DBG(8, "%s: %s\n", __func__, parameters);
+ return esci2_cmd(s, "PARAx0000000", 12, parameters, strlen(parameters), NULL, &para_cb);
+}
+
+SANE_Status esci2_mech(epsonds_scanner *s, char *parameters)
+{
+ DBG(8, "%s: %s\n", __func__, parameters);
+ return esci2_cmd(s, "MECHx0000000", 12, parameters, strlen(parameters), NULL, &para_cb);
+}
+
+SANE_Status esci2_trdt(epsonds_scanner *s)
+{
+ return esci2_cmd_simple(s, "TRDTx0000000", NULL);
+}
+
+
+static SANE_Status img_cb(void *userdata, char *token, int len)
+{
+ struct epsonds_scanner *s = userdata;
+
+ if (DBG_LEVEL >= 11) {
+ debug_token(DBG_LEVEL, __func__, token, len);
+ }
+
+ /* psti0000256i0000000i0000945 / 24 */
+
+ /* integer comparison first so it's faster */
+ if (len == 24 && strncmp("pst", token, 3) == 0) {
+
+ s->dummy = decode_value(token + 3 + 8, 8);
+
+ DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
+ __func__,
+ decode_value(token + 3, 8),
+ decode_value(token + 3 + 8 + 8, 8),
+ s->dummy);
+
+ return SANE_STATUS_GOOD;
+ }
+
+ if (len == 16 && strncmp("pen", token, 3) == 0) {
+ DBG(10, "%s: page end\n", __func__);
+ s->eof = 1;
+ return SANE_STATUS_EOF;
+ }
+
+ /* typIMGA or typIMGB */
+ if (len == 4 && strncmp("typ", token, 3) == 0) {
+
+ if (token[6] == 'B')
+ s->backside = 1;
+ else
+ s->backside = 0;
+
+ return SANE_STATUS_GOOD;
+ }
+
+ if (strncmp("err", token, 3) == 0) {
+
+ s->scanning = 0;
+
+ char *option = token + 3; /* ADF, TPU, FB */
+ char *cause = token + 3 + 4; /* OPN, PJ, PE, ERR, LTF, LOCK, DFED, DTCL, AUT, PERM */
+
+ DBG(1, "%s: error on option %3.3s, cause %4.4s\n",
+ __func__, option, cause);
+
+ if (cause[0] == 'P' && cause[1] == 'J')
+ return SANE_STATUS_JAMMED;
+
+ if (cause[0] == 'P' && cause[1] == 'E')
+ return SANE_STATUS_NO_DOCS;
+
+ if (cause[0] == 'O' && cause[1] == 'P' && cause[2] == 'N')
+ return SANE_STATUS_COVER_OPEN;
+
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ if (len == 4 && strncmp("atnCAN ", token, 3 + 4) == 0) {
+ DBG(1, "%s: cancel request\n", __func__);
+ s->canceling = 1;
+ s->scanning = 0;
+ return SANE_STATUS_CANCELLED;
+ }
+
+ if (len == 4 && strncmp("lftd000", token, 3 + 4) == 0) {
+ s->scanning = 0;
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+
+SANE_Status
+esci2_img(struct epsonds_scanner *s, SANE_Int *length)
+{
+ SANE_Status status = SANE_STATUS_GOOD;
+
+ *length = 0;
+
+ if (s->canceling)
+ return SANE_STATUS_CANCELLED;
+
+ /* request image data */
+ eds_send(s, "IMG x0000000", 12, &status);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ /* receive DataHeaderBlock */
+ memset(s->buf, 0x00, 64);
+ eds_recv(s, s->buf, 64, &status);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ /* check if we need to read any image data */
+ unsigned int more = 0;
+ if (!esci2_check_header("IMG ", (char *)s->buf, &more)) {
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ /* this handles eof and errors */
+ SANE_Status parse_status = esci2_parse_block((char *)s->buf + 12, 64 - 12, s, &img_cb);
+
+ /* no more data? return using the status of the esci2_parse_block
+ * call, which might hold other error conditions.
+ */
+ if (!more) {
+ return parse_status;
+ }
+
+ /* ALWAYS read image data */
+ ssize_t read = eds_recv(s, s->buf, more, &status);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ if (read != more) {
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ /* handle esci2_parse_block errors */
+ if (parse_status != SANE_STATUS_GOOD) {
+ return parse_status;
+ }
+
+ DBG(15, "%s: read %lu bytes, status: %d\n", __func__, (unsigned long) read, status);
+
+ *length = read;
+
+ if (s->canceling) {
+ return SANE_STATUS_CANCELLED;
+ }
+
+ return SANE_STATUS_GOOD;
+}
diff --git a/backend/epsonds-cmd.h b/backend/epsonds-cmd.h
new file mode 100644
index 0000000..923e811
--- /dev/null
+++ b/backend/epsonds-cmd.h
@@ -0,0 +1,29 @@
+/*
+ * epsonds-cmd.h - Epson ESC/I-2 routines.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#ifndef epsonds_cmd_h
+#define epsonds_cmd_h
+
+SANE_Status esci2_info(epsonds_scanner *s);
+SANE_Status esci2_fin(epsonds_scanner *s);
+SANE_Status esci2_can(epsonds_scanner *s);
+SANE_Status esci2_capa(epsonds_scanner *s);
+SANE_Status esci2_resa(epsonds_scanner *s);
+SANE_Status esci2_stat(epsonds_scanner *s);
+SANE_Status esci2_para(epsonds_scanner *s, char *parameters);
+SANE_Status esci2_mech(epsonds_scanner *s, char *parameters);
+SANE_Status esci2_trdt(epsonds_scanner *s);
+SANE_Status esci2_img(struct epsonds_scanner *s, SANE_Int *length) ;
+
+#endif
+
diff --git a/backend/epsonds-io.c b/backend/epsonds-io.c
new file mode 100644
index 0000000..28bacfc
--- /dev/null
+++ b/backend/epsonds-io.c
@@ -0,0 +1,177 @@
+/*
+ * epsonds-io.c - Epson ESC/I-2 driver, low level I/O.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#define DEBUG_DECLARE_ONLY
+
+#include "sane/config.h"
+#include <ctype.h>
+#include <unistd.h> /* sleep */
+
+#include "epsonds.h"
+#include "epsonds-io.h"
+
+size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status)
+{
+ DBG(32, "%s: size = %lu\n", __func__, (u_long) length);
+
+ if (length == 2) {
+
+ char *cmd = buf;
+
+ switch (cmd[0]) {
+ case FS:
+ DBG(9, "%s: FS %c\n", __func__, cmd[1]);
+ break;
+ }
+ }
+
+ if (s->hw->connection == SANE_EPSONDS_NET) {
+ /* XXX */
+ } else if (s->hw->connection == SANE_EPSONDS_USB) {
+
+ size_t n = length;
+
+ *status = sanei_usb_write_bulk(s->fd, buf, &n);
+
+ return n;
+ }
+
+ /* never reached */
+
+ *status = SANE_STATUS_INVAL;
+
+ return 0;
+}
+
+size_t eds_recv(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status)
+{
+ size_t n = 0;
+
+ DBG(30, "%s: size = %ld, buf = %p\n", __func__, (long) length, buf);
+
+ if (s->hw->connection == SANE_EPSONDS_NET) {
+ /* XXX */
+ } else if (s->hw->connection == SANE_EPSONDS_USB) {
+
+ /* !!! only report an error if we don't read anything */
+
+ n = length;
+ *status = sanei_usb_read_bulk(s->fd, (SANE_Byte *)buf,
+ (size_t *) &n);
+ if (n > 0)
+ *status = SANE_STATUS_GOOD;
+ }
+
+ if (n < length) {
+ DBG(1, "%s: expected = %lu, got = %ld, canceling: %d\n", __func__,
+ (u_long)length, (long)n, s->canceling);
+
+ *status = SANE_STATUS_IO_ERROR;
+ }
+
+ return n;
+}
+
+/* Simple function to exchange a fixed amount of data with the scanner */
+
+SANE_Status eds_txrx(epsonds_scanner* s, char *txbuf, size_t txlen,
+ char *rxbuf, size_t rxlen)
+{
+ SANE_Status status;
+ size_t done;
+
+ done = eds_send(s, txbuf, txlen, &status);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status));
+ return status;
+ }
+
+ if (done != txlen) {
+ DBG(1, "%s: tx err, short write\n", __func__);
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ done = eds_recv(s, rxbuf, rxlen, &status);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status));
+ }
+
+ return status;
+}
+
+/* This function should be used to send codes that only requires the scanner
+ * to give back an ACK or a NAK, namely FS X or FS Y
+ */
+
+SANE_Status eds_control(epsonds_scanner *s, void *buf, size_t buf_size)
+{
+ char result;
+ SANE_Status status;
+
+ DBG(12, "%s: size = %lu\n", __func__, (u_long) buf_size);
+
+ status = eds_txrx(s, buf, buf_size, &result, 1);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: failed, %s\n", __func__, sane_strstatus(status));
+ return status;
+ }
+
+ if (result == ACK)
+ return SANE_STATUS_GOOD;
+
+ if (result == NAK) {
+ DBG(3, "%s: NAK\n", __func__);
+ return SANE_STATUS_INVAL;
+ }
+
+ DBG(1, "%s: result is neither ACK nor NAK but 0x%02x\n",
+ __func__, result);
+
+ return SANE_STATUS_INVAL;
+}
+
+SANE_Status eds_fsy(epsonds_scanner *s)
+{
+ return eds_control(s, "\x1CY", 2);
+}
+
+SANE_Status eds_fsx(epsonds_scanner *s)
+{
+ SANE_Status status = eds_control(s, "\x1CX", 2);
+ if (status == SANE_STATUS_GOOD) {
+ s->locked = 1;
+ }
+
+ return status;
+}
+
+SANE_Status eds_lock(epsonds_scanner *s)
+{
+ SANE_Status status;
+
+ DBG(5, "%s\n", __func__);
+
+ if (s->hw->connection == SANE_EPSONDS_USB) {
+ sanei_usb_set_timeout(USB_SHORT_TIMEOUT);
+ }
+
+ status = eds_fsx(s);
+
+ if (s->hw->connection == SANE_EPSONDS_USB) {
+ sanei_usb_set_timeout(USB_TIMEOUT);
+ }
+
+ return status;
+}
+
+
diff --git a/backend/epsonds-io.h b/backend/epsonds-io.h
new file mode 100644
index 0000000..1a1b2b7
--- /dev/null
+++ b/backend/epsonds-io.h
@@ -0,0 +1,33 @@
+/*
+ * epsonds-io.h - Epson ESC/I-2 driver, low level I/O.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#ifndef epsonds_io_h
+#define epsonds_io_h
+
+#define USB_TIMEOUT (6 * 1000)
+#define USB_SHORT_TIMEOUT (1 * 800)
+
+size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status);
+size_t eds_recv(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status);
+
+SANE_Status eds_txrx(epsonds_scanner *s, char *txbuf, size_t txlen,
+ char *rxbuf, size_t rxlen);
+
+SANE_Status eds_control(epsonds_scanner *s, void *buf, size_t buf_size);
+
+SANE_Status eds_fsy(epsonds_scanner *s);
+SANE_Status eds_fsx(epsonds_scanner *s);
+SANE_Status eds_lock(epsonds_scanner *s);
+
+#endif
+
diff --git a/backend/epsonds-jpeg.c b/backend/epsonds-jpeg.c
new file mode 100644
index 0000000..d825d99
--- /dev/null
+++ b/backend/epsonds-jpeg.c
@@ -0,0 +1,221 @@
+/*
+ * epsonds-jpeg.c - Epson ESC/I-2 driver, JPEG support.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#define DEBUG_DECLARE_ONLY
+
+#include <math.h>
+
+#include "epsonds.h"
+#include "epsonds-jpeg.h"
+#include "epsonds-ops.h"
+
+#define min(A,B) (((A)<(B)) ? (A) : (B))
+
+typedef struct
+{
+ struct jpeg_source_mgr pub;
+
+ epsonds_scanner *s;
+ JOCTET *buffer;
+
+ SANE_Byte *linebuffer;
+ SANE_Int linebuffer_size;
+ SANE_Int linebuffer_index;
+}
+epsonds_src_mgr;
+
+METHODDEF(void)
+jpeg_init_source(j_decompress_ptr UNUSEDARG cinfo)
+{
+}
+
+METHODDEF(void)
+jpeg_term_source(j_decompress_ptr UNUSEDARG cinfo)
+{
+}
+
+METHODDEF(boolean)
+jpeg_fill_input_buffer(j_decompress_ptr cinfo)
+{
+ epsonds_src_mgr *src = (epsonds_src_mgr *)cinfo->src;
+
+ /* read from the scanner or the ring buffer */
+
+ int avail = eds_ring_avail(src->s->current);
+ if (avail == 0) {
+ return FALSE;
+ }
+
+ /* read from scanner if no data? */
+ int size = min(1024, avail);
+
+ eds_ring_read(src->s->current, src->buffer, size);
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = size;
+
+ return TRUE;
+}
+
+METHODDEF (void)
+jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+ epsonds_src_mgr *src = (epsonds_src_mgr *)cinfo->src;
+
+ if (num_bytes > 0) {
+
+ while (num_bytes > (long)src->pub.bytes_in_buffer) {
+ num_bytes -= (long)src->pub.bytes_in_buffer;
+ jpeg_fill_input_buffer(cinfo);
+ }
+
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+SANE_Status
+eds_jpeg_start(epsonds_scanner *s)
+{
+ epsonds_src_mgr *src;
+
+ s->jpeg_cinfo.err = jpeg_std_error(&s->jpeg_err);
+
+ jpeg_create_decompress(&s->jpeg_cinfo);
+
+ s->jpeg_cinfo.src = (struct jpeg_source_mgr *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo,
+ JPOOL_PERMANENT, sizeof(epsonds_src_mgr));
+
+ memset(s->jpeg_cinfo.src, 0x00, sizeof(epsonds_src_mgr));
+
+ src = (epsonds_src_mgr *)s->jpeg_cinfo.src;
+ src->s = s;
+
+ src->buffer = (JOCTET *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo,
+ JPOOL_PERMANENT,
+ 1024 * sizeof(JOCTET));
+
+ src->pub.init_source = jpeg_init_source;
+ src->pub.fill_input_buffer = jpeg_fill_input_buffer;
+ src->pub.skip_input_data = jpeg_skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart;
+ src->pub.term_source = jpeg_term_source;
+ src->pub.bytes_in_buffer = 0;
+ src->pub.next_input_byte = NULL;
+
+ s->jpeg_header_seen = 0;
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status
+eds_jpeg_read_header(epsonds_scanner *s)
+{
+ epsonds_src_mgr *src = (epsonds_src_mgr *)s->jpeg_cinfo.src;
+
+ if (jpeg_read_header(&s->jpeg_cinfo, TRUE)) {
+
+ s->jdst = sanei_jpeg_jinit_write_ppm(&s->jpeg_cinfo);
+
+ if (jpeg_start_decompress(&s->jpeg_cinfo)) {
+
+ DBG(3, "%s: w: %d, h: %d, components: %d\n",
+ __func__,
+ s->jpeg_cinfo.output_width, s->jpeg_cinfo.output_height,
+ s->jpeg_cinfo.output_components);
+
+ int size = s->jpeg_cinfo.output_width * s->jpeg_cinfo.output_components * 1;
+
+ src->linebuffer = (*s->jpeg_cinfo.mem->alloc_large)((j_common_ptr)&s->jpeg_cinfo,
+ JPOOL_PERMANENT, size);
+
+ src->linebuffer_size = 0;
+ src->linebuffer_index = 0;
+
+ s->jpeg_header_seen = 1;
+
+ return SANE_STATUS_GOOD;
+
+ } else {
+ DBG(0, "%s: decompression failed\n", __func__);
+ return SANE_STATUS_IO_ERROR;
+ }
+ } else {
+ DBG(0, "%s: cannot read JPEG header\n", __func__);
+ return SANE_STATUS_IO_ERROR;
+ }
+}
+
+void
+eds_jpeg_finish(epsonds_scanner *s)
+{
+ jpeg_destroy_decompress(&s->jpeg_cinfo);
+}
+
+void
+eds_jpeg_read(SANE_Handle handle, SANE_Byte *data,
+ SANE_Int max_length, SANE_Int *length)
+{
+ epsonds_scanner *s = handle;
+
+ *length = 0;
+
+ struct jpeg_decompress_struct cinfo = s->jpeg_cinfo;
+ epsonds_src_mgr *src = (epsonds_src_mgr *)s->jpeg_cinfo.src;
+
+ /* copy from line buffer if available */
+ if (src->linebuffer_size && src->linebuffer_index < src->linebuffer_size) {
+
+ *length = src->linebuffer_size - src->linebuffer_index;
+
+ if (*length > max_length)
+ *length = max_length;
+
+ memcpy(data, src->linebuffer + src->linebuffer_index, *length);
+ src->linebuffer_index += *length;
+
+ return;
+ }
+
+ if (cinfo.output_scanline >= cinfo.output_height) {
+ *length = 0;
+ return;
+ }
+
+ /* scanlines of decompressed data will be in s->jdst->buffer
+ * only one line at time is supported
+ */
+
+ int l = jpeg_read_scanlines(&cinfo, s->jdst->buffer, 1);
+ if (l == 0) {
+ return;
+ }
+
+ /* from s->jdst->buffer to linebuffer
+ * linebuffer holds width * bytesperpixel
+ */
+
+ (*s->jdst->put_pixel_rows)(&cinfo, s->jdst, 1, (char *)src->linebuffer);
+
+ *length = cinfo.output_width * cinfo.output_components * 1;
+ src->linebuffer_size = *length;
+ src->linebuffer_index = 0;
+
+ if (*length > max_length)
+ *length = max_length;
+
+ memcpy(data, src->linebuffer + src->linebuffer_index, *length);
+ src->linebuffer_index += *length;
+}
+
+
diff --git a/backend/epsonds-jpeg.h b/backend/epsonds-jpeg.h
new file mode 100644
index 0000000..c54208e
--- /dev/null
+++ b/backend/epsonds-jpeg.h
@@ -0,0 +1,19 @@
+/*
+ * epsonds.c - Epson ESC/I-2 driver, JPEG support.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#define UNUSEDARG __attribute__ ((unused))
+
+SANE_Status eds_jpeg_start(epsonds_scanner *s);
+void eds_jpeg_finish(epsonds_scanner *s);
+SANE_Status eds_jpeg_read_header(epsonds_scanner *s);
+void eds_jpeg_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length);
diff --git a/backend/epsonds-ops.c b/backend/epsonds-ops.c
new file mode 100644
index 0000000..94f1071
--- /dev/null
+++ b/backend/epsonds-ops.c
@@ -0,0 +1,474 @@
+/*
+ * epsonds-ops.c - Epson ESC/I-2 driver, support routines.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#define DEBUG_DECLARE_ONLY
+
+#include "sane/config.h"
+
+#include <unistd.h> /* sleep */
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "epsonds.h"
+#include "epsonds-io.h"
+#include "epsonds-ops.h"
+#include "epsonds-cmd.h"
+
+extern struct mode_param mode_params[];
+
+/* Define the different scan sources */
+
+#define FBF_STR SANE_I18N("Flatbed")
+#define TPU_STR SANE_I18N("Transparency Unit")
+#define ADF_STR SANE_I18N("Automatic Document Feeder")
+
+extern SANE_String_Const source_list[];
+
+void
+eds_dev_init(epsonds_device *dev)
+{
+ dev->res_list = malloc(sizeof(SANE_Word));
+ dev->res_list[0] = 0;
+
+ dev->depth_list = malloc(sizeof(SANE_Word));
+ dev->depth_list[0] = 0;
+}
+
+SANE_Status
+eds_dev_post_init(struct epsonds_device *dev)
+{
+ DBG(10, "%s\n", __func__);
+
+ SANE_String_Const *source_list_add = source_list;
+ if (dev->has_fb)
+ *source_list_add++ = FBF_STR;
+
+ if (dev->has_adf)
+ *source_list_add++ = ADF_STR;
+
+ if (source_list[0] == 0
+ || (dev->res_list[0] == 0 && dev->dpi_range.min == 0)
+ || dev->depth_list[0] == 0) {
+
+ DBG(1, "something is wrong in the discovery process, aborting.\n");
+ DBG(1, "sources: %ld, res: %d, depths: %d.\n",
+ source_list_add - source_list, dev->res_list[0], dev->depth_list[0]);
+
+ return SANE_STATUS_INVAL;
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status
+eds_add_resolution(epsonds_device *dev, int r)
+{
+ DBG(10, "%s: add (dpi): %d\n", __func__, r);
+
+ /* first element is the list size */
+ dev->res_list[0]++;
+ dev->res_list = realloc(dev->res_list,
+ (dev->res_list[0] + 1) *
+ sizeof(SANE_Word));
+ if (dev->res_list == NULL)
+ return SANE_STATUS_NO_MEM;
+
+ dev->res_list[dev->res_list[0]] = r;
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status
+eds_set_resolution_range(epsonds_device *dev, int min, int max)
+{
+ DBG(10, "%s: set min/max (dpi): %d/%d\n", __func__, min, max);
+
+ dev->dpi_range.min = min;
+ dev->dpi_range.max = max;
+ dev->dpi_range.quant = 1;
+
+ return SANE_STATUS_GOOD;
+}
+
+void
+eds_set_fbf_area(epsonds_device *dev, int x, int y, int unit)
+{
+ if (x == 0 || y == 0)
+ return;
+
+ dev->fbf_x_range.min = 0;
+ dev->fbf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit);
+ dev->fbf_x_range.quant = 0;
+
+ dev->fbf_y_range.min = 0;
+ dev->fbf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit);
+ dev->fbf_y_range.quant = 0;
+
+ DBG(5, "%s: %f,%f %f,%f %d [mm]\n",
+ __func__,
+ SANE_UNFIX(dev->fbf_x_range.min),
+ SANE_UNFIX(dev->fbf_y_range.min),
+ SANE_UNFIX(dev->fbf_x_range.max),
+ SANE_UNFIX(dev->fbf_y_range.max), unit);
+}
+
+void
+eds_set_adf_area(struct epsonds_device *dev, int x, int y, int unit)
+{
+ dev->adf_x_range.min = 0;
+ dev->adf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit);
+ dev->adf_x_range.quant = 0;
+
+ dev->adf_y_range.min = 0;
+ dev->adf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit);
+ dev->adf_y_range.quant = 0;
+
+ DBG(5, "%s: %f,%f %f,%f %d [mm]\n",
+ __func__,
+ SANE_UNFIX(dev->adf_x_range.min),
+ SANE_UNFIX(dev->adf_y_range.min),
+ SANE_UNFIX(dev->adf_x_range.max),
+ SANE_UNFIX(dev->adf_y_range.max), unit);
+}
+
+void
+eds_set_tpu_area(struct epsonds_device *dev, int x, int y, int unit)
+{
+ dev->tpu_x_range.min = 0;
+ dev->tpu_x_range.max = SANE_FIX(x * MM_PER_INCH / unit);
+ dev->tpu_x_range.quant = 0;
+
+ dev->tpu_y_range.min = 0;
+ dev->tpu_y_range.max = SANE_FIX(y * MM_PER_INCH / unit);
+ dev->tpu_y_range.quant = 0;
+
+ DBG(5, "%s: %f,%f %f,%f %d [mm]\n",
+ __func__,
+ SANE_UNFIX(dev->tpu_x_range.min),
+ SANE_UNFIX(dev->tpu_y_range.min),
+ SANE_UNFIX(dev->tpu_x_range.max),
+ SANE_UNFIX(dev->tpu_y_range.max), unit);
+}
+
+SANE_Status
+eds_add_depth(epsonds_device *dev, SANE_Word depth)
+{
+ DBG(5, "%s: add (bpp): %d\n", __func__, depth);
+
+ /* > 8bpp not implemented yet */
+ if (depth > 8) {
+ DBG(1, " not supported");
+ return SANE_STATUS_GOOD;
+ }
+
+ if (depth > dev->max_depth)
+ dev->max_depth = depth;
+
+ /* first element is the list size */
+ dev->depth_list[0]++;
+ dev->depth_list = realloc(dev->depth_list,
+ (dev->depth_list[0] + 1) *
+ sizeof(SANE_Word));
+
+ if (dev->depth_list == NULL)
+ return SANE_STATUS_NO_MEM;
+
+ dev->depth_list[dev->depth_list[0]] = depth;
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status
+eds_init_parameters(epsonds_scanner *s)
+{
+ int dpi, bytes_per_pixel;
+
+ memset(&s->params, 0, sizeof(SANE_Parameters));
+
+ s->dummy = 0;
+
+ dpi = s->val[OPT_RESOLUTION].w;
+
+ if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 ||
+ SANE_UNFIX(s->val[OPT_BR_X].w) == 0)
+ return SANE_STATUS_INVAL;
+
+ s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) *
+ s->val[OPT_RESOLUTION].w) + 0.5;
+
+ s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) *
+ s->val[OPT_RESOLUTION].w) + 0.5;
+
+ s->params.pixels_per_line =
+ ((SANE_UNFIX(s->val[OPT_BR_X].w -
+ s->val[OPT_TL_X].w) / MM_PER_INCH) * dpi) + 0.5;
+ s->params.lines =
+ ((SANE_UNFIX(s->val[OPT_BR_Y].w -
+ s->val[OPT_TL_Y].w) / MM_PER_INCH) * dpi) + 0.5;
+
+ DBG(5, "%s: tlx %f tly %f brx %f bry %f [mm]\n",
+ __func__,
+ SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w),
+ SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w));
+
+ DBG(5, "%s: tlx %d tly %d brx %d bry %d [dots @ %d dpi]\n",
+ __func__, s->left, s->top,
+ s->params.pixels_per_line, s->params.lines, dpi);
+
+ /* center aligned? */
+ if (s->hw->alignment == 1) {
+
+ SANE_Int offset = ((SANE_UNFIX(s->hw->x_range->max) / MM_PER_INCH) * dpi) + 0.5;
+
+ s->left += ((offset - s->params.pixels_per_line) / 2);
+
+ DBG(5, "%s: centered to tlx %d tly %d brx %d bry %d [dots @ %d dpi]\n",
+ __func__, s->left, s->top,
+ s->params.pixels_per_line, s->params.lines, dpi);
+ }
+
+ /*
+ * Calculate bytes_per_pixel and bytes_per_line for
+ * any color depths.
+ *
+ * The default color depth is stored in mode_params.depth:
+ */
+
+ if (mode_params[s->val[OPT_MODE].w].depth == 1)
+ s->params.depth = 1;
+ else
+ s->params.depth = s->val[OPT_DEPTH].w;
+
+ /* this works because it can only be set to 1, 8 or 16 */
+ bytes_per_pixel = s->params.depth / 8;
+ if (s->params.depth % 8) { /* just in case ... */
+ bytes_per_pixel++;
+ }
+
+ /* pixels_per_line is rounded to the next 8bit boundary */
+ s->params.pixels_per_line = s->params.pixels_per_line & ~7;
+
+ s->params.last_frame = SANE_TRUE;
+
+ switch (s->val[OPT_MODE].w) {
+ case MODE_BINARY:
+ case MODE_GRAY:
+ s->params.format = SANE_FRAME_GRAY;
+ s->params.bytes_per_line =
+ s->params.pixels_per_line * s->params.depth / 8;
+ break;
+ case MODE_COLOR:
+ s->params.format = SANE_FRAME_RGB;
+ s->params.bytes_per_line =
+ 3 * s->params.pixels_per_line * bytes_per_pixel;
+ break;
+ }
+
+ if (s->params.bytes_per_line == 0) {
+ DBG(1, "bytes_per_line is ZERO\n");
+ return SANE_STATUS_INVAL;
+ }
+
+ /*
+ * If (s->top + s->params.lines) is larger than the max scan area, reset
+ * the number of scan lines:
+ * XXX: precalculate the maximum scanning area elsewhere (use dev max_y)
+ */
+
+ if (SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH * dpi <
+ (s->params.lines + s->top)) {
+ s->params.lines =
+ ((int) SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH *
+ dpi + 0.5) - s->top;
+ }
+
+ if (s->params.lines <= 0) {
+ DBG(1, "wrong number of lines: %d\n", s->params.lines);
+ return SANE_STATUS_INVAL;
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+void
+eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_length,
+ SANE_Int *length)
+{
+ int lines, available;
+ int hw_line_size = (s->params.bytes_per_line + s->dummy);
+
+ /* trim max_length to a multiple of hw_line_size */
+ max_length -= (max_length % hw_line_size);
+
+ /* check available data */
+ available = eds_ring_avail(s->current);
+ if (max_length > available)
+ max_length = available;
+
+ lines = max_length / hw_line_size;
+
+ DBG(18, "copying %d lines (%d, %d)\n", lines, s->params.bytes_per_line, s->dummy);
+
+ /* need more data? */
+ if (lines == 0) {
+ *length = 0;
+ return;
+ }
+
+ *length = (lines * s->params.bytes_per_line);
+
+ /* we need to copy one line at time, skipping
+ * dummy bytes at the end of each line
+ */
+
+ /* lineart */
+ if (s->params.depth == 1) {
+
+ while (lines--) {
+
+ eds_ring_read(s->current, s->line_buffer, s->params.bytes_per_line);
+ eds_ring_skip(s->current, s->dummy);
+
+ int i;
+
+ SANE_Byte *p = s->line_buffer;
+
+ for (i = 0; i < s->params.bytes_per_line; i++) {
+ *data++ = ~*p++;
+ }
+ }
+
+ } else { /* gray and color */
+
+ while (lines--) {
+
+ eds_ring_read(s->current, data, s->params.bytes_per_line);
+ eds_ring_skip(s->current, s->dummy);
+
+ data += s->params.bytes_per_line;
+
+ }
+ }
+}
+
+SANE_Status eds_ring_init(ring_buffer *ring, SANE_Int size)
+{
+ ring->ring = realloc(ring->ring, size);
+ if (!ring->ring) {
+ return SANE_STATUS_NO_MEM;
+ }
+
+ ring->size = size;
+ ring->fill = 0;
+ ring->end = ring->ring + size;
+ ring->wp = ring->rp = ring->ring;
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status eds_ring_write(ring_buffer *ring, SANE_Byte *buf, SANE_Int size)
+{
+ if (size > (ring->size - ring->fill)) {
+ DBG(1, "ring buffer full, requested: %d, available: %d\n", size, ring->size - ring->fill);
+ return SANE_STATUS_NO_MEM;
+ }
+
+ SANE_Int tail = ring->end - ring->wp;
+ if (size < tail) {
+
+ memcpy(ring->wp, buf, size);
+
+ ring->wp += size;
+ ring->fill += size;
+
+ } else {
+
+ memcpy(ring->wp, buf, tail);
+ size -= tail;
+
+ ring->wp = ring->ring;
+ memcpy(ring->wp, buf + tail, size);
+
+ ring->wp += size;
+ ring->fill += (tail + size);
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size)
+{
+ DBG(18, "reading from ring, %d bytes available\n", (int)ring->fill);
+
+ /* limit read to available */
+ if (size > ring->fill) {
+ DBG(1, "not enough data in the ring, shouldn't happen\n");
+ size = ring->fill;
+ }
+
+ SANE_Int tail = ring->end - ring->rp;
+ if (size < tail) {
+
+ memcpy(buf, ring->rp, size);
+
+ ring->rp += size;
+ ring->fill -= size;
+
+ return size;
+
+ } else {
+
+ memcpy(buf, ring->rp, tail);
+ size -= tail;
+
+ ring->rp = ring->ring;
+ memcpy(buf + tail, ring->rp, size);
+
+ ring->rp += size;
+ ring->fill -= (size + tail);
+
+ return size + tail;
+ }
+}
+
+SANE_Int eds_ring_skip(ring_buffer *ring, SANE_Int size)
+{
+ /* limit skip to available */
+ if (size > ring->fill)
+ size = ring->fill;
+
+ SANE_Int tail = ring->end - ring->rp;
+ if (size < tail) {
+ ring->rp += size;
+ } else {
+
+ ring->rp = ring->ring + (size - tail);
+ }
+
+ ring->fill -= size;
+
+ return size;
+}
+
+SANE_Int eds_ring_avail(ring_buffer *ring)
+{
+ return ring->fill;
+}
+
+void eds_ring_flush(ring_buffer *ring)
+{
+ eds_ring_skip(ring, ring->fill);
+}
+
+
diff --git a/backend/epsonds-ops.h b/backend/epsonds-ops.h
new file mode 100644
index 0000000..3f45393
--- /dev/null
+++ b/backend/epsonds-ops.h
@@ -0,0 +1,41 @@
+/*
+ * epsonds-ops.h - Epson ESC/I-2 driver.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#define e2_model(s,m) e2_dev_model((s)->hw,(m))
+
+extern void eds_dev_init(epsonds_device *dev);
+extern SANE_Status eds_dev_post_init(struct epsonds_device *dev);
+
+extern SANE_Status eds_add_resolution(epsonds_device *dev, int r);
+extern SANE_Status eds_set_resolution_range(epsonds_device *dev, int min, int max);
+extern void eds_set_fbf_area(epsonds_device *dev, int x, int y, int unit);
+extern void eds_set_adf_area(epsonds_device *dev, int x, int y, int unit);
+extern void eds_set_tpu_area(epsonds_device *dev, int x, int y, int unit);
+
+extern SANE_Status eds_add_depth(epsonds_device *dev, SANE_Word depth);
+extern SANE_Status eds_discover_capabilities(epsonds_scanner *s);
+extern SANE_Status eds_set_extended_scanning_parameters(epsonds_scanner *s);
+extern SANE_Status eds_set_scanning_parameters(epsonds_scanner *s);
+extern void eds_setup_block_mode(epsonds_scanner *s);
+extern SANE_Status eds_init_parameters(epsonds_scanner *s);
+
+extern void eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_length,
+ SANE_Int *length);
+
+extern SANE_Status eds_ring_init(ring_buffer *ring, SANE_Int size);
+extern SANE_Status eds_ring_write(ring_buffer *ring, SANE_Byte *buf, SANE_Int size);
+extern SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size);
+extern SANE_Int eds_ring_skip(ring_buffer *ring, SANE_Int size);
+extern SANE_Int eds_ring_avail(ring_buffer *ring);
+extern void eds_ring_flush(ring_buffer *ring) ;
+
diff --git a/backend/epsonds-usb.c b/backend/epsonds-usb.c
new file mode 100644
index 0000000..c7e514c
--- /dev/null
+++ b/backend/epsonds-usb.c
@@ -0,0 +1,33 @@
+/*
+ * epsonds-usb.c - Epson ESC/I-2 driver, USB device list.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#include "epsonds-usb.h"
+
+SANE_Word epsonds_usb_product_ids[] = {
+ 0x0145, /* DS-5500, DS-6500, DS-7500 */
+ 0x0146, /* DS-50000, DS-60000, DS-70000 */
+ 0x014c, /* DS-510 */
+ 0x014d, /* DS-560 */
+ 0x0150, /* DS-40 */
+ 0x0152, /* DS-760, DS-860 */
+ 0x0154, /* DS-520 */
+ 0x08bc, /* PX-M7050 Series, WF-8510/8590 Series */
+ 0x08cc, /* PX-M7050FX Series, WF-R8590 Series */
+ 0 /* last entry - this is used for devices that are specified
+ in the config file as "usb <vendor> <product>" */
+};
+
+int epsonds_get_number_of_ids(void)
+{
+ return sizeof (epsonds_usb_product_ids) / sizeof (SANE_Word);
+}
diff --git a/backend/epsonds-usb.h b/backend/epsonds-usb.h
new file mode 100644
index 0000000..96c77b5
--- /dev/null
+++ b/backend/epsonds-usb.h
@@ -0,0 +1,24 @@
+/*
+ * epsonds-usb.h - Epson ESC/I-2 driver, USB device list.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#include "sane/sane.h"
+
+#ifndef _EPSONDS_USB_H_
+#define _EPSONDS_USB_H_
+
+#define SANE_EPSONDS_VENDOR_ID (0x4b8)
+
+extern SANE_Word epsonds_usb_product_ids[];
+extern int epsonds_get_number_of_ids(void);
+
+#endif
diff --git a/backend/epsonds.c b/backend/epsonds.c
new file mode 100644
index 0000000..d16744f
--- /dev/null
+++ b/backend/epsonds.c
@@ -0,0 +1,1434 @@
+/*
+ * epsonds.c - Epson ESC/I-2 driver.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#define EPSONDS_VERSION 1
+#define EPSONDS_REVISION 0
+#define EPSONDS_BUILD 35
+
+/* debugging levels:
+ *
+ * 32 eds_send
+ * 30 eds_recv
+ * 20 sane_read and related
+ * 18 sane_read and related
+ * 17 setvalue, getvalue, control_option
+ * 16
+ * 15 esci2_img
+ * 13 image_cb
+ * 12 eds_control
+ * 11 all received params
+ * 10 some received params
+ * 9
+ * 8 esci2_xxx
+ * 7 open/close/attach
+ * 6 print_params
+ * 5 basic functions
+ * 3 JPEG decompressor
+ * 1 scanner info and capabilities
+ * 0 errors
+ */
+
+#include "sane/config.h"
+
+#include <ctype.h>
+
+#include "sane/saneopts.h"
+#include "sane/sanei_config.h"
+
+#include "epsonds.h"
+#include "epsonds-usb.h"
+#include "epsonds-io.h"
+#include "epsonds-cmd.h"
+#include "epsonds-ops.h"
+#include "epsonds-jpeg.h"
+
+/*
+ * Definition of the mode_param struct, that is used to
+ * specify the valid parameters for the different scan modes.
+ *
+ * The depth variable gets updated when the bit depth is modified.
+ */
+
+struct mode_param mode_params[] = {
+ {0, 0x00, 0x30, 1},
+ {0, 0x00, 0x30, 8},
+ {1, 0x02, 0x00, 8},
+ {0, 0x00, 0x30, 1}
+};
+
+static SANE_String_Const mode_list[] = {
+ SANE_VALUE_SCAN_MODE_LINEART,
+ SANE_VALUE_SCAN_MODE_GRAY,
+ SANE_VALUE_SCAN_MODE_COLOR,
+ NULL
+};
+
+static const SANE_String_Const adf_mode_list[] = {
+ SANE_I18N("Simplex"),
+ SANE_I18N("Duplex"),
+ NULL
+};
+
+/* Define the different scan sources */
+
+#define FBF_STR SANE_I18N("Flatbed")
+#define ADF_STR SANE_I18N("Automatic Document Feeder")
+
+/* order will be fixed: fb, adf, tpu */
+SANE_String_Const source_list[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * List of pointers to devices - will be dynamically allocated depending
+ * on the number of devices found.
+ */
+static const SANE_Device **devlist;
+
+/* Some utility functions */
+
+static size_t
+max_string_size(const SANE_String_Const strings[])
+{
+ size_t size, max_size = 0;
+ int i;
+
+ for (i = 0; strings[i]; i++) {
+ size = strlen(strings[i]) + 1;
+ if (size > max_size)
+ max_size = size;
+ }
+ return max_size;
+}
+
+static SANE_Status attach_one_usb(SANE_String_Const devname);
+
+static void
+print_params(const SANE_Parameters params)
+{
+ DBG(6, "params.format = %d\n", params.format);
+ DBG(6, "params.last_frame = %d\n", params.last_frame);
+ DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line);
+ DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line);
+ DBG(6, "params.lines = %d\n", params.lines);
+ DBG(6, "params.depth = %d\n", params.depth);
+}
+
+static void
+close_scanner(epsonds_scanner *s)
+{
+ DBG(7, "%s: fd = %d\n", __func__, s->fd);
+
+ if (s->fd == -1)
+ return;
+
+ if (s->locked) {
+ DBG(7, " unlocking scanner\n");
+ esci2_fin(s);
+ }
+
+ if (s->hw->connection == SANE_EPSONDS_USB) {
+ sanei_usb_close(s->fd);
+ }
+
+ free(s->front.ring);
+ free(s->back.ring);
+ free(s->line_buffer);
+ free(s);
+
+ DBG(7, "%s: ZZZ\n", __func__);
+}
+
+static SANE_Status
+open_scanner(epsonds_scanner *s)
+{
+ SANE_Status status = SANE_STATUS_INVAL;
+
+ DBG(7, "%s: %s\n", __func__, s->hw->sane.name);
+
+ if (s->fd != -1) {
+ DBG(5, "scanner is already open: fd = %d\n", s->fd);
+ return SANE_STATUS_GOOD; /* no need to open the scanner */
+ }
+
+ if (s->hw->connection == SANE_EPSONDS_USB) {
+
+ status = sanei_usb_open(s->hw->sane.name, &s->fd);
+ sanei_usb_set_timeout(USB_TIMEOUT);
+
+ } else {
+ DBG(1, "unknown connection type: %d\n", s->hw->connection);
+ }
+
+ if (status == SANE_STATUS_ACCESS_DENIED) {
+ DBG(1, "please check that you have permissions on the device.\n");
+ DBG(1, "if this is a multi-function device with a printer,\n");
+ DBG(1, "disable any conflicting driver (like usblp).\n");
+ }
+
+ if (status != SANE_STATUS_GOOD)
+ DBG(1, "%s open failed: %s\n",
+ s->hw->sane.name,
+ sane_strstatus(status));
+ else
+ DBG(5, " opened correctly\n");
+
+ return status;
+}
+
+static SANE_Status
+validate_usb(struct epsonds_scanner *s)
+{
+ DBG(1, "%s\n", __func__);
+
+ SANE_Status status;
+ int vendor, product;
+ int i = 0, numIds;
+
+ SANE_Bool is_valid = SANE_FALSE;
+
+ /* if the sanei_usb_get_vendor_product call is not supported,
+ * then we just ignore this and rely on the user to config
+ * the correct device.
+ */
+ status = sanei_usb_get_vendor_product(s->fd, &vendor, &product);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "the device cannot be verified - will continue\n");
+ return SANE_STATUS_GOOD;
+ }
+
+ /* check the vendor ID to see if we are dealing with an EPSON device */
+ if (vendor != SANE_EPSONDS_VENDOR_ID) {
+ /* this is not a supported vendor ID */
+ DBG(1, "not an Epson device at %s (vendor id=0x%x)\n",
+ s->hw->sane.name, vendor);
+ return SANE_STATUS_INVAL;
+ }
+
+ numIds = epsonds_get_number_of_ids();
+
+ /* check all known product IDs to verify that we know
+ about the device */
+ while (i != numIds && !is_valid) {
+ if (product == epsonds_usb_product_ids[i])
+ is_valid = SANE_TRUE;
+ i++;
+ }
+
+ if (is_valid == SANE_FALSE) {
+ DBG(1, "the device at %s is not a supported (product id=0x%x)\n",
+ s->hw->sane.name, product);
+ return SANE_STATUS_INVAL;
+ }
+
+ DBG(1, "found valid Epson ESC/I-2 scanner: 0x%x/0x%x at %s\n",
+ vendor, product, s->hw->sane.name);
+
+ return SANE_STATUS_GOOD;
+}
+
+static int num_devices; /* number of scanners attached to backend */
+static epsonds_device *first_dev; /* first EPSON scanner in list */
+
+static struct epsonds_scanner *
+scanner_create(struct epsonds_device *dev, SANE_Status *status)
+{
+ struct epsonds_scanner *s;
+
+ s = malloc(sizeof(struct epsonds_scanner));
+ if (s == NULL) {
+ *status = SANE_STATUS_NO_MEM;
+ return NULL;
+ }
+
+ /* clear verything */
+ memset(s, 0x00, sizeof(struct epsonds_scanner));
+
+ s->fd = -1;
+ s->hw = dev;
+
+ return s;
+}
+
+static struct epsonds_scanner *
+device_detect(const char *name, int type, SANE_Status *status)
+{
+ struct epsonds_scanner *s;
+ struct epsonds_device *dev;
+
+ DBG(1, "%s\n", __func__);
+
+ /* try to find the device in our list */
+ for (dev = first_dev; dev; dev = dev->next) {
+ if (strcmp(dev->sane.name, name) == 0) {
+ DBG(1, " found cached device\n");
+ return scanner_create(dev, status);
+ }
+ }
+
+ /* not found, create new if valid */
+ if (type == SANE_EPSONDS_NODEV) {
+ *status = SANE_STATUS_INVAL;
+ return NULL;
+ }
+
+ /* alloc and clear our device structure */
+ dev = malloc(sizeof(*dev));
+ if (!dev) {
+ *status = SANE_STATUS_NO_MEM;
+ return NULL;
+ }
+ memset(dev, 0x00, sizeof(struct epsonds_device));
+
+ s = scanner_create(dev, status);
+ if (s == NULL)
+ return NULL;
+
+ dev->connection = type;
+ dev->model = strdup("(undetermined)");
+
+ dev->sane.name = name;
+ dev->sane.vendor = "Epson";
+ dev->sane.model = dev->model;
+ dev->sane.type = "ESC/I-2";
+
+ *status = open_scanner(s);
+ if (*status != SANE_STATUS_GOOD) {
+ free(s);
+ return NULL;
+ }
+
+ if (dev->connection == SANE_EPSONDS_USB) {
+ *status = validate_usb(s);
+ }
+
+ if (*status != SANE_STATUS_GOOD)
+ goto close;
+
+ eds_dev_init(dev);
+
+ /* lock scanner */
+ *status = eds_lock(s);
+ if (*status != SANE_STATUS_GOOD) {
+ goto close;
+ }
+
+ /* discover capabilities */
+ *status = esci2_info(s);
+ if (*status != SANE_STATUS_GOOD)
+ goto close;
+
+ *status = esci2_capa(s);
+ if (*status != SANE_STATUS_GOOD)
+ goto close;
+
+ *status = esci2_resa(s);
+ if (*status != SANE_STATUS_GOOD)
+ goto close;
+
+ /* assume 1 and 8 bit are always supported */
+ eds_add_depth(s->hw, 1);
+ eds_add_depth(s->hw, 8);
+
+ /* setup area according to available options */
+ if (s->hw->has_fb) {
+
+ dev->x_range = &dev->fbf_x_range;
+ dev->y_range = &dev->fbf_y_range;
+ dev->alignment = dev->fbf_alignment;
+
+ } else if (s->hw->has_adf) {
+
+ dev->x_range = &dev->adf_x_range;
+ dev->y_range = &dev->adf_y_range;
+ dev->alignment = dev->adf_alignment;
+
+ } else {
+ DBG(0, "unable to lay on the flatbed or feed the feeder. is that a scanner??\n");
+ }
+
+ *status = eds_dev_post_init(dev);
+ if (*status != SANE_STATUS_GOOD)
+ goto close;
+
+ DBG(1, "scanner model: %s\n", dev->model);
+
+ /* add this scanner to the device list */
+
+ num_devices++;
+ dev->next = first_dev;
+ first_dev = dev;
+
+ return s;
+
+close:
+ DBG(1, " failed\n");
+
+ close_scanner(s);
+ return NULL;
+}
+
+
+static SANE_Status
+attach(const char *name, int type)
+{
+ SANE_Status status;
+
+ DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type);
+
+ epsonds_scanner *s = device_detect(name, type, &status);
+ if (s == NULL)
+ return status;
+
+ close_scanner(s);
+ return status;
+}
+
+SANE_Status
+attach_one_usb(const char *dev)
+{
+ DBG(7, "%s: dev = %s\n", __func__, dev);
+ return attach(dev, SANE_EPSONDS_USB);
+}
+
+static SANE_Status
+attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)
+{
+ int vendor, product;
+
+ int len = strlen(line);
+
+ DBG(7, "%s: len = %d, line = %s\n", __func__, len, line);
+
+ if (sscanf(line, "usb %i %i", &vendor, &product) == 2) {
+
+ int numIds;
+
+ /* add the vendor and product IDs to the list of
+ known devices before we call the attach function */
+
+ DBG(7, " user configured device\n");
+
+ numIds = epsonds_get_number_of_ids();
+ if (vendor != 0x4b8)
+ return SANE_STATUS_INVAL; /* this is not an EPSON device */
+
+ /* add to last slot */
+ epsonds_usb_product_ids[numIds - 1] = product;
+ sanei_usb_attach_matching_devices(line, attach_one_usb);
+
+ } else if (strncmp(line, "usb", 3) == 0 && len == 3) {
+
+ int i, numIds;
+
+ DBG(7, " probing usb devices\n");
+
+ numIds = epsonds_get_number_of_ids();
+
+ for (i = 0; i < numIds; i++) {
+ sanei_usb_find_devices(0x4b8,
+ epsonds_usb_product_ids[i], attach_one_usb);
+ }
+ } else {
+ DBG(0, "unable to parse config line: %s\n", line);
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+static void
+free_devices(void)
+{
+ epsonds_device *dev, *next;
+
+ for (dev = first_dev; dev; dev = next) {
+ next = dev->next;
+ free(dev->name);
+ free(dev->model);
+ free(dev);
+ }
+
+ free(devlist);
+ first_dev = NULL;
+}
+
+static void
+probe_devices(void)
+{
+ DBG(5, "%s\n", __func__);
+
+ free_devices();
+ sanei_configure_attach(EPSONDS_CONFIG_FILE, NULL, attach_one_config);
+}
+
+/**** SANE API ****/
+
+SANE_Status
+sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
+{
+ DBG_INIT();
+ DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__);
+
+ DBG(1, "epsonds backend, version %i.%i.%i\n",
+ EPSONDS_VERSION, EPSONDS_REVISION, EPSONDS_BUILD);
+
+ if (version_code != NULL)
+ *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR,
+ EPSONDS_BUILD);
+
+ sanei_usb_init();
+
+ return SANE_STATUS_GOOD;
+}
+
+void
+sane_exit(void)
+{
+ DBG(5, "** %s\n", __func__);
+ free_devices();
+}
+
+SANE_Status
+sane_get_devices(const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only)
+{
+ int i;
+ epsonds_device *dev;
+
+ DBG(5, "** %s\n", __func__);
+
+ probe_devices();
+
+ devlist = malloc((num_devices + 1) * sizeof(devlist[0]));
+ if (!devlist) {
+ DBG(1, "out of memory (line %d)\n", __LINE__);
+ return SANE_STATUS_NO_MEM;
+ }
+
+ DBG(5, "%s - results:\n", __func__);
+
+ for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) {
+ DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model);
+ devlist[i] = &dev->sane;
+ }
+
+ devlist[i] = NULL;
+
+ *device_list = devlist;
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+init_options(epsonds_scanner *s)
+{
+ int i;
+
+ for (i = 0; i < NUM_OPTIONS; i++) {
+ s->opt[i].size = sizeof(SANE_Word);
+ s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
+ }
+
+ s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
+ s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
+ s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
+ s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
+ s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
+
+ /* "Scan Mode" group: */
+
+ s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode");
+ s->opt[OPT_MODE_GROUP].desc = "";
+ s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
+ s->opt[OPT_MODE_GROUP].cap = 0;
+
+ /* scan mode */
+ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
+ s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
+ s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
+ s->opt[OPT_MODE].type = SANE_TYPE_STRING;
+ s->opt[OPT_MODE].size = max_string_size(mode_list);
+ s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ s->opt[OPT_MODE].constraint.string_list = mode_list;
+ s->val[OPT_MODE].w = 0; /* Lineart */
+
+ /* bit depth */
+ s->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH;
+ s->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
+ s->opt[OPT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
+ s->opt[OPT_DEPTH].type = SANE_TYPE_INT;
+ s->opt[OPT_DEPTH].unit = SANE_UNIT_BIT;
+ s->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ s->opt[OPT_DEPTH].constraint.word_list = s->hw->depth_list;
+ s->val[OPT_DEPTH].w = s->hw->depth_list[1]; /* the first "real" element is the default */
+
+ /* default is Lineart, disable depth selection */
+ s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE;
+
+ /* resolution */
+ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
+ s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
+ s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
+
+ s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
+ s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
+
+ /* range */
+ if (s->hw->dpi_range.quant) {
+ s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range;
+ s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min;
+ } else { /* list */
+ s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->res_list;
+ s->val[OPT_RESOLUTION].w = s->hw->res_list[1];
+ }
+
+ /* "Geometry" group: */
+ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry");
+ s->opt[OPT_GEOMETRY_GROUP].desc = "";
+ s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
+ s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
+
+ /* top-left x */
+ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
+ s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
+ s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
+ s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
+ s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
+ s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_TL_X].constraint.range = s->hw->x_range;
+ s->val[OPT_TL_X].w = 0;
+
+ /* top-left y */
+ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
+ s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
+ s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
+
+ s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
+ s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
+ s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_TL_Y].constraint.range = s->hw->y_range;
+ s->val[OPT_TL_Y].w = 0;
+
+ /* bottom-right x */
+ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
+ s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
+ s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
+
+ s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
+ s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
+ s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
+ s->val[OPT_BR_X].w = s->hw->x_range->max;
+
+ /* bottom-right y */
+ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
+ s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
+ s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
+
+ s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
+ s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
+ s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
+ s->val[OPT_BR_Y].w = s->hw->y_range->max;
+
+ /* "Optional equipment" group: */
+ s->opt[OPT_EQU_GROUP].title = SANE_I18N("Optional equipment");
+ s->opt[OPT_EQU_GROUP].desc = "";
+ s->opt[OPT_EQU_GROUP].type = SANE_TYPE_GROUP;
+ s->opt[OPT_EQU_GROUP].cap = SANE_CAP_ADVANCED;
+
+ /* source */
+ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
+ s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
+ s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
+ s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
+ s->opt[OPT_SOURCE].size = max_string_size(source_list);
+ s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ s->opt[OPT_SOURCE].constraint.string_list = source_list;
+ s->val[OPT_SOURCE].w = 0;
+
+ s->opt[OPT_EJECT].name = "eject";
+ s->opt[OPT_EJECT].title = SANE_I18N("Eject");
+ s->opt[OPT_EJECT].desc = SANE_I18N("Eject the sheet in the ADF");
+ s->opt[OPT_EJECT].type = SANE_TYPE_BUTTON;
+
+ if (!s->hw->adf_has_eject)
+ s->opt[OPT_EJECT].cap |= SANE_CAP_INACTIVE;
+
+ s->opt[OPT_LOAD].name = "load";
+ s->opt[OPT_LOAD].title = SANE_I18N("Load");
+ s->opt[OPT_LOAD].desc = SANE_I18N("Load a sheet in the ADF");
+ s->opt[OPT_LOAD].type = SANE_TYPE_BUTTON;
+
+ if (!s->hw->adf_has_load)
+ s->opt[OPT_LOAD].cap |= SANE_CAP_INACTIVE;
+
+ s->opt[OPT_ADF_MODE].name = "adf-mode";
+ s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode");
+ s->opt[OPT_ADF_MODE].desc =
+ SANE_I18N("Selects the ADF mode (simplex/duplex)");
+ s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING;
+ s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list);
+ s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list;
+ s->val[OPT_ADF_MODE].w = 0; /* simplex */
+
+ if (!s->hw->adf_is_duplex)
+ s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE;
+
+ s->opt[OPT_ADF_SKEW].name = "adf-skew";
+ s->opt[OPT_ADF_SKEW].title = SANE_I18N("ADF Skew Correction");
+ s->opt[OPT_ADF_SKEW].desc =
+ SANE_I18N("Enables ADF skew correction");
+ s->opt[OPT_ADF_SKEW].type = SANE_TYPE_BOOL;
+ s->val[OPT_ADF_SKEW].w = 0;
+
+ if (!s->hw->adf_has_skew)
+ s->opt[OPT_ADF_SKEW].cap |= SANE_CAP_INACTIVE;
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status
+sane_open(SANE_String_Const name, SANE_Handle *handle)
+{
+ SANE_Status status;
+ epsonds_scanner *s = NULL;
+
+ int l = strlen(name);
+
+ DBG(7, "** %s: name = %s\n", __func__, name);
+
+ /* probe if empty device name provided */
+ if (l == 0) {
+
+ probe_devices();
+
+ if (first_dev == NULL) {
+ DBG(1, "no devices detected\n");
+ return SANE_STATUS_INVAL;
+ }
+
+ s = device_detect(first_dev->sane.name, first_dev->connection,
+ &status);
+ if (s == NULL) {
+ DBG(1, "cannot open a perfectly valid device (%s),"
+ " please report to the authors\n", name);
+ return SANE_STATUS_INVAL;
+ }
+
+ } else {
+
+ if (strncmp(name, "libusb:", 7) == 0) {
+ s = device_detect(name, SANE_EPSONDS_USB, &status);
+ if (s == NULL)
+ return status;
+ } else {
+
+ /* as a last resort, check for a match
+ * in the device list. This should handle SCSI
+ * devices and platforms without libusb.
+ */
+
+ if (first_dev == NULL)
+ probe_devices();
+
+ s = device_detect(name, SANE_EPSONDS_NODEV, &status);
+ if (s == NULL) {
+ DBG(1, "invalid device name: %s\n", name);
+ return SANE_STATUS_INVAL;
+ }
+ }
+ }
+
+ /* s is always valid here */
+
+ DBG(5, "%s: handle obtained\n", __func__);
+
+ init_options(s);
+
+ *handle = (SANE_Handle)s;
+
+ status = open_scanner(s);
+ if (status != SANE_STATUS_GOOD) {
+ free(s);
+ return status;
+ }
+
+ /* lock scanner if required */
+ if (!s->locked) {
+ status = eds_lock(s);
+ }
+
+ return status;
+}
+
+void
+sane_close(SANE_Handle handle)
+{
+ epsonds_scanner *s = (epsonds_scanner *)handle;
+
+ DBG(1, "** %s\n", __func__);
+
+ close_scanner(s);
+}
+
+const SANE_Option_Descriptor *
+sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
+{
+ epsonds_scanner *s = (epsonds_scanner *) handle;
+
+ if (option < 0 || option >= NUM_OPTIONS)
+ return NULL;
+
+ return s->opt + option;
+}
+
+static const SANE_String_Const *
+search_string_list(const SANE_String_Const *list, SANE_String value)
+{
+ while (*list != NULL && strcmp(value, *list) != 0)
+ list++;
+
+ return ((*list == NULL) ? NULL : list);
+}
+
+static void
+activateOption(epsonds_scanner *s, SANE_Int option, SANE_Bool *change)
+{
+ if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
+ s->opt[option].cap &= ~SANE_CAP_INACTIVE;
+ *change = SANE_TRUE;
+ }
+}
+
+static void
+deactivateOption(epsonds_scanner *s, SANE_Int option, SANE_Bool *change)
+{
+ if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
+ s->opt[option].cap |= SANE_CAP_INACTIVE;
+ *change = SANE_TRUE;
+ }
+}
+
+/*
+ * Handles setting the source (flatbed, transparency adapter (TPU),
+ * or auto document feeder (ADF)).
+ *
+ * For newer scanners it also sets the focus according to the
+ * glass / TPU settings.
+ */
+
+static void
+change_source(epsonds_scanner *s, SANE_Int optindex, char *value)
+{
+ int force_max = SANE_FALSE;
+ SANE_Bool dummy;
+
+ DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex,
+ value);
+
+ s->val[OPT_SOURCE].w = optindex;
+
+ /* if current selected area is the maximum available,
+ * keep this setting on the new source.
+ */
+ if (s->val[OPT_TL_X].w == s->hw->x_range->min
+ && s->val[OPT_TL_Y].w == s->hw->y_range->min
+ && s->val[OPT_BR_X].w == s->hw->x_range->max
+ && s->val[OPT_BR_Y].w == s->hw->y_range->max) {
+ force_max = SANE_TRUE;
+ }
+
+ if (strcmp(ADF_STR, value) == 0) {
+
+ s->hw->x_range = &s->hw->adf_x_range;
+ s->hw->y_range = &s->hw->adf_y_range;
+ s->hw->alignment = s->hw->adf_alignment;
+
+ if (s->hw->adf_is_duplex) {
+ activateOption(s, OPT_ADF_MODE, &dummy);
+ } else {
+ deactivateOption(s, OPT_ADF_MODE, &dummy);
+ s->val[OPT_ADF_MODE].w = 0;
+ }
+
+ } else if (strcmp(TPU_STR, value) == 0) {
+
+ s->hw->x_range = &s->hw->tpu_x_range;
+ s->hw->y_range = &s->hw->tpu_y_range;
+
+ deactivateOption(s, OPT_ADF_MODE, &dummy);
+
+ } else {
+
+ /* neither ADF nor TPU active, assume FB */
+ s->hw->x_range = &s->hw->fbf_x_range;
+ s->hw->y_range = &s->hw->fbf_y_range;
+ s->hw->alignment = s->hw->fbf_alignment;
+ }
+
+ s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
+ s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
+
+ if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max)
+ s->val[OPT_TL_X].w = s->hw->x_range->min;
+
+ if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max)
+ s->val[OPT_TL_Y].w = s->hw->y_range->min;
+
+ if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max)
+ s->val[OPT_BR_X].w = s->hw->x_range->max;
+
+ if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max)
+ s->val[OPT_BR_Y].w = s->hw->y_range->max;
+}
+
+static SANE_Status
+getvalue(SANE_Handle handle, SANE_Int option, void *value)
+{
+ epsonds_scanner *s = (epsonds_scanner *)handle;
+ SANE_Option_Descriptor *sopt = &(s->opt[option]);
+ Option_Value *sval = &(s->val[option]);
+
+ DBG(17, "%s: option = %d\n", __func__, option);
+
+ switch (option) {
+
+ case OPT_NUM_OPTS:
+ case OPT_RESOLUTION:
+ case OPT_TL_X:
+ case OPT_TL_Y:
+ case OPT_BR_X:
+ case OPT_BR_Y:
+ case OPT_DEPTH:
+ case OPT_ADF_SKEW:
+ *((SANE_Word *) value) = sval->w;
+ break;
+
+ case OPT_MODE:
+ case OPT_ADF_MODE:
+ case OPT_SOURCE:
+ strcpy((char *) value, sopt->constraint.string_list[sval->w]);
+ break;
+
+ default:
+ return SANE_STATUS_INVAL;
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
+{
+ epsonds_scanner *s = (epsonds_scanner *) handle;
+ SANE_Option_Descriptor *sopt = &(s->opt[option]);
+ Option_Value *sval = &(s->val[option]);
+
+ SANE_Status status;
+ const SANE_String_Const *optval = NULL;
+ int optindex = 0;
+ SANE_Bool reload = SANE_FALSE;
+
+ DBG(17, "** %s: option = %d, value = %p\n", __func__, option, value);
+
+ status = sanei_constrain_value(sopt, value, info);
+ if (status != SANE_STATUS_GOOD)
+ return status;
+
+ if (info && value && (*info & SANE_INFO_INEXACT)
+ && sopt->type == SANE_TYPE_INT)
+ DBG(17, " constrained val = %d\n", *(SANE_Word *) value);
+
+ if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) {
+ optval = search_string_list(sopt->constraint.string_list,
+ (char *) value);
+ if (optval == NULL)
+ return SANE_STATUS_INVAL;
+ optindex = optval - sopt->constraint.string_list;
+ }
+
+ /* block faulty frontends */
+ if (sopt->cap & SANE_CAP_INACTIVE) {
+ DBG(1, " tried to modify a disabled parameter");
+ return SANE_STATUS_INVAL;
+ }
+
+ switch (option) {
+
+ case OPT_ADF_MODE: /* simple lists */
+ sval->w = optindex;
+ break;
+
+ case OPT_ADF_SKEW:
+ case OPT_RESOLUTION:
+ sval->w = *((SANE_Word *) value);
+ reload = SANE_TRUE;
+ break;
+
+ case OPT_BR_X:
+ case OPT_BR_Y:
+ sval->w = *((SANE_Word *) value);
+ if (SANE_UNFIX(sval->w) == 0) {
+ DBG(17, " invalid br-x or br-y\n");
+ return SANE_STATUS_INVAL;
+ }
+ /* passthru */
+ case OPT_TL_X:
+ case OPT_TL_Y:
+ sval->w = *((SANE_Word *) value);
+ if (NULL != info)
+ *info |= SANE_INFO_RELOAD_PARAMS;
+ break;
+
+ case OPT_SOURCE:
+ change_source(s, optindex, (char *) value);
+ reload = SANE_TRUE;
+ break;
+
+ case OPT_MODE:
+ {
+ /* use JPEG mode if RAW is not available when bpp > 1 */
+ if (optindex > 0 && !s->hw->has_raw) {
+ s->mode_jpeg = 1;
+ } else {
+ s->mode_jpeg = 0;
+ }
+
+ sval->w = optindex;
+
+ /* if binary, then disable the bit depth selection */
+ if (optindex == 0) {
+ s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE;
+ } else {
+ if (s->hw->depth_list[0] == 1)
+ s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE;
+ else {
+ s->opt[OPT_DEPTH].cap &= ~SANE_CAP_INACTIVE;
+ s->val[OPT_DEPTH].w =
+ mode_params[optindex].depth;
+ }
+ }
+
+ reload = SANE_TRUE;
+ break;
+ }
+
+ case OPT_DEPTH:
+ sval->w = *((SANE_Word *) value);
+ mode_params[s->val[OPT_MODE].w].depth = sval->w;
+ reload = SANE_TRUE;
+ break;
+
+ case OPT_LOAD:
+ esci2_mech(s, "#ADFLOAD");
+ break;
+
+ case OPT_EJECT:
+ esci2_mech(s, "#ADFEJCT");
+ break;
+
+ default:
+ return SANE_STATUS_INVAL;
+ }
+
+ if (reload && info != NULL)
+ *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
+
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status
+sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action,
+ void *value, SANE_Int *info)
+{
+ DBG(17, "** %s: action = %x, option = %d\n", __func__, action, option);
+
+ if (option < 0 || option >= NUM_OPTIONS)
+ return SANE_STATUS_INVAL;
+
+ if (info != NULL)
+ *info = 0;
+
+ switch (action) {
+ case SANE_ACTION_GET_VALUE:
+ return getvalue(handle, option, value);
+
+ case SANE_ACTION_SET_VALUE:
+ return setvalue(handle, option, value, info);
+
+ default:
+ return SANE_STATUS_INVAL;
+ }
+
+ return SANE_STATUS_INVAL;
+}
+
+SANE_Status
+sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
+{
+ epsonds_scanner *s = (epsonds_scanner *)handle;
+
+ DBG(5, "** %s\n", __func__);
+
+ if (params == NULL)
+ DBG(1, "%s: params is NULL\n", __func__);
+
+ /*
+ * If sane_start was already called, then just retrieve the parameters
+ * from the scanner data structure
+ */
+ if (s->scanning) {
+ DBG(5, "scan in progress, returning saved params structure\n");
+ } else {
+ /* otherwise initialize the params structure */
+ eds_init_parameters(s);
+ }
+
+ if (params != NULL)
+ *params = s->params;
+
+ print_params(s->params);
+
+ return SANE_STATUS_GOOD;
+}
+
+/*
+ * This function is part of the SANE API and gets called from the front end to
+ * start the scan process.
+ */
+
+SANE_Status
+sane_start(SANE_Handle handle)
+{
+ epsonds_scanner *s = (epsonds_scanner *)handle;
+ char buf[64];
+ SANE_Status status = 0;
+
+ s->pages++;
+
+ DBG(5, "** %s, pages = %d, scanning = %d, backside = %d, front fill: %d, back fill: %d\n",
+ __func__, s->pages, s->scanning, s->backside,
+ eds_ring_avail(&s->front),
+ eds_ring_avail(&s->back));
+
+ s->eof = 0;
+ s->canceling = 0;
+
+ if ((s->pages % 2) == 1) {
+ s->current = &s->front;
+ eds_ring_flush(s->current);
+ } else if (eds_ring_avail(&s->back)) {
+ DBG(5, "back side\n");
+ s->current = &s->back;
+ }
+
+ /* prepare the JPEG decompressor */
+ if (s->mode_jpeg) {
+ status = eds_jpeg_start(s);
+ if (status != SANE_STATUS_GOOD) {
+ goto end;
+ } }
+
+ /* scan already in progress? (one pass adf) */
+ if (s->scanning) {
+ DBG(5, " scan in progress, returning early\n");
+ return SANE_STATUS_GOOD;
+ }
+
+ /* calc scanning parameters */
+ status = eds_init_parameters(s);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, " parameters initialization failed\n");
+ return status;
+ }
+
+ /* allocate line buffer */
+ s->line_buffer = realloc(s->line_buffer, s->params.bytes_per_line);
+ if (s->line_buffer == NULL)
+ return SANE_STATUS_NO_MEM;
+
+ /* ring buffer for front page, twice bsz */
+ /* XXX read value from scanner */
+ status = eds_ring_init(&s->front, (65536 * 4) * 2);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ /* transfer buffer, bsz */
+ /* XXX read value from scanner */
+ s->buf = realloc(s->buf, 65536 * 4);
+ if (s->buf == NULL)
+ return SANE_STATUS_NO_MEM;
+
+ print_params(s->params);
+
+ /* set scanning parameters */
+
+ char cmd[100]; /* take care not to overflow */
+
+ /* document source */
+ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) {
+
+ sprintf(buf, "#ADF%s%s",
+ s->val[OPT_ADF_MODE].w ? "DPLX" : "",
+ s->val[OPT_ADF_SKEW].w ? "SKEW" : "");
+
+ } else if (strcmp(source_list[s->val[OPT_SOURCE].w], FBF_STR) == 0) {
+
+ strcpy(buf, "#FB ");
+
+ } else {
+ /* XXX */
+ }
+
+ strcpy(cmd, buf);
+
+ if (s->params.format == SANE_FRAME_GRAY) {
+ sprintf(buf, "#COLM%03d", s->params.depth);
+ } else if (s->params.format == SANE_FRAME_RGB) {
+ sprintf(buf, "#COLC%03d", s->params.depth * 3);
+ }
+
+ strcat(cmd, buf);
+
+ /* image transfer format */
+ if (!s->mode_jpeg) {
+ if (s->params.depth > 1 || s->hw->has_raw) {
+ strcat(cmd, "#FMTRAW ");
+ }
+ } else {
+ strcat(cmd, "#FMTJPG #JPGd090");
+ }
+
+ /* resolution (RSMi not always supported) */
+
+ if (s->val[OPT_RESOLUTION].w > 999) {
+ sprintf(buf, "#RSMi%07d", s->val[OPT_RESOLUTION].w);
+ } else {
+ sprintf(buf, "#RSMd%03d", s->val[OPT_RESOLUTION].w);
+ }
+
+ strcat(cmd, buf);
+
+ /* scanning area */
+ sprintf(buf, "#ACQi%07di%07di%07di%07d",
+ s->left, s->top, s->params.pixels_per_line, s->params.lines);
+
+ strcat(cmd, buf);
+
+ status = esci2_para(s, cmd);
+ if (status != SANE_STATUS_GOOD) {
+ goto end;
+ }
+
+ /* start scanning */
+ DBG(1, "%s: scanning...\n", __func__);
+
+ /* switch to data state */
+ status = esci2_trdt(s);
+ if (status != SANE_STATUS_GOOD) {
+ goto end;
+ }
+
+ /* first page is page 1 */
+ s->pages = 1;
+ s->scanning = 1;
+
+end:
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: start failed: %s\n", __func__, sane_strstatus(status));
+ }
+
+ return status;
+}
+
+/* this moves data from our buffers to SANE */
+
+SANE_Status
+sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
+ SANE_Int *length)
+{
+ SANE_Int read = 0, tries = 3;
+ SANE_Status status = 0;
+ epsonds_scanner *s = (epsonds_scanner *)handle;
+
+ *length = read = 0;
+
+ DBG(20, "** %s: backside = %d\n", __func__, s->backside);
+
+ /* sane_read called before sane_start? */
+ if (s->current == NULL) {
+ DBG(0, "%s: buffer is NULL", __func__);
+ return SANE_STATUS_INVAL;
+ }
+
+ /* anything in the buffer? pass it to the frontend */
+ SANE_Int available = eds_ring_avail(s->current);
+ if (available) {
+
+ DBG(18, "reading from ring buffer, %d left\n", available);
+
+ if (s->mode_jpeg && !s->jpeg_header_seen) {
+
+ status = eds_jpeg_read_header(s);
+ if (status != SANE_STATUS_GOOD && --tries) {
+ goto read_again;
+ }
+ }
+
+ if (s->mode_jpeg) {
+ eds_jpeg_read(handle, data, max_length, &read);
+ } else {
+ eds_copy_image_from_ring(s, data, max_length, &read);
+ }
+
+ if (read == 0) {
+ goto read_again;
+ }
+
+ *length = read;
+
+ return SANE_STATUS_GOOD;
+
+
+ } else if (s->current == &s->back) {
+
+ /* finished reading the back page, next
+ * command should give us the EOF
+ */
+ DBG(18, "back side ring buffer empty\n");
+ }
+
+ /* read until data or error */
+
+read_again:
+
+ status = esci2_img(s, &read);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(20, "read: %d, eof: %d, backside: %d, status: %d\n", read, s->eof, s->backside, status);
+ }
+
+ /* just got a back side page, alloc ring buffer if necessary
+ * we didn't before because dummy was not known
+ */
+ if (s->backside) {
+
+ int required = s->params.lines * (s->params.bytes_per_line + s->dummy);
+
+ if (s->back.size < required) {
+
+ DBG(20, "allocating buffer for the back side\n");
+
+ status = eds_ring_init(&s->back, required);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+ }
+ }
+
+ /* abort scanning when appropriate */
+ if (status == SANE_STATUS_CANCELLED) {
+ esci2_can(s);
+ return status;
+ }
+
+ if (s->eof && s->backside) {
+ DBG(18, "back side scan finished\n");
+ }
+
+ /* read again if no error and no data */
+ if (read == 0 && status == SANE_STATUS_GOOD) {
+ goto read_again;
+ }
+
+ /* got something, write to ring */
+ if (read) {
+
+ DBG(20, " %d bytes read, %d lines, eof: %d, canceling: %d, status: %d, backside: %d\n",
+ read, read / (s->params.bytes_per_line + s->dummy),
+ s->canceling, s->eof, status, s->backside);
+
+ /* move data to the appropriate ring */
+ status = eds_ring_write(s->backside ? &s->back : &s->front, s->buf, read);
+
+ if (0 && s->mode_jpeg && !s->jpeg_header_seen
+ && status == SANE_STATUS_GOOD) {
+
+ status = eds_jpeg_read_header(s);
+ if (status != SANE_STATUS_GOOD && --tries) {
+ goto read_again;
+ }
+ }
+ }
+
+ /* continue reading if appropriate */
+ if (status == SANE_STATUS_GOOD)
+ return status;
+
+ /* cleanup */
+ DBG(5, "** %s: cleaning up\n", __func__);
+
+ if (s->mode_jpeg) {
+ eds_jpeg_finish(s);
+ }
+
+ eds_ring_flush(s->current);
+
+ return status;
+}
+
+/*
+ * void sane_cancel(SANE_Handle handle)
+ *
+ * Set the cancel flag to true. The next time the backend requests data
+ * from the scanner the CAN message will be sent.
+ */
+
+void
+sane_cancel(SANE_Handle handle)
+{
+ DBG(1, "** %s\n", __func__);
+ ((epsonds_scanner *)handle)->canceling = SANE_TRUE;
+}
+
+/*
+ * SANE_Status sane_set_io_mode()
+ *
+ * not supported - for asynchronous I/O
+ */
+
+SANE_Status
+sane_set_io_mode(SANE_Handle __sane_unused__ handle,
+ SANE_Bool __sane_unused__ non_blocking)
+{
+ return SANE_STATUS_UNSUPPORTED;
+}
+
+/*
+ * SANE_Status sane_get_select_fd()
+ *
+ * not supported - for asynchronous I/O
+ */
+
+SANE_Status
+sane_get_select_fd(SANE_Handle __sane_unused__ handle,
+ SANE_Int __sane_unused__ *fd)
+{
+ return SANE_STATUS_UNSUPPORTED;
+}
diff --git a/backend/epsonds.conf.in b/backend/epsonds.conf.in
new file mode 100644
index 0000000..bd032f3
--- /dev/null
+++ b/backend/epsonds.conf.in
@@ -0,0 +1,12 @@
+# epsonds.conf
+#
+# here are some examples for how to configure the epsonds backend
+
+# USB
+usb
+
+# For libusb support for unknown scanners use the following command
+# usb <product ID> <device ID>
+# e.g.:
+# usb 0x4b8 0x14c
+
diff --git a/backend/epsonds.h b/backend/epsonds.h
new file mode 100644
index 0000000..2c2e422
--- /dev/null
+++ b/backend/epsonds.h
@@ -0,0 +1,198 @@
+/*
+ * epsonds.c - Epson ESC/I-2 driver.
+ *
+ * Copyright (C) 2015 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is part of the SANE package.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#ifndef epsonds_h
+#define epsonds_h
+
+#undef BACKEND_NAME
+#define BACKEND_NAME epsonds
+#define DEBUG_NOT_STATIC
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h> /* for memset and memcpy */
+#include <stdio.h>
+
+#include "sane/sane.h"
+#include "sane/sanei_backend.h"
+#include "sane/sanei_debug.h"
+#include "sane/sanei_usb.h"
+#include "sane/sanei_jpeg.h"
+
+#ifdef __GNUC__
+#define __func__ __FUNCTION__
+#else
+#define __func__ "(undef)"
+/* I cast my vote for C99... :) */
+#endif
+
+#define EPSONDS_CONFIG_FILE "epsonds.conf"
+
+#ifndef PATH_MAX
+#define PATH_MAX (1024)
+#endif
+
+#ifndef XtNumber
+#define XtNumber(x) (sizeof(x) / sizeof(x[0]))
+#define XtOffset(p_type, field) ((size_t)&(((p_type)NULL)->field))
+#define XtOffsetOf(s_type, field) XtOffset(s_type*, field)
+#endif
+
+#define ACK 0x06
+#define NAK 0x15
+#define FS 0x1C
+
+#define FBF_STR SANE_I18N("Flatbed")
+#define TPU_STR SANE_I18N("Transparency Unit")
+#define ADF_STR SANE_I18N("Automatic Document Feeder")
+
+enum {
+ OPT_NUM_OPTS = 0,
+ OPT_MODE_GROUP,
+ OPT_MODE,
+ OPT_DEPTH,
+ OPT_RESOLUTION,
+ OPT_GEOMETRY_GROUP,
+ OPT_TL_X,
+ OPT_TL_Y,
+ OPT_BR_X,
+ OPT_BR_Y,
+ OPT_EQU_GROUP,
+ OPT_SOURCE,
+ OPT_EJECT,
+ OPT_LOAD,
+ OPT_ADF_MODE,
+ OPT_ADF_SKEW,
+ NUM_OPTIONS
+};
+
+typedef enum
+{ /* hardware connection to the scanner */
+ SANE_EPSONDS_NODEV, /* default, no HW specified yet */
+ SANE_EPSONDS_USB, /* USB interface */
+ SANE_EPSONDS_NET /* network interface (unsupported)*/
+} epsonds_conn_type;
+
+/* hardware description */
+
+struct epsonds_device
+{
+ struct epsonds_device *next;
+
+ epsonds_conn_type connection;
+
+ char *name;
+ char *model;
+
+ unsigned int model_id;
+
+ SANE_Device sane;
+ SANE_Range *x_range;
+ SANE_Range *y_range;
+ SANE_Range dpi_range;
+ SANE_Byte alignment;
+
+
+ SANE_Int *res_list; /* list of resolutions */
+ SANE_Int *depth_list;
+ SANE_Int max_depth; /* max. color depth */
+
+ SANE_Bool has_raw; /* supports RAW format */
+
+ SANE_Bool has_fb; /* flatbed */
+ SANE_Range fbf_x_range; /* x range */
+ SANE_Range fbf_y_range; /* y range */
+ SANE_Byte fbf_alignment; /* left, center, right */
+ SANE_Bool fbf_has_skew; /* supports skew correction */
+
+ SANE_Bool has_adf; /* adf */
+ SANE_Range adf_x_range; /* x range */
+ SANE_Range adf_y_range; /* y range */
+ SANE_Bool adf_is_duplex; /* supports duplex mode */
+ SANE_Bool adf_singlepass; /* supports single pass duplex */
+ SANE_Bool adf_has_skew; /* supports skew correction */
+ SANE_Bool adf_has_load; /* supports load command */
+ SANE_Bool adf_has_eject; /* supports eject command */
+ SANE_Byte adf_alignment; /* left, center, right */
+
+ SANE_Bool has_tpu; /* tpu */
+ SANE_Range tpu_x_range; /* transparency unit x range */
+ SANE_Range tpu_y_range; /* transparency unit y range */
+};
+
+typedef struct epsonds_device epsonds_device;
+
+typedef struct ring_buffer
+{
+ SANE_Byte *ring, *wp, *rp, *end;
+ SANE_Int fill, size;
+
+} ring_buffer;
+
+/* an instance of a scanner */
+
+struct epsonds_scanner
+{
+ struct epsonds_scanner *next;
+ struct epsonds_device *hw;
+
+ int fd;
+
+ SANE_Option_Descriptor opt[NUM_OPTIONS];
+ Option_Value val[NUM_OPTIONS];
+ SANE_Parameters params;
+
+ SANE_Byte *buf, *line_buffer;
+ ring_buffer *current, front, back;
+
+ SANE_Bool eof, scanning, canceling, locked, backside, mode_jpeg;
+
+ SANE_Int left, top, pages, dummy;
+
+ /* jpeg stuff */
+
+ djpeg_dest_ptr jdst;
+ struct jpeg_decompress_struct jpeg_cinfo;
+ struct jpeg_error_mgr jpeg_err;
+ SANE_Bool jpeg_header_seen;
+};
+
+typedef struct epsonds_scanner epsonds_scanner;
+
+struct mode_param
+{
+ int color;
+ int flags;
+ int dropout_mask;
+ int depth;
+};
+
+enum {
+ MODE_BINARY, MODE_GRAY, MODE_COLOR
+};
+
+#endif
diff --git a/backend/genesys.c b/backend/genesys.c
index 913a048..548d0da 100644
--- a/backend/genesys.c
+++ b/backend/genesys.c
@@ -58,7 +58,7 @@
* SANE backend for Genesys Logic GL646/GL841/GL842/GL843/GL846/GL847/GL124 based scanners
*/
-#define BUILD 2504
+#define BUILD 2506
#define BACKEND_NAME genesys
#include "genesys.h"
@@ -157,6 +157,15 @@ static const SANE_Range enhance_range = {
1 /* quantization */
};
+/**
+ * range for expiration time
+ */
+static const SANE_Range expiration_range = {
+ -1, /* minimum */
+ 30000, /* maximum */
+ 1 /* quantization */
+};
+
void
sanei_genesys_init_structs (Genesys_Device * dev)
{
@@ -3044,11 +3053,15 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
case CIS_CANONLIDE100:
case CIS_CANONLIDE200:
case CIS_CANONLIDE110:
+ case CIS_CANONLIDE120:
case CIS_CANONLIDE210:
+ case CIS_CANONLIDE220:
/* TODO store this in a data struct so we avoid
* growing this switch */
if(dev->model->ccd_type!=CIS_CANONLIDE110
- && dev->model->ccd_type!=CIS_CANONLIDE210)
+ && dev->model->ccd_type!=CIS_CANONLIDE210
+ && dev->model->ccd_type!=CIS_CANONLIDE120
+ && dev->model->ccd_type!=CIS_CANONLIDE220)
target_code=0xdc00;
else
target_code=0xf000;
@@ -5307,6 +5320,9 @@ calc_parameters (Genesys_Scanner * s)
s->dev->settings.brightness=0;
}
+ /* cache expiration time */
+ s->dev->settings.expiration_time=s->val[OPT_EXPIRATION_TIME].w;
+
return status;
}
@@ -5895,6 +5911,17 @@ init_options (Genesys_Scanner * s)
}
#endif
+ /* expiration time for calibration cache entries */
+ s->opt[OPT_EXPIRATION_TIME].name = "expiration-time";
+ s->opt[OPT_EXPIRATION_TIME].title = SANE_I18N ("Calibration cache expiration time");
+ s->opt[OPT_EXPIRATION_TIME].desc = SANE_I18N ("Time (in minutes) before a cached calibration expires."
+ "A value of 0 means cache is not used used. A negative value means cache never expires.");
+ s->opt[OPT_EXPIRATION_TIME].type = SANE_TYPE_INT;
+ s->opt[OPT_EXPIRATION_TIME].unit = SANE_UNIT_NONE;
+ s->opt[OPT_EXPIRATION_TIME].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_EXPIRATION_TIME].constraint.range = &expiration_range;
+ s->val[OPT_EXPIRATION_TIME].w = 60; /* 60 minutes by default */
+
/* Powersave time (turn lamp off) */
s->opt[OPT_LAMP_OFF_TIME].name = "lamp-off-time";
s->opt[OPT_LAMP_OFF_TIME].title = SANE_I18N ("Lamp off time");
@@ -6915,8 +6942,8 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
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);
+ DBG (DBG_info, "%s: Calibration filename set to:\n", __FUNCTION__);
+ DBG (DBG_info, "%s: >%s<\n", __FUNCTION__, s->dev->calib_file);
free(tmpstr);
/* now open file, fetch calibration records */
@@ -7193,37 +7220,35 @@ static SANE_Status set_calibration_value (Genesys_Scanner * s, int option, void
{
SANE_Status status=SANE_STATUS_GOOD;
char *tmp;
- Genesys_Calibration_Cache *cache;
Genesys_Device *dev=s->dev;
+ DBGSTART;
+
/* try to load file */
tmp=dev->calib_file;
dev->calib_file=val;
status=sanei_genesys_read_calibration (dev);
- /* file exists but is invalid */
+ /* file exists but is invalid, so fall back to previous cache file
+ * an re-read it */
if (status!=SANE_STATUS_IO_ERROR && status!=SANE_STATUS_GOOD)
{
dev->calib_file=tmp;
+ status=sanei_genesys_read_calibration (dev);
return status;
}
- /* we can set no file name value */
+ /* now we can set file name value */
if (s->val[option].s)
free (s->val[option].s);
s->val[option].s = strdup (val);
if (tmp)
free (tmp);
dev->calib_file = strdup (val);
+ DBG (DBG_info, "%s: Calibration filename set to:\n", __FUNCTION__);
+ DBG (DBG_info, "%s: >%s<\n", __FUNCTION__, s->dev->calib_file);
- /* clear device calibration cache */
- while(dev->calibration_cache!=NULL)
- {
- cache=dev->calibration_cache;
- dev->calibration_cache=dev->calibration_cache->next;
- free(cache);
- }
-
+ DBGCOMPLETED;
return SANE_STATUS_GOOD;
}
@@ -7418,6 +7443,7 @@ set_option_value (Genesys_Scanner * s, int option, void *val,
RIE(set_calibration_value (s, option, val));
break;
case OPT_LAMP_OFF_TIME:
+ case OPT_EXPIRATION_TIME:
if (*(SANE_Word *) val != s->val[option].w)
{
s->val[option].w = *(SANE_Word *) val;
diff --git a/backend/genesys.conf.in b/backend/genesys.conf.in
index 5300787..7899455 100644
--- a/backend/genesys.conf.in
+++ b/backend/genesys.conf.in
@@ -60,6 +60,12 @@ usb 0x04a9 0x1907
# Canon LiDE 210
usb 0x04a9 0x190a
+# Canon LiDE 120
+usb 0x04a9 0x190e
+
+# Canon LiDE 220
+usb 0x04a9 0x190f
+
# Canon 5600f
usb 0x04a9 0x1906
diff --git a/backend/genesys.h b/backend/genesys.h
index fea3f3b..eab92bb 100644
--- a/backend/genesys.h
+++ b/backend/genesys.h
@@ -120,6 +120,7 @@ enum Genesys_Option
OPT_DISABLE_INTERPOLATION,
OPT_COLOR_FILTER,
OPT_CALIBRATION_FILE,
+ OPT_EXPIRATION_TIME,
OPT_SENSOR_GROUP,
OPT_SCAN_SW,
diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c
index 213b9c9..4358e94 100644
--- a/backend/genesys_devices.c
+++ b/backend/genesys_devices.c
@@ -660,6 +660,30 @@ static Genesys_Sensor Sensor[] = {
{2.1, 2.1, 2.1},
{NULL, NULL, NULL}}
,
+
+ /* CANONLIDE120 */
+ {CIS_CANONLIDE120,
+ 2400, /* optical resolution */
+ 87, /* black pixels */
+ 16, /* dummy pixels 16 */
+ 303, /* 303 */
+ 5168*4, /* total pixels */
+ 210,
+ 200,
+ {0x00, 0x00, 0x00, 0x00},
+ /* reg 0x10 - 0x15 : EXPR, EXPG and EXPB */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* reg 0x16 - 0x1d */
+ 0x10, 0x04, 0x00, 0x01, 0x30, 0x00, 0x02, 0x01 },
+ /* reg 0x52 - 0x5e */
+ {
+ 0x00, 0x02, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04,
+ 0x1a, 0x00, 0xc0, 0x00, 0x00
+ }
+ ,
+ {2.1, 2.1, 2.1},
+ {NULL, NULL, NULL}}
+ ,
/* CANON LIDE 210 sensor */
{CIS_CANONLIDE210,
2400, /* optical resolution */
@@ -683,6 +707,29 @@ static Genesys_Sensor Sensor[] = {
{2.1, 2.1, 2.1},
{NULL, NULL, NULL}}
,
+ /* CANON LIDE 220 sensor */
+ {CIS_CANONLIDE220,
+ 2400, /* optical resolution */
+ 87, /* black pixels */
+ 16, /* dummy pixels 16 */
+ 303, /* 303 */
+ 5168*4, /* total pixels */
+ 210,
+ 200,
+ {0x00, 0x00, 0x00, 0x00},
+ /* reg 0x10 - 0x15 : EXPR, EXPG and EXPB */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* reg 0x16 - 0x1d */
+ 0x10, 0x04, 0x00, 0x01, 0x30, 0x00, 0x02, 0x01 },
+ /* reg 0x52 - 0x5e */
+ {
+ 0x00, 0x02, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04,
+ 0x1a, 0x00, 0xc0, 0x00, 0x00
+ }
+ ,
+ {2.1, 2.1, 2.1},
+ {NULL, NULL, NULL}}
+ ,
{CCD_PLUSTEK_3600,
1200,
87, /*(black) */
@@ -1854,6 +1901,59 @@ static Genesys_Model canon_lide_110_model = {
400
};
+static Genesys_Model canon_lide_120_model = {
+ "canon-lide-120", /* Name */
+ "Canon", /* Device vendor string */
+ "LiDE 120", /* Device model name */
+ GENESYS_GL124,
+ NULL,
+
+ {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */
+ {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */
+ {16, 8, 0}, /* possible depths in gray mode */
+ {16, 8, 0}, /* possible depths in color mode */
+
+ SANE_FIX (2.2), /* Start of scan area in mm (x) */
+ SANE_FIX (9.0), /* Start of scan area in mm (y) */
+ SANE_FIX (216.70), /* Size of scan area in mm (x) */
+ SANE_FIX (300.0), /* Size of scan area in mm (y) */
+
+ SANE_FIX (1.0), /* Start of white strip in mm (y) */
+ SANE_FIX (0.0), /* Start of black mark in mm (x) */
+
+ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */
+ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */
+ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */
+ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */
+
+ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */
+
+ SANE_FIX (0.0), /* Size of scan area after paper sensor stops
+ sensing document in mm */
+ SANE_FIX (0.0), /* Amount of feeding needed to eject document
+ after finishing scanning in mm */
+
+ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */
+
+ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */
+
+ SANE_TRUE, /* Is this a CIS scanner? */
+ SANE_FALSE, /* Is this a sheetfed scanner? */
+ CIS_CANONLIDE120,
+ DAC_CANONLIDE110,
+ GPO_CANONLIDE110,
+ MOTOR_CANONLIDE110,
+ GENESYS_FLAG_SKIP_WARMUP
+ | GENESYS_FLAG_OFFSET_CALIBRATION
+ | GENESYS_FLAG_DARK_CALIBRATION
+ | GENESYS_FLAG_HALF_CCD_MODE
+ | GENESYS_FLAG_SHADING_REPARK
+ | GENESYS_FLAG_CUSTOM_GAMMA,
+ GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW,
+ 50,
+ 400
+};
+
static Genesys_Model canon_lide_210_model = {
"canon-lide-210", /* Name */
@@ -1908,6 +2008,59 @@ static Genesys_Model canon_lide_210_model = {
400
};
+static Genesys_Model canon_lide_220_model = {
+ "canon-lide-220", /* Name */
+ "Canon", /* Device vendor string */
+ "LiDE 220", /* Device model name */
+ GENESYS_GL124, /* or a compatible one */
+ NULL,
+
+ {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */
+ {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */
+ {16, 8, 0}, /* possible depths in gray mode */
+ {16, 8, 0}, /* possible depths in color mode */
+
+ SANE_FIX (2.2), /* Start of scan area in mm (x) */
+ SANE_FIX (8.7), /* Start of scan area in mm (y) */
+ SANE_FIX (216.70), /* Size of scan area in mm (x) */
+ SANE_FIX (297.5), /* Size of scan area in mm (y) */
+
+ SANE_FIX (0.0), /* Start of white strip in mm (y) */
+ SANE_FIX (0.0), /* Start of black mark in mm (x) */
+
+ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */
+ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */
+ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */
+ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */
+
+ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */
+
+ SANE_FIX (0.0), /* Size of scan area after paper sensor stops
+ sensing document in mm */
+ SANE_FIX (0.0), /* Amount of feeding needed to eject document
+ after finishing scanning in mm */
+
+ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */
+
+ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */
+
+ SANE_TRUE, /* Is this a CIS scanner? */
+ SANE_FALSE, /* Is this a sheetfed scanner? */
+ CIS_CANONLIDE220,
+ DAC_CANONLIDE110,
+ GPO_CANONLIDE210,
+ MOTOR_CANONLIDE210,
+ GENESYS_FLAG_SKIP_WARMUP
+ | GENESYS_FLAG_OFFSET_CALIBRATION
+ | GENESYS_FLAG_DARK_CALIBRATION
+ | GENESYS_FLAG_HALF_CCD_MODE
+ | GENESYS_FLAG_SHADING_REPARK
+ | GENESYS_FLAG_CUSTOM_GAMMA,
+ GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_EXTRA_SW,
+ 60,
+ 400
+};
+
static Genesys_Model canon_5600f_model = {
"canon-5600f", /* Name */
"Canon", /* Device vendor string */
@@ -3507,7 +3660,9 @@ static Genesys_USB_Device_Entry genesys_usb_device_list[] = {
{0x03f0, 0x4705, &hpn6310_model},
/* GL124 devices */
{0x04a9, 0x1909, &canon_lide_110_model},
+ {0x04a9, 0x190e, &canon_lide_120_model},
{0x04a9, 0x190a, &canon_lide_210_model},
+ {0x04a9, 0x190f, &canon_lide_220_model},
{0, 0, NULL}
};
diff --git a/backend/genesys_gl124.c b/backend/genesys_gl124.c
index 86aa4ee..eaac873 100644
--- a/backend/genesys_gl124.c
+++ b/backend/genesys_gl124.c
@@ -852,7 +852,7 @@ gl124_init_motor_regs_scan (Genesys_Device * dev,
}
else
{
- min_speed = 600;
+ min_speed = 900;
if(dev->model->ccd_type==MOTOR_CANONLIDE110)
{
min_speed = 300;
@@ -2108,6 +2108,17 @@ gl124_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
return SANE_STATUS_GOOD;
}
+ /* feed a little first */
+ if (strcmp (dev->model->name, "canon-lide-210") == 0)
+ {
+ status = gl124_feed (dev, 20, SANE_TRUE);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (DBG_error, "%s: failed to do initial feed: %s\n", __FUNCTION__, sane_strstatus (status));
+ return status;
+ }
+ }
+
memcpy (local_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set));
resolution=sanei_genesys_get_lowest_dpi(dev);
@@ -2202,12 +2213,13 @@ gl124_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
/** @brief moves the slider to steps at motor base dpi
* @param dev device to work on
* @param steps number of steps to move
+ * @param reverse true is moving backward
* */
#ifndef UNIT_TESTING
static
#endif
SANE_Status
-gl124_feed (Genesys_Device * dev, unsigned int steps)
+gl124_feed (Genesys_Device * dev, unsigned int steps, int reverse)
{
Genesys_Register_Set local_reg[GENESYS_GL124_MAX_REGS];
SANE_Status status;
@@ -2242,9 +2254,7 @@ gl124_feed (Genesys_Device * dev, unsigned int steps)
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));
+ DBG (DBG_error, "%s: failed to set up registers: %s\n", __FUNCTION__, sane_strstatus (status));
DBGCOMPLETED;
return status;
}
@@ -2262,6 +2272,13 @@ gl124_feed (Genesys_Device * dev, unsigned int steps)
r = sanei_genesys_get_address (local_reg, REG01);
r->value &= ~REG01_SCAN;
+ /* set up for reverse if needed */
+ if(reverse)
+ {
+ r = sanei_genesys_get_address (local_reg, REG02);
+ r->value |= REG02_MTRREV;
+ }
+
/* send registers */
RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL124_MAX_REGS));
@@ -2653,7 +2670,7 @@ gl124_init_regs_for_scan (Genesys_Device * dev)
if(channels*dev->settings.yres>=600 && move>700)
{
- status = gl124_feed (dev, move-500);
+ status = gl124_feed (dev, move-500, SANE_FALSE);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "%s: failed to move to scan area\n",__FUNCTION__);
@@ -3511,12 +3528,13 @@ gl124_init_gpio (Genesys_Device * dev)
DBGSTART;
/* per model GPIO layout */
- if (strcmp (dev->model->name, "canon-lide-110") == 0)
+ if ((strcmp (dev->model->name, "canon-lide-110") == 0)
+ ||(strcmp (dev->model->name, "canon-lide-120") == 0))
{
idx = 0;
}
else
- { /* canon LiDE 210 case */
+ { /* canon LiDE 210 and 220 case */
idx = 1;
}
@@ -3544,12 +3562,13 @@ gl124_init_memory_layout (Genesys_Device * dev)
DBGSTART;
/* point to per model memory layout */
- if (strcmp (dev->model->name, "canon-lide-110") == 0)
+ if ((strcmp (dev->model->name, "canon-lide-110") == 0)
+ ||(strcmp (dev->model->name, "canon-lide-120") == 0))
{
idx = 0;
}
else
- { /* canon LiDE 210 case */
+ { /* canon LiDE 210 and 220 case */
idx = 1;
}
diff --git a/backend/genesys_gl124.h b/backend/genesys_gl124.h
index 8b9998a..ae8016c 100644
--- a/backend/genesys_gl124.h
+++ b/backend/genesys_gl124.h
@@ -620,11 +620,23 @@ static Sensor_Profile sensors[]={
{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 120 */
+ {CIS_CANONLIDE120, 600, 1, 2768, 0x0f, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21},
+ {CIS_CANONLIDE120, 600, 0, 5360, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21},
+ {CIS_CANONLIDE120, 1200, 0, 10528, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22},
+ {CIS_CANONLIDE120, 2400, 0, 20864, 0x0f, 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},
{CIS_CANONLIDE210, 2400, 0, 20864, 0x1e, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24},
+
+ /* LiDE 220 */
+ {CIS_CANONLIDE220, 600, 1, 2768, 0x0f, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21},
+ {CIS_CANONLIDE220, 600, 0, 5360, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21},
+ {CIS_CANONLIDE220, 1200, 0, 10528, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22},
+ {CIS_CANONLIDE220, 2400, 0, 20864, 0x0f, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24},
};
@@ -704,7 +716,7 @@ SANE_Status gl124_send_shading_data (Genesys_Device * dev, uint8_t * data, int s
#ifndef UNIT_TESTING
static
#endif
-SANE_Status gl124_feed (Genesys_Device * dev, unsigned int steps);
+SANE_Status gl124_feed (Genesys_Device * dev, unsigned int steps, int reverse);
GENESYS_STATIC SANE_Status
gl124_stop_action (Genesys_Device * dev);
diff --git a/backend/genesys_low.c b/backend/genesys_low.c
index 63420e4..0af2149 100644
--- a/backend/genesys_low.c
+++ b/backend/genesys_low.c
@@ -1437,6 +1437,7 @@ sanei_genesys_wait_for_home (Genesys_Device * dev)
SANE_Status status;
uint8_t val;
int loop;
+ int max=300;
DBGSTART;
@@ -1492,7 +1493,14 @@ sanei_genesys_wait_for_home (Genesys_Device * dev)
}
++loop;
}
- while (loop < 300 && !(val & HOMESNR) && status == SANE_STATUS_GOOD);
+ while (loop < max && !(val & HOMESNR) && status == SANE_STATUS_GOOD);
+
+ /* if after the timeout, head is still not parked, error out */
+ if(loop >= max && !(val & HOMESNR) && status == SANE_STATUS_GOOD)
+ {
+ DBG (DBG_error, "%s: failed to reach park position %ds\n", __FUNCTION__, max/10);
+ return SANE_STATUS_IO_ERROR;
+ }
DBGCOMPLETED;
return status;
@@ -1755,7 +1763,11 @@ int sanei_genesys_get_lowest_dpi(Genesys_Device *dev)
/** @brief check is a cache entry may be used
* Compares current settings with the cache entry and return
* SANE_TRUE if they are compatible.
- */
+ * 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.
+ * flatbed cache entries are considred too old and then expires if they
+ * are older than the expiration time option, forcing calibration at least once
+ * then given time. */
SANE_Status
sanei_genesys_is_compatible_calibration (Genesys_Device * dev,
Genesys_Calibration_Cache * cache,
@@ -1771,22 +1783,20 @@ sanei_genesys_is_compatible_calibration (Genesys_Device * dev,
if(dev->model->cmd_set->calculate_current_setup==NULL)
{
- DBG (DBG_proc,
- "sanei_genesys_is_compatible_calibration: no calculate_setup, non compatible cache\n");
+ DBG (DBG_proc, "%s: no calculate_setup, non compatible cache\n", __FUNCTION__);
return SANE_STATUS_UNSUPPORTED;
}
status = dev->model->cmd_set->calculate_current_setup (dev);
if (status != SANE_STATUS_GOOD)
{
- DBG (DBG_error,
- "sanei_genesys_is_compatible_calibration: failed to calculate current setup: %s\n",
+ DBG (DBG_error, "%s: failed to calculate current setup: %s\n", __FUNCTION__,
sane_strstatus (status));
return status;
}
dev->current_setup.scan_method = dev->settings.scan_method;
- DBG (DBG_proc, "sanei_genesys_is_compatible_calibration: checking\n");
+ DBG (DBG_proc, "%s: checking\n", __FUNCTION__);
/* 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 */
@@ -1804,39 +1814,36 @@ sanei_genesys_is_compatible_calibration (Genesys_Device * dev,
resolution=sanei_genesys_compute_dpihw(dev,dev->settings.xres);
compatible = (resolution == ((int) sanei_genesys_compute_dpihw(dev,cache->used_setup.xres)));
}
+ DBG (DBG_io, "%s: after resolution check current compatible=%d\n", __FUNCTION__, compatible);
if (dev->current_setup.half_ccd != cache->used_setup.half_ccd)
{
- DBG (DBG_io,
- "sanei_genesys_is_compatible_calibration: half_ccd=%d, used=%d\n",
+ DBG (DBG_io, "%s: half_ccd=%d, used=%d\n", __FUNCTION__,
dev->current_setup.half_ccd, cache->used_setup.half_ccd);
compatible = 0;
}
if (dev->current_setup.scan_method != cache->used_setup.scan_method)
{
- DBG (DBG_io,
- "sanei_genesys_is_compatible_calibration: current method=%d, used=%d\n",
+ DBG (DBG_io, "%s: current method=%d, used=%d\n", __FUNCTION__,
dev->current_setup.scan_method, cache->used_setup.scan_method);
compatible = 0;
}
if (!compatible)
{
- DBG (DBG_proc,
- "sanei_genesys_is_compatible_calibration: completed, non compatible cache\n");
+ DBG (DBG_proc, "%s: completed, non compatible cache\n", __FUNCTION__);
return SANE_STATUS_UNSUPPORTED;
}
- /* a cache entry expires after 60 minutes for non sheetfed scanners */
+ /* a cache entry expires after afetr expiration time for non sheetfed scanners */
/* this is not taken into account when overwriting cache entries */
#ifdef HAVE_SYS_TIME_H
- if(for_overwrite == SANE_FALSE)
+ if(for_overwrite == SANE_FALSE && dev->settings.expiration_time >=0)
{
gettimeofday (&time, NULL);
- if ((time.tv_sec - cache->last_calibration > 60 * 60)
+ if ((time.tv_sec - cache->last_calibration > dev->settings.expiration_time*60)
&& (dev->model->is_sheetfed == SANE_FALSE)
&& (dev->settings.scan_method == SCAN_METHOD_FLATBED))
{
- DBG (DBG_proc,
- "sanei_genesys_is_compatible_calibration: expired entry, non compatible cache\n");
+ DBG (DBG_proc, "%s: expired entry, non compatible cache\n", __FUNCTION__);
return SANE_STATUS_UNSUPPORTED;
}
}
diff --git a/backend/genesys_low.h b/backend/genesys_low.h
index b1f29e1..b5a0a8f 100644
--- a/backend/genesys_low.h
+++ b/backend/genesys_low.h
@@ -382,6 +382,8 @@ Genesys_Color_Order;
#define CCD_PLUSTEK3800 26
#define CIS_CANONLIDE210 27
#define CIS_CANONLIDE80 28
+#define CIS_CANONLIDE220 29
+#define CIS_CANONLIDE120 30
#define GPO_UMAX 0
#define GPO_ST12 1
@@ -705,6 +707,9 @@ typedef struct
/**< value for brightness enhancement in the [-100..100] range */
int brightness;
+
+ /**< cahe entries expiration time */
+ int expiration_time;
} Genesys_Settings;
typedef struct Genesys_Current_Setup
diff --git a/backend/hp5590.c b/backend/hp5590.c
index 8db3d5e..7b1cd60 100644
--- a/backend/hp5590.c
+++ b/backend/hp5590.c
@@ -1239,6 +1239,14 @@ convert_to_rgb (struct hp5590_scanner *scanner, SANE_Byte *data, SANE_Int size)
buf[i*6+5] = ptr[2*i+bytes_per_color*2];
}
}
+
+ /* Invert pixels in case of TMA Negatives source has been selected */
+ if (scanner->source == SOURCE_TMA_NEGATIVES)
+ {
+ for (i = 0; i < bytes_per_line; i++)
+ buf[i] ^= 0xff;
+ }
+
memcpy (ptr, buf, bytes_per_line);
}
free (buf);
diff --git a/backend/pixma.c b/backend/pixma.c
index 4c7ec46..3396155 100644
--- a/backend/pixma.c
+++ b/backend/pixma.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
diff --git a/backend/pixma.h b/backend/pixma.h
index af38725..eedf74d 100644
--- a/backend/pixma.h
+++ b/backend/pixma.h
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -114,7 +114,7 @@ typedef uint32_t uint32_t;
/**@{*/
#define PIXMA_VERSION_MAJOR 0
#define PIXMA_VERSION_MINOR 17
-#define PIXMA_VERSION_BUILD 14
+#define PIXMA_VERSION_BUILD 17
/**@}*/
/** \name Error codes */
diff --git a/backend/pixma_common.c b/backend/pixma_common.c
index 771a5af..0945a69 100644
--- a/backend/pixma_common.c
+++ b/backend/pixma_common.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
diff --git a/backend/pixma_common.h b/backend/pixma_common.h
index 55ab570..069f8b8 100644
--- a/backend/pixma_common.h
+++ b/backend/pixma_common.h
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
This file is part of the SANE package.
diff --git a/backend/pixma_imageclass.c b/backend/pixma_imageclass.c
index b2526fa..3995805 100644
--- a/backend/pixma_imageclass.c
+++ b/backend/pixma_imageclass.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2009 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2008 Dennis Lou, dlou 99 at yahoo dot com
@@ -95,8 +95,13 @@
#define MF6680_PID 0x26fa
#define MF8030_PID 0x2707
#define IR1133_PID 0x2742
+#define MF5900_PID 0x2743
#define D530_PID 0x2775
#define MF8500_PID 0x277a
+#define MF6100_PID 0x278e
+#define MF820_PID 0x27a6
+#define MF220_PID 0x27a8
+#define MF210_PID 0x27a9
enum iclass_state_t
@@ -799,6 +804,11 @@ const pixma_config_t pixma_iclass_devices[] = {
DEV ("Canon i-SENSYS MF5880dn", "MF5880", MF5880_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP),
DEV ("Canon i-SENSYS MF6680dn", "MF6680", MF6680_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP),
DEV ("Canon imageRUNNER 1133", "iR1133", IR1133_PID, 600, 0, 637, 877, PIXMA_CAP_ADFDUP),
+ DEV ("Canon i-SENSYS MF5900 Series", "MF5900", MF5900_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
DEV ("Canon i-SENSYS MF8500C Series", "MF8500C", MF8500_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
+ DEV ("Canon i-SENSYS MF6100 Series", "MF6100", MF6100_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
+ DEV ("Canon imageClass MF810/820", "MF810/820", MF820_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
+ DEV ("Canon i-SENSYS MF220 Series", "MF220", MF220_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
+ DEV ("Canon i-SENSYS MF210 Series", "MF210", MF210_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF),
DEV (NULL, NULL, 0, 0, 0, 0, 0, 0)
};
diff --git a/backend/pixma_io_sanei.c b/backend/pixma_io_sanei.c
index 59d1602..08ec525 100644
--- a/backend/pixma_io_sanei.c
+++ b/backend/pixma_io_sanei.c
@@ -1,7 +1,7 @@
/* SANE - Scanner Access Now Easy.
* For limitations, see function sanei_usb_get_vendor_product().
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
This file is part of the SANE package.
diff --git a/backend/pixma_mp150.c b/backend/pixma_mp150.c
index 22ca41d..79711fe 100644
--- a/backend/pixma_mp150.c
+++ b/backend/pixma_mp150.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2009 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -224,6 +224,10 @@
#define MG2900_PID 0x1780
#define E460_PID 0x1788
+/* 2015 new devices (untested) */
+#define MX490_PID 0x1787
+#define E480_PID 0x1789
+
/* Generation 4 XML messages that encapsulates the Pixma protocol messages */
#define XML_START_1 \
@@ -1149,6 +1153,7 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
&& s->cfg->pid != MG5300_PID
&& s->cfg->pid != MG5500_PID
&& s->cfg->pid != MG6300_PID
+ && s->cfg->pid != MG6400_PID
&& s->cfg->pid != MG7100_PID)
reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->wx, line_size);
@@ -1817,5 +1822,9 @@ const pixma_config_t pixma_mp150_devices[] = {
DEVICE ("Canon PIXMA MG2900 Series", "MG2900", MG2900_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA E460 Series", "E460", E460_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS),
+ /* Latest devices (2015) Generation 4 CIS */
+ DEVICE ("Canon PIXMA MX490 Series", "MX490", MX490_PID, 600, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
+ DEVICE ("Canon PIXMA E480 Series", "E480", E480_PID, 600, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
+
END_OF_DEVICE_LIST
};
diff --git a/backend/pixma_mp730.c b/backend/pixma_mp730.c
index 58d1994..2184ff7 100644
--- a/backend/pixma_mp730.c
+++ b/backend/pixma_mp730.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
diff --git a/backend/pixma_mp750.c b/backend/pixma_mp750.c
index e46a942..8d2d94c 100644
--- a/backend/pixma_mp750.c
+++ b/backend/pixma_mp750.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
This file is part of the SANE package.
diff --git a/backend/pixma_mp810.c b/backend/pixma_mp810.c
index 59e96eb..e8bf75f 100644
--- a/backend/pixma_mp810.c
+++ b/backend/pixma_mp810.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2014 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2015 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2009 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -657,6 +657,23 @@ static unsigned calc_shifting (pixma_t * s)
}
break;
+ case MP990_PID:
+ if (s->param->xdpi == 4800)
+ {
+ if (is_scanning_from_tpu (s))
+ {
+ mp->stripe_shift = 6;
+ mp->stripe_shift2 = 6;
+ }
+ else
+ {
+ mp->stripe_shift = 3;
+ mp->stripe_shift2 = 3;
+ }
+ mp->jumplines = 34; /* better than 32 or 34 : applies to flatbed & TPU */
+ }
+ break;
+
default: /* Default, and all CIS devices */
break;
}
@@ -850,7 +867,7 @@ static int send_scan_param (pixma_t * s)
* 0x24 | 1 | all | 0x01
* -----+-------+---------+---------------------------
* 0x25 | 1 | default | 0x00; cs8800f: 0x01
- * | | tpu | 0x00; cs9000f, mg8200: 0x01
+ * | | tpu | 0x00; cs9000f, mg8200, mp990: 0x01
* | | tpuir | cs9000f: 0x00
* -----+-------+---------+---------------------------
* ... | 1 | all | 0x00
@@ -908,8 +925,8 @@ static int send_scan_param (pixma_t * s)
data[0x23] = 0x02;
data[0x24] = 0x01;
- /* MG8200 addition */
- if (s->cfg->pid == MG8200_PID)
+ /* MG8200 & MP990 addition */
+ if (s->cfg->pid == MG8200_PID || s->cfg->pid == MP990_PID)
{
if (is_scanning_from_tpu (s))
{