summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Lagendijk <louis.lagendijk@gmail.com>2016-12-30 20:04:53 +0100
committerLouis Lagendijk <louis.lagendijk@gmail.com>2016-12-30 20:04:53 +0100
commit526f642f6487cd348b39a6e138c2bffa9a88d0f6 (patch)
treeac9918da1b9f2bcf693bae46792cab0cce921a09
parent32be261254a78d1f314b3ee86fd5e5b40ab91a86 (diff)
parent68cd2744d1906ebf00b2bfdc90662992f8e5385c (diff)
Merge branch 'master' of ssh://git.debian.org/git/sane/sane-backends
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--AUTHORS114
-rw-r--r--backend/Makefile.am2
-rw-r--r--backend/Makefile.in4
-rw-r--r--backend/avision.c39
-rw-r--r--backend/avision.h1
-rw-r--r--backend/fujitsu-scsi.h8
-rw-r--r--backend/fujitsu.c179
-rw-r--r--backend/fujitsu.h10
-rw-r--r--backend/hp3500.c811
-rw-r--r--backend/pixma.h5
-rw-r--r--backend/pixma_mp150.c5
-rw-r--r--backend/pixma_mp730.c34
-rw-r--r--backend/xerox_mfp-tcp.c132
-rw-r--r--backend/xerox_mfp-usb.c126
-rw-r--r--backend/xerox_mfp.c2306
-rw-r--r--backend/xerox_mfp.h218
-rwxr-xr-xconfigure14
-rw-r--r--configure.ac4
-rw-r--r--doc/descriptions/pixma.desc8
-rw-r--r--doc/sane-avision.man10
-rw-r--r--doc/sane-pixma.man4
-rw-r--r--doc/sane-xerox_mfp.man59
-rw-r--r--doc/sane.man9
-rw-r--r--sanei/sanei_pp.c4
-rw-r--r--sanei/sanei_usb.c11
-rw-r--r--tools/Makefile.am5
-rw-r--r--tools/Makefile.in10
28 files changed, 2267 insertions, 1866 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 408c6b0..8c1a069 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -18,6 +18,7 @@ build:debian-8-mini:
image: $REGISTRY_HUB:debian-8-mini
variables:
CONFIGURE_OPTS: "$CONFIGURE_MINI"
+ MAKE_FLAGS: "CFLAGS=-Werror"
<<: *build_definition
build:debian-8-full:
diff --git a/AUTHORS b/AUTHORS
index 9f59348..81e257a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,106 +9,106 @@ Backends:
apple: Milon Firikis
artec: Chris Pinkham
artec_eplus48u:Sergey Vlasov, Andreas Nowack, David Stevenson, and
- Michael Herder (*)
- as6e: Eugene S. Weiss (*)
+ Michael Herder
+ as6e: Eugene S. Weiss
avision: Meino Christian Cramer, René Rebe (*)
bh: Tom Martone
canon: Helmut Koeberle, Manuel Panea, and Markus Mertinat
Mitsuru Okaniwa, Ulrich Deiters (*)
- canon630u: Nathan Rutman (*)
+ canon630u: Nathan Rutman
canon_dr: m. allan noah (*)
- canon_pp: Matthew Duggan (*), Simon Krix
- coolscan: Didier Carlier, Andreas Rick
+ canon_pp: Matthew Duggan, Simon Krix
cardscan: m. allan noah (*)
- coolscan2: Andras Major (*)
- coolscan3: Alessandro Zummo (*)
- dc25: Peter Fales (*)
+ coolscan: Didier Carlier, Andreas Rick
+ coolscan2: Andras Major
+ coolscan3: Alessandro Zummo
+ dc25: Peter Fales
dc210: Brian J. Murrell
- dc240: Peter Fales (*)
- dell1600n_net: Jon Chambers (*)
+ dc240: Peter Fales
+ dell1600n_net: Jon Chambers
dll: David Mosberger
dmc: David F. Skoll
epjitsu: m. allan noah (*)
- epson: Karl Heinz Kremer (*)
- epson2: Alessandro Zummo (*)
- epsonds: Alessandro Zummo (*)
- fujitsu: Randolph Bentson, Frederik Ramm, Oliver Schirrmeister (*),
+ epson: Karl Heinz Kremer
+ epson2: Alessandro Zummo
+ epsonds: Alessandro Zummo
+ fujitsu: Randolph Bentson, Frederik Ramm, Oliver Schirrmeister,
m. allan noah (*)
- gphoto2: Peter Fales (*)
- genesys: Henning Geinitz (*), Gerhard Jaeger (*), Stéphane Voltz (*),
- Pierre Willenbrock (*)
+ genesys: Henning Geinitz, Gerhard Jaeger (*), Stéphane Voltz (*),
+ Pierre Willenbrock
+ gphoto2: Peter Fales
gt68xx: Sergey Vlasov, Andreas Nowack, David Stevenson, and
- Henning Geinitz (*)
+ Henning Geinitz
hp: Peter Kirchgessner (*)
Geoffrey Dairiki
- hpsj5s: Max Vorobiev
hp3500: Troy Rollo (*)
- hp3900: Jonathan Bravo Lopez (*)
+ hp3900: Jonathan Bravo Lopez
hp4200: Adrian Perez Jorge, Andrew John Lewis, Arnar Mar Hrafnkelsson,
- Frank Zago (*), Henning Geinitz (*)
- hp5400: Martijn van Oosterhout, Thomas Soumarmon (*)
+ Frank Zago, Henning Geinitz
+ hp5400: Martijn van Oosterhout, Thomas Soumarmon
hp5590: Ilia Sotnikov (*)
hpljm1005: Philippe Rétornaz
+ hpsj5s: Max Vorobiev
hs2p: Jeremy Johnson (*)
- ibm: M.F., Henning Geinitz (*)
+ ibm: M.F., Henning Geinitz
kodak: m. allan noah (*)
kodakaio: Paul Newall (*)
kvs1025: Tao Zhang, m. allan noah (*)
kvs20xx: unknown, m. allan noah (*)
kvs40xx: unknown, m. allan noah (*)
- leo: Frank Zago (*)
- lexmark: Fred Odendaal (*), Stéphane Voltz (*)
- ma1509: Henning Geinitz (*)
- magicolor: Reinhold Kainhofer (*)(based on epson2 backend)
- matsushita: Frank Zago (*)
- microtek: Matthew Marjanovic (*)
+ leo: Frank Zago
+ lexmark: Fred Odendaal, Stéphane Voltz (*)
+ ma1509: Henning Geinitz
+ magicolor: Reinhold Kainhofer(based on epson2 backend)
+ matsushita: Frank Zago
+ microtek: Matthew Marjanovic
microtek2: Bernd Schroeder, Karsten Festag
mustek: Andreas Bolsch, David Mosberger, Andreas Czechanowski,
- Henning Geinitz (*), and James Perry.
- mustek_pp: Jochen Eisinger (*), Eddy De Greef (*)
- mustek_usb: Tom Wang and Henning Geinitz (*)
- mustek_usb2: Roy Zhou, Jack Xu, Vinci Cen, and Henning Geinitz (*)
- nec: Kazuya Fukuda (*)
+ Henning Geinitz, and James Perry.
+ mustek_pp: Jochen Eisinger, Eddy De Greef
+ mustek_usb: Tom Wang and Henning Geinitz
+ mustek_usb2: Roy Zhou, Jack Xu, Vinci Cen, and Henning Geinitz
+ nec: Kazuya Fukuda
net: Andreas Beck, David Mosberger, Julien Blache
- niash: Ullrich Sigwanz (*), Bertrik Sikken (*)
+ niash: Ullrich Sigwanz, Bertrik Sikken
p5: Stéphane Voltz (*)
- pie: Simon Munton (*)
+ pie: Simon Munton
pieusb: Jan Vleeshouwers, Michael Rickmann, Klaus Kämpf
pint: Gordon Matzigkeit
- pixma: Wittawat Yamwong (*)
- Nicolas Martin (*)
+ pixma: Wittawat Yamwong
+ Nicolas Martin
Louis Lagendijk (*)
Dennis Lou
Rolf Bensch (*)
plustek: Gerhard Jaeger (*)
plustek_pp: Rick Bronson (former pp driver-code), Gerhard Jaeger (*)
pnm: Andreas Beck, Gordon Matzigkeit, David Mosberger, Michael
- Herder (*), and Henning Geinitz (*)
+ Herder, and Henning Geinitz
qcam: Scott Laird (original driver), David Mosberger (SANE backend),
despeckling filter by Patrick Reynolds,
B&W fixes by Andrew Kuchling
ricoh: Feico W. Dillema
rts8891: Stéphane Voltz (*)
s9036: Ingo Schneider
- sceptre: Frank Zago (*)
- sharp: Kazuya Fukuda (*) and Abel Deuring (*)
- sm3600: Marian Eichholz (*) and Glenn Ramsey
- sm3840: Earle F. Philhower III (*)
+ sceptre: Frank Zago
+ sharp: Kazuya Fukuda and Abel Deuring
+ sm3600: Marian Eichholz and Glenn Ramsey
+ sm3840: Earle F. Philhower III
snapscan: Kevin Charter, Franck Schneider, Michel Roelofs, Sebastien
- Sable, Henrik Johansson, Chris Bagwell (*), and Oliver Schwartz (*)
+ Sable, Henrik Johansson, Chris Bagwell, and Oliver Schwartz (*)
sp15c: Randolph Bentson
st400: Ingo Wilken
- stv680: Gerard Klaver (*)
+ stv680: Gerard Klaver
tamarack: Rogier Wolff
- teco1: Frank Zago (*)
- teco2: Frank Zago (*), Gerard Klaver (*)
- teco3: Frank Zago (*)
- test: Henning Geinitz (*)
+ teco1: Frank Zago
+ teco2: Frank Zago, Gerard Klaver
+ teco3: Frank Zago
+ test: Henning Geinitz
u12: Gerhard Jaeger (*)
- umax: Oliver Rauch (*) and Michael K. Johnson
- umax_pp: Stéphane Voltz (*)
+ umax: Oliver Rauch and Michael K. Johnson
umax1220u: Marcio L. Teixeira, Patrick Lessard
- v4l: Juergen G. Schimmer, and Henning Geinitz (*)
+ umax_pp: Stéphane Voltz (*)
+ v4l: Juergen G. Schimmer, and Henning Geinitz
xerox_mfp: Alex Belkin (*)
Frontends:
@@ -117,13 +117,13 @@ Frontends:
saned: Andreas Beck, David Mosberger, Julien Blache
scanimage: Andreas Beck, David Mosberger, Gordon Matzigkeit,
m. allan noah (*), Julien Blache, Stéphane Voltz (*)
- tstbackend: Frank Zago (*)
+ tstbackend: Frank Zago
Sanei internal code:
Adrian Perez Jorge, Andreas Beck, Andreas Czechanowski, Christian Bucher,
- David Mosberger-Tang, Frank Zago (*), Henning Geinitz (*),
- Jeff Freedman, Jochen Eisinger (*), Marcio Teixeira, Yuri Dario,
+ David Mosberger-Tang, Frank Zago, Henning Geinitz,
+ Jeff Freedman, Jochen Eisinger, Marcio Teixeira, Yuri Dario,
Gerhard Jaeger (*), m. allan noah (*)
Java API:
@@ -132,8 +132,8 @@ Java API:
Miscellaneous coding:
- Julien Blache, Mattias Ellert (*), Petter Reinholdtsen (*),
- Chris Bagwell (*), Olaf Meeuwissen (*)
+ Julien Blache, Mattias Ellert, Petter Reinholdtsen,
+ Chris Bagwell, Olaf Meeuwissen (*)
Translators:
diff --git a/backend/Makefile.am b/backend/Makefile.am
index 9d1b8df..f7fb403 100644
--- a/backend/Makefile.am
+++ b/backend/Makefile.am
@@ -520,7 +520,7 @@ libhp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500
nodist_libsane_hp3500_la_SOURCES = hp3500-s.c
libsane_hp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500
libsane_hp3500_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
-libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
+libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
libhp3900_la_SOURCES = hp3900.c
libhp3900_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3900
diff --git a/backend/Makefile.in b/backend/Makefile.in
index 3a8dee2..4e070f0 100644
--- a/backend/Makefile.in
+++ b/backend/Makefile.in
@@ -748,7 +748,7 @@ libsane_hp3500_la_DEPENDENCIES = $(COMMON_LIBS) libhp3500.la \
../sanei/sanei_config.lo sane_strstatus.lo \
../sanei/sanei_usb.lo ../sanei/sanei_thread.lo \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
nodist_libsane_hp3500_la_OBJECTS = libsane_hp3500_la-hp3500-s.lo
libsane_hp3500_la_OBJECTS = $(nodist_libsane_hp3500_la_OBJECTS)
libsane_hp3500_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@@ -2370,7 +2370,7 @@ libhp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500
nodist_libsane_hp3500_la_SOURCES = hp3500-s.c
libsane_hp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500
libsane_hp3500_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
-libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
+libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
libhp3900_la_SOURCES = hp3900.c
libhp3900_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3900
nodist_libsane_hp3900_la_SOURCES = hp3900-s.c
diff --git a/backend/avision.c b/backend/avision.c
index 8120090..61491a2 100644
--- a/backend/avision.c
+++ b/backend/avision.c
@@ -1277,6 +1277,9 @@ static SANE_Bool force_calibration = SANE_FALSE;
static SANE_Bool force_a4 = SANE_FALSE;
static SANE_Bool force_a3 = SANE_FALSE;
+/* trust ADF-presence flag, even if ADF model is nonzero */
+static SANE_Bool skip_adf = SANE_FALSE;
+
/* hardware resolutions to interpolate from */
static const int hw_res_list_c5[] =
{
@@ -2736,7 +2739,7 @@ wait_4_light (Avision_Scanner* s)
struct command_read rcmd;
char* light_status[] =
{ "off", "on", "warming up", "needs warm up test",
- "light check error", "RESERVED" };
+ "light check error", "backlight on", "RESERVED" };
SANE_Status status;
uint8_t result;
@@ -2753,6 +2756,11 @@ wait_4_light (Avision_Scanner* s)
set_triple (rcmd.transferlen, size);
for (try = 0; try < 90; ++ try) {
+
+ if (s->cancelled) {
+ DBG (3, "wait_4_light: cancelled\n");
+ return SANE_STATUS_CANCELLED;
+ }
DBG (5, "wait_4_light: read bytes %lu\n", (u_long) size);
status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, &result, &size);
@@ -2762,10 +2770,10 @@ wait_4_light (Avision_Scanner* s)
return status;
}
- DBG (3, "wait_4_light: command is %d. Result is %s\n",
- status, light_status[(result>4)?5:result]);
+ DBG (3, "wait_4_light: command is %d. Result is %d (%s)\n",
+ status, result, light_status[(result>5)?6:result]);
- if (result == 1) {
+ if (result == 1 || result == 5) {
return SANE_STATUS_GOOD;
}
else if (dev->hw->feature_type & AV_LIGHT_CHECK_BOGUS) {
@@ -3218,11 +3226,13 @@ get_accessories_info (Avision_Scanner* s)
{
dev->inquiry_duplex = 1;
dev->inquiry_duplex_interlaced = 0;
- } else if (result[0] == 0 && result[2] != 0) {
+ } else if (result[0] == 0 && result[2] != 0 && !skip_adf) {
/* Sometimes the scanner will report that there is no ADF attached, yet
* an ADF model number will still be reported. This happens on the
* HP8200 series and possibly others. In this case we need to reset the
- * the adf and try reading it again.
+ * the adf and try reading it again. Skip this if the configuration says
+ * to do so, so that we don't fail out the scanner as being broken and
+ * unsupported if there isn't actually an ADF present.
*/
DBG (3, "get_accessories_info: Found ADF model number but the ADF-present flag is not set. Trying to recover...\n");
status = adf_reset (s);
@@ -6212,6 +6222,7 @@ do_cancel (Avision_Scanner* s)
s->prepared = s->scanning = SANE_FALSE;
s->duplex_rear_valid = SANE_FALSE;
s->page = 0;
+ s->cancelled = 1;
if (sanei_thread_is_valid (s->reader_pid)) {
int exit_status;
@@ -7627,6 +7638,11 @@ sane_reload_devices (void)
linenumber);
force_a3 = SANE_TRUE;
}
+ else if (strcmp (word, "skip-adf") == 0) {
+ DBG (3, "sane_reload_devices: config file line %d: enabling skip-adf\n",
+ linenumber);
+ skip_adf = SANE_TRUE;
+ }
else if (strcmp (word, "static-red-calib") == 0) {
DBG (3, "sane_reload_devices: config file line %d: static red calibration\n",
linenumber);
@@ -8310,6 +8326,9 @@ sane_start (SANE_Handle handle)
/* Make sure there is no scan running!!! */
if (s->scanning)
return SANE_STATUS_DEVICE_BUSY;
+
+ /* Clear cancellation status */
+ s->cancelled = 0;
/* Make sure we have a current parameter set. Some of the
parameters will be overwritten below, but that's OK. */
@@ -8362,6 +8381,14 @@ sane_start (SANE_Handle handle)
sane_strstatus (status));
goto stop_scanner_and_return;
}
+ /* Re-check the light, as setting the window may have changed
+ * which light is to be turned on. */
+ if (s->prepared == SANE_FALSE && dev->inquiry_light_control) {
+ status = wait_4_light (s);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+ }
}
#ifdef DEBUG_TEST
diff --git a/backend/avision.h b/backend/avision.h
index 2122e09..b26907f 100644
--- a/backend/avision.h
+++ b/backend/avision.h
@@ -444,6 +444,7 @@ typedef struct Avision_Scanner
SANE_Bool prepared; /* first page marker */
SANE_Bool scanning; /* scan in progress */
unsigned int page; /* page counter, 0: uninitialized, 1: scanning 1st page, ... */
+ int cancelled;
SANE_Parameters params; /* scan window */
Avision_Dimensions avdimen; /* scan window - detailed internals */
diff --git a/backend/fujitsu-scsi.h b/backend/fujitsu-scsi.h
index 22d2c08..26f08d9 100644
--- a/backend/fujitsu-scsi.h
+++ b/backend/fujitsu-scsi.h
@@ -1059,12 +1059,12 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
/* DTC also called Auto-I mode?*/
/*warning: filtering uses inverse logic*/
-#define set_WD_filtering(sb, val) setbitfield(sb + 0x2f, 1, 7, val)
-#define get_WD_filtering(sb) getbitfield(sb + 0x2f, 1, 7)
+#define set_WD_filtering(sb, val) setbitfield(sb + 0x2f, 1, 7, !val)
+#define get_WD_filtering(sb) !getbitfield(sb + 0x2f, 1, 7)
/*warning: smoothing uses inverse logic*/
-#define set_WD_smoothing(sb, val) setbitfield(sb + 0x2f, 3, 5, val)
-#define get_WD_smoothing(sb) getbitfield(sb + 0x2f, 3, 5)
+#define set_WD_smoothing(sb, val) setbitfield(sb + 0x2f, 3, 5, !val)
+#define get_WD_smoothing(sb) !getbitfield(sb + 0x2f, 3, 5)
#define set_WD_gamma_curve(sb, val) setbitfield(sb + 0x2f, 3, 3, val)
#define get_WD_gamma_curve(sb) getbitfield(sb + 0x2f, 3, 3)
diff --git a/backend/fujitsu.c b/backend/fujitsu.c
index 82a6b30..f5e8a5c 100644
--- a/backend/fujitsu.c
+++ b/backend/fujitsu.c
@@ -591,6 +591,11 @@
- add initial support for fi-7030
- set has_MS_lamp=0 for fi-71x0
- add I18N macros to all option titles and descriptions
+ v132 2016-10-07, MAN
+ - remove ipc_mode option and variables
+ - set ipc mode based on other options
+ - cleanup inverted logic DTC options
+ - fixes threshold option reported in #315069
SANE FLOW DIAGRAM
@@ -640,7 +645,7 @@
#include "fujitsu.h"
#define DEBUG 1
-#define BUILD 131
+#define BUILD 132
/* values for SANE_DEBUG_FUJITSU env var:
- errors 5
@@ -2033,14 +2038,6 @@ init_model (struct fujitsu *s)
s->window_gamma = 0x80;
}
- /* older scanners would enable their highest */
- /* IPC mode by default. Newer scanners don't, */
- /* so we go ahead and turn it on. */
- if (s->has_sdtc)
- s->ipc_mode = WD_ipc_SDTC;
- else if (s->has_dtc)
- s->ipc_mode = WD_ipc_DTC;
-
/* endorser type tells string length (among other things) */
if(s->has_endorser_b){
/*old-style is 40 bytes*/
@@ -2489,11 +2486,6 @@ init_user (struct fujitsu *s)
s->u_endorser_dir=DIR_TTB;
strcpy((char *)s->u_endorser_string,"%05ud");
- /* inverted logic ipc settings */
- s->noise_removal = 1;
- s->bp_filter = 1;
- s->smoothing = 1;
-
/* more recent machines default to this being 'on', *
* which causes the scanner to ingest multiple pages *
* even when the user only wants one */
@@ -3277,37 +3269,6 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
opt->cap = SANE_CAP_INACTIVE;
}
- if(option==OPT_IPC_MODE){
- i=0;
- s->ipc_mode_list[i++]=STRING_DEFAULT;
- if(s->has_dtc){
- s->ipc_mode_list[i++]=STRING_DTC;
- }
- if(s->has_sdtc){
- s->ipc_mode_list[i++]=STRING_SDTC;
- }
- s->ipc_mode_list[i]=NULL;
-
- opt->name = "ipc-mode";
- opt->title = SANE_I18N ("IPC mode");
- opt->desc = SANE_I18N ("Image processing mode, enables additional options");
- opt->type = SANE_TYPE_STRING;
- opt->unit = SANE_UNIT_NONE;
-
- opt->constraint_type = SANE_CONSTRAINT_STRING_LIST;
- opt->constraint.string_list = s->ipc_mode_list;
- opt->size = maxStringSize (opt->constraint.string_list);
-
- if ( i > 2 ){
- opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if(s->s_mode != MODE_HALFTONE && s->s_mode != MODE_LINEART){
- opt->cap |= SANE_CAP_INACTIVE;
- }
- }
- else
- opt->cap = SANE_CAP_INACTIVE;
- }
-
/* =============== DTC params ================================ */
/* enabled when in dtc mode (manually or by default) */
if(option==OPT_BP_FILTER){
@@ -3319,8 +3280,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if(s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(get_ipc_mode(s) == WD_ipc_SDTC){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3337,8 +3297,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if(s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(get_ipc_mode(s) == WD_ipc_SDTC){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3361,8 +3320,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if(s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(get_ipc_mode(s) == WD_ipc_SDTC){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3385,8 +3343,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if(s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(get_ipc_mode(s) == WD_ipc_SDTC){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3403,8 +3360,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if(s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(get_ipc_mode(s) == WD_ipc_SDTC){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3421,8 +3377,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if(s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(get_ipc_mode(s) == WD_ipc_SDTC){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3439,9 +3394,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if( !s->noise_removal
- || s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(!s->noise_removal){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3458,9 +3411,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if( !s->noise_removal
- || s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(!s->noise_removal){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3477,9 +3428,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if( !s->noise_removal
- || s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(!s->noise_removal){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3496,9 +3445,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_dtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if( !s->noise_removal
- || s->ipc_mode == WD_ipc_SDTC
- || (s->has_sdtc && s->ipc_mode == WD_ipc_DEFAULT)){
+ if(!s->noise_removal){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -3524,7 +3471,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if ( s->has_sdtc ){
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- if (s->ipc_mode == WD_ipc_DTC){
+ if(get_ipc_mode(s) == WD_ipc_DTC){
opt->cap |= SANE_CAP_INACTIVE;
}
}
@@ -4800,18 +4747,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
}
return SANE_STATUS_GOOD;
- case OPT_IPC_MODE:
- if(s->ipc_mode == WD_ipc_DEFAULT){
- strcpy (val, STRING_DEFAULT);
- }
- else if(s->ipc_mode == WD_ipc_DTC){
- strcpy (val, STRING_DTC);
- }
- else if(s->ipc_mode == WD_ipc_SDTC){
- strcpy (val, STRING_SDTC);
- }
- return SANE_STATUS_GOOD;
-
+ /* DTC params*/
case OPT_BP_FILTER:
*val_p = s->bp_filter;
return SANE_STATUS_GOOD;
@@ -4852,6 +4788,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
*val_p = s->matrix_2;
return SANE_STATUS_GOOD;
+ /* SDTC params*/
case OPT_VARIANCE:
*val_p = s->variance;
return SANE_STATUS_GOOD;
@@ -5496,48 +5433,35 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
s->wl_follow = WD_wl_follow_OFF;
return SANE_STATUS_GOOD;
- case OPT_IPC_MODE:
- if (!strcmp (val, STRING_DEFAULT)) {
- tmp = WD_ipc_DEFAULT;
- }
- else if (!strcmp (val, STRING_DTC)) {
- tmp = WD_ipc_DTC;
- }
- else {
- tmp = WD_ipc_SDTC;
- }
-
- if (tmp != s->ipc_mode)
- *info |= SANE_INFO_RELOAD_OPTIONS;
-
- s->ipc_mode = tmp;
- return SANE_STATUS_GOOD;
-
+ /* DTC params*/
case OPT_BP_FILTER:
s->bp_filter = val_c;
+ *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
case OPT_SMOOTHING:
s->smoothing = val_c;
+ *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
case OPT_GAMMA_CURVE:
s->gamma_curve = val_c;
+ *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
case OPT_THRESHOLD_CURVE:
s->threshold_curve = val_c;
+ *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
case OPT_THRESHOLD_WHITE:
s->threshold_white = val_c;
+ *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
case OPT_NOISE_REMOVAL:
- if (val_c != s->noise_removal)
- *info |= SANE_INFO_RELOAD_OPTIONS;
-
s->noise_removal = val_c;
+ *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
case OPT_MATRIX_5:
@@ -5556,8 +5480,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
s->matrix_2 = val_c;
return SANE_STATUS_GOOD;
+ /* SDTC params*/
case OPT_VARIANCE:
s->variance = val_c;
+ *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
/* Advanced Group */
@@ -7640,15 +7566,15 @@ set_window (struct fujitsu *s)
set_WD_separation(desc1,s->separation);
set_WD_mirroring(desc1,s->mirroring);
- if (s->has_sdtc && s->ipc_mode != WD_ipc_DTC)
+ if (get_ipc_mode(s) == WD_ipc_SDTC)
set_WD_variance(desc1,s->variance);
- if ((s->has_dtc && !s->has_sdtc) || s->ipc_mode == WD_ipc_DTC){
- set_WD_filtering(desc1,!s->bp_filter);
- set_WD_smoothing(desc1,!s->smoothing);
+ else if (get_ipc_mode(s) == WD_ipc_DTC){
+ set_WD_filtering(desc1,s->bp_filter);
+ set_WD_smoothing(desc1,s->smoothing);
set_WD_gamma_curve(desc1,s->gamma_curve);
set_WD_threshold_curve(desc1,s->threshold_curve);
- set_WD_noise_removal(desc1,!s->noise_removal);
+ set_WD_noise_removal(desc1,s->noise_removal);
if(s->noise_removal){
set_WD_matrix5x5(desc1,s->matrix_5);
set_WD_matrix4x4(desc1,s->matrix_4);
@@ -7660,7 +7586,7 @@ set_window (struct fujitsu *s)
set_WD_wl_follow(desc1,s->wl_follow);
set_WD_subwindow_list(desc1,0);
- set_WD_ipc_mode(desc1,s->ipc_mode);
+ set_WD_ipc_mode(desc1,get_ipc_mode(s));
}
else{
@@ -9934,6 +9860,43 @@ get_page_height(struct fujitsu *s)
return height;
}
+/* scanners have two different possible IPC
+ * modes, which enable a different series of
+ * subordinate options. Rather than provide
+ * the user with an option to pick the IPC
+ * mode, we show them the subordinate ones,
+ * and pick the right mode to match.
+ */
+static int
+get_ipc_mode(struct fujitsu *s)
+{
+ if ( s->bp_filter
+ || s->smoothing
+ || s->gamma_curve
+ || s->threshold_curve
+ || s->threshold_white
+ || s->noise_removal
+ || s->matrix_5
+ || s->matrix_4
+ || s->matrix_3
+ || s->matrix_2
+ )
+ return WD_ipc_DTC;
+
+ if(s->variance)
+ return WD_ipc_SDTC;
+
+ /* special case: 0 threshold should activate IPC */
+ if(!s->threshold){
+ if(s->has_sdtc)
+ return WD_ipc_SDTC;
+ if(s->has_dtc)
+ return WD_ipc_DTC;
+ }
+
+ return WD_ipc_DEFAULT;
+}
+
/* s->max_y gives the maximum height of paper which can be scanned
* this actually varies by resolution, so a helper to change it */
static int
diff --git a/backend/fujitsu.h b/backend/fujitsu.h
index 6ce1a56..916f069 100644
--- a/backend/fujitsu.h
+++ b/backend/fujitsu.h
@@ -43,7 +43,6 @@ enum fujitsu_Option
OPT_SEPARATION,
OPT_MIRRORING,
OPT_WL_FOLLOW,
- OPT_IPC_MODE,
/*IPC/DTC*/
OPT_BP_FILTER,
@@ -386,7 +385,6 @@ struct fujitsu
SANE_Range ht_pattern_range;
SANE_Range emphasis_range;
SANE_String_Const wl_follow_list[4];
- SANE_String_Const ipc_mode_list[4];
SANE_Range gamma_curve_range;
SANE_Range threshold_curve_range;
SANE_Range variance_range;
@@ -456,7 +454,6 @@ struct fujitsu
int separation;
int mirroring;
int wl_follow;
- int ipc_mode;
/* ipc_mode=DTC */
int bp_filter;
@@ -534,12 +531,6 @@ struct fujitsu
SANE_Parameters u_params;
SANE_Parameters s_params;
- /* also keep a backup copy, in case the software enhancement code overwrites*/
- /*
- SANE_Parameters u_params_bk;
- SANE_Parameters s_params_bk;
- */
-
/* --------------------------------------------------------------------- */
/* values which are set by scanning functions to keep track of pages, etc */
int started;
@@ -821,6 +812,7 @@ static int must_downsample (struct fujitsu *s);
static int must_fully_buffer (struct fujitsu *s);
static int get_page_width (struct fujitsu *s);
static int get_page_height (struct fujitsu *s);
+static int get_ipc_mode (struct fujitsu *s);
static int set_max_y (struct fujitsu *s);
static SANE_Status send_lut (struct fujitsu *s);
diff --git a/backend/hp3500.c b/backend/hp3500.c
index 458bbe8..26fe071 100644
--- a/backend/hp3500.c
+++ b/backend/hp3500.c
@@ -84,6 +84,7 @@
#include <string.h>
#include <ctype.h>
#include <time.h>
+#include <math.h>
#include <sys/types.h>
#include <unistd.h>
@@ -145,6 +146,7 @@ enum hp3500_option
OPT_MODE,
OPT_BRIGHTNESS,
OPT_CONTRAST,
+ OPT_GAMMA,
NUM_OPTIONS
};
@@ -189,6 +191,8 @@ struct hp3500_data
int brightness;
int contrast;
+ double gamma;
+
SANE_Option_Descriptor opt[NUM_OPTIONS];
SANE_Device sane;
};
@@ -218,6 +222,8 @@ static const SANE_Range range_brightness =
{ 0, 255, 0 };
static const SANE_Range range_contrast =
{ 0, 255, 0 };
+static const SANE_Range range_gamma =
+ { SANE_FIX (0.2), SANE_FIX(4.0), SANE_FIX(0.01) };
#define HP3500_COLOR_SCAN 0
@@ -383,6 +389,7 @@ sane_open (SANE_String_Const name, SANE_Handle * handle)
scanner->mode = 0;
scanner->brightness = 128;
scanner->contrast = 64;
+ scanner->gamma = 2.2;
calculateDerivedValues (scanner);
return SANE_STATUS_GOOD;
@@ -537,6 +544,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
*(SANE_Word *) val = scanner->contrast;
return SANE_STATUS_GOOD;
+ case OPT_GAMMA:
+ *(SANE_Word *) val = SANE_FIX(scanner->gamma);
+ return SANE_STATUS_GOOD;
+
case OPT_BRIGHTNESS:
*(SANE_Word *) val = scanner->brightness;
return SANE_STATUS_GOOD;
@@ -650,6 +661,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
case OPT_CONTRAST:
scanner->contrast = *(SANE_Word *) val;
return SANE_STATUS_GOOD;
+
+ case OPT_GAMMA:
+ scanner->gamma = SANE_UNFIX(*(SANE_Word *) val);
+ return SANE_STATUS_GOOD;
} /* switch */
} /* else */
return SANE_STATUS_INVAL;
@@ -953,7 +968,7 @@ attachScanner (const char *devicename)
dev->devicename = strdup (devicename);
dev->sfd = -1;
dev->last_scan = 0;
- dev->reader_pid = -1;
+ dev->reader_pid = (SANE_Pid) -1;
dev->pipe_r = dev->pipe_w = -1;
dev->sane.name = dev->devicename;
@@ -1088,6 +1103,16 @@ init_options (struct hp3500_data *scanner)
opt->constraint.range = &range_contrast;
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
+ opt = scanner->opt + OPT_GAMMA;
+ opt->name = SANE_NAME_ANALOG_GAMMA;
+ opt->title = SANE_TITLE_ANALOG_GAMMA;
+ opt->desc = SANE_DESC_ANALOG_GAMMA;
+ opt->type = SANE_TYPE_FIXED;
+ opt->unit = SANE_UNIT_NONE;
+ opt->constraint_type = SANE_CONSTRAINT_RANGE;
+ opt->constraint.range = &range_gamma;
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
+
return SANE_STATUS_GOOD;
}
@@ -1751,14 +1776,14 @@ rt_set_basic_calibration (unsigned char *regs,
int greengain,
int blueoffset1, int blueoffset2, int bluegain)
{
- regs[0x05] = redoffset1;
- regs[0x02] = redoffset2;
+ regs[0x02] = redoffset1;
+ regs[0x05] = redoffset2;
regs[0x08] = redgain;
- regs[0x06] = greenoffset1;
- regs[0x03] = greenoffset2;
+ regs[0x03] = greenoffset1;
+ regs[0x06] = greenoffset2;
regs[0x09] = greengain;
- regs[0x07] = blueoffset1;
- regs[0x04] = blueoffset2;
+ regs[0x04] = blueoffset1;
+ regs[0x07] = blueoffset2;
regs[0x0a] = bluegain;
return 0;
}
@@ -1767,13 +1792,36 @@ static int
rt_set_calibration_addresses (unsigned char *regs,
unsigned redaddr,
unsigned greenaddr,
- unsigned blueaddr, unsigned endaddr)
+ unsigned blueaddr,
+ unsigned endaddr,
+ unsigned width)
{
+ unsigned endpage = (endaddr + 31) / 32;
+ unsigned scanline_pages = ((width + 1) * 3 + 31) / 32;
+
+ /* Red, green and blue detailed calibration addresses */
+
regs[0x84] = redaddr;
regs[0x8e] = (regs[0x8e] & 0x0f) | ((redaddr >> 4) & 0xf0);
rt_set_value_lsbfirst (regs, 0x85, 2, greenaddr);
rt_set_value_lsbfirst (regs, 0x87, 2, blueaddr);
- rt_set_value_lsbfirst (regs, 0x89, 2, (endaddr + 31) / 32);
+
+ /* I don't know what the next three are used for, but each buffer commencing
+ * at 0x80 and 0x82 needs to hold a full scan line.
+ */
+
+ rt_set_value_lsbfirst (regs, 0x80, 2, endpage);
+ rt_set_value_lsbfirst (regs, 0x82, 2, endpage + scanline_pages);
+ rt_set_value_lsbfirst (regs, 0x89, 2, endpage + scanline_pages * 2);
+
+ /* I don't know what this is, but it seems to be a number of pages that can hold
+ * 16 complete scan lines, but not calculated as an offset from any other page
+ */
+
+ rt_set_value_lsbfirst (regs, 0x51, 2, (48 * (width + 1) + 31) / 32);
+
+ /* I don't know what this is either, but this is what the Windows driver does */
+ rt_set_value_lsbfirst (regs, 0x8f, 2, 0x1c00);
return 0;
}
@@ -1800,6 +1848,13 @@ rt_set_data_feed_on (unsigned char *regs)
}
static int
+rt_set_data_feed_off (unsigned char *regs)
+{
+ regs[0xb2] |= 0x04;
+ return 0;
+}
+
+static int
rt_enable_ccd (unsigned char *regs, int enable)
{
if (enable)
@@ -2247,10 +2302,14 @@ rt_nvram_read (int block, int location, unsigned char *data, int bytes)
return 0;
}
+/* This is what we want as the initial registers, not what they
+ * are at power on time. In particular 13 bytes at 0x10 are
+ * different, and the byte at 0x94 is different.
+ */
static unsigned char initial_regs[] = {
/* 0x00 */ 0xf5, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x08 */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
- /* 0x10 */ 0xe1, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc,
+ /* 0x10 */ 0x81, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
/* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
/* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x19,
@@ -2266,7 +2325,7 @@ static unsigned char initial_regs[] = {
/* 0x78 */ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x80 */ 0x0f, 0x02, 0x4b, 0x02, 0x00, 0xec, 0x19, 0xd8,
/* 0x88 */ 0x2d, 0x87, 0x02, 0xff, 0x3f, 0x78, 0x60, 0x00,
- /* 0x90 */ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x90 */ 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
/* 0x98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xa0 */ 0x00, 0x00, 0x00, 0x0c, 0x27, 0x64, 0x00, 0x00,
/* 0xa8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -2365,14 +2424,14 @@ static struct resolution_parameters resparms[] = {
/* My values - all work */
/*res r39 rC3 rC6 freq cph0s rgo gbo intra mmcm d3 tg stepsz */
{1200, 3, 6, 4, 2, 1, 22, 22, 4, 2, 1, RT_NORMAL_TG, 0x157b},
- {600, 15, 6, 4, 1, 0, 9, 10, 0, 2, 1, RT_NORMAL_TG, 0x055e},
+ {600, 15, 6, 4, 1, 1, 9, 10, 0, 2, 1, RT_NORMAL_TG, 0x055e},
{400, 3, 1, 4, 1, 1, 6, 6, 1, 2, 1, RT_NORMAL_TG, 0x157b},
- {300, 15, 3, 4, 1, 0, 5, 4, 0, 2, 1, RT_NORMAL_TG, 0x02af},
- {200, 7, 1, 4, 1, 0, 3, 3, 0, 2, 1, RT_NORMAL_TG, 0x055e},
- {150, 15, 3, 1, 1, 0, 2, 2, 0, 2, 1, RT_NORMAL_TG, 0x02af},
- {100, 3, 1, 3, 1, 0, 1, 1, 0, 2, 1, RT_NORMAL_TG, 0x0abd},
- {75, 15, 3, 3, 1, 0, 1, 1, 0, 2, 1, RT_NORMAL_TG, 0x02af},
- {50, 15, 1, 1, 1, 0, 0, 0, 0, 2, 1, RT_NORMAL_TG, 0x055e},
+ {300, 15, 3, 4, 1, 1, 5, 4, 0, 2, 1, RT_NORMAL_TG, 0x02af},
+ {200, 7, 1, 4, 1, 1, 3, 3, 0, 2, 1, RT_NORMAL_TG, 0x055e},
+ {150, 15, 3, 1, 1, 1, 2, 2, 0, 2, 1, RT_NORMAL_TG, 0x02af},
+ {100, 3, 1, 3, 1, 1, 1, 1, 0, 2, 1, RT_NORMAL_TG, 0x0abd},
+ {75, 15, 3, 3, 1, 1, 1, 1, 0, 2, 1, RT_NORMAL_TG, 0x02af},
+ {50, 15, 1, 1, 1, 1, 0, 0, 0, 2, 1, RT_NORMAL_TG, 0x055e},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
@@ -2599,6 +2658,90 @@ constrain (int val, int min, int max)
return val;
}
+#if 0
+static void
+sram_dump_byte(FILE *fp,
+ unsigned char const *left,
+ unsigned leftstart,
+ unsigned leftlimit,
+ unsigned char const *right,
+ unsigned rightstart,
+ unsigned rightlimit,
+ unsigned idx)
+{
+ unsigned ridx = rightstart + idx;
+ unsigned lidx = leftstart + idx;
+
+ putc(' ', fp);
+ if (rightstart < rightlimit && leftstart < leftlimit && left[lidx] != right[ridx])
+ fputs("<b>", fp);
+ if (leftstart < leftlimit)
+ fprintf(fp, "%02x", left[lidx]);
+ else
+ fputs(" ", fp);
+ if (rightstart < rightlimit && leftstart < leftlimit && left[lidx] != right[ridx])
+ fputs("</b>", fp);
+}
+
+static void
+dump_sram_to_file(char const *fname,
+ unsigned char const *expected,
+ unsigned end_calibration_offset)
+{
+ FILE *fp = fopen(fname, "w");
+ rt_set_sram_page(0);
+
+ if (fp)
+ {
+ unsigned char buf[1024];
+ unsigned loc = 0;
+
+ fprintf(fp, "<html><head></head><body><pre>\n");
+ while (loc < end_calibration_offset)
+ {
+ unsigned byte = 0;
+
+ rt_read_sram(1024, buf);
+
+ while (byte < 1024)
+ {
+ unsigned idx = 0;
+
+ fprintf(fp, "%06x:", loc);
+ do
+ {
+ sram_dump_byte(fp, buf, byte, 1024, expected, loc, end_calibration_offset, idx);
+ } while (++idx & 0x7);
+ fprintf(fp, " -");
+ do
+ {
+ sram_dump_byte(fp, buf, byte, 1024, expected, loc, end_calibration_offset, idx);
+ } while (++idx & 0x7);
+
+ idx = 0;
+ fputs(" ", fp);
+
+ do
+ {
+ sram_dump_byte(fp, expected, loc, end_calibration_offset, buf, byte, 1024, idx);
+ } while (++idx & 0x7);
+ fprintf(fp, " -");
+ do
+ {
+ sram_dump_byte(fp, expected, loc, end_calibration_offset, buf, byte, 1024, idx);
+ } while (++idx & 0x7);
+
+
+ fputs("\n", fp);
+ byte += 16;
+ loc += 16;
+ }
+ }
+ fprintf(fp, "</pre></body></html>");
+ fclose(fp);
+ }
+}
+#endif
static int
rts8801_doscan (unsigned width,
@@ -2612,7 +2755,8 @@ rts8801_doscan (unsigned width,
int oddfirst,
unsigned char const *calib_info,
int merged_channels,
- detailed_calibration_data const *detailed_calib_data)
+ double *postprocess_offsets,
+ double *postprocess_gains)
{
unsigned rowbytes = 0;
unsigned output_rowbytes = 0;
@@ -2639,6 +2783,7 @@ rts8801_doscan (unsigned width,
channels = 3;
rowbytes = width * 3;
+
switch (colour)
{
case HP3500_GRAY_SCAN:
@@ -2710,32 +2855,27 @@ rts8801_doscan (unsigned width,
if (!rows_to_begin || !--rows_to_begin)
{
unsigned char *outnow = output_buffer;
+ unsigned x;
- for (i = 0;
- i < (merged_channels ? rowbytes : width);
- i += merged_channels ? channels : 1)
+ for (i = x = 0;
+ x < width;
+ ++x, i += merged_channels ? channels : 1)
{
for (j = 0; j < channels; ++j)
{
unsigned pix =
(unsigned char) channel_data[j][i & 1][i];
- if (detailed_calib_data)
- {
- unsigned char const *calib_start =
- detailed_calib_data->channeldata[j] +
- 2 *
- detailed_calib_data->
- resolution_divisor * i /
- (merged_channels ? channels : 1);
- pix =
- constrain ((int) pix -
- (int) calib_start[0], 0,
- 255);
- pix =
- constrain (pix * calib_start[1] /
- 0x40, 0, 255);
- }
+ if (postprocess_gains && postprocess_offsets)
+ {
+ int ppidx = j * width + x;
+
+ pix = constrain ( pix
+ * postprocess_gains[ppidx]
+ - postprocess_offsets[ppidx],
+ 0,
+ 255);
+ }
*outnow++ = pix;
}
}
@@ -2818,6 +2958,9 @@ static unsigned local_sram_size;
static unsigned char r93setting;
#define RTS8801_F_SUPPRESS_MOVEMENT 1
+#define RTS8801_F_LAMP_OFF 2
+#define RTS8801_F_NO_DISPLACEMENTS 4
+#define RTS8801_F_ODDX 8
static int
find_resolution_index (unsigned resolution)
@@ -2848,7 +2991,8 @@ rts8801_fullscan (unsigned x,
int green_calib_offset,
int blue_calib_offset,
int end_calib_offset,
- detailed_calibration_data const *detailed_calib_data)
+ double *postprocess_offsets,
+ double *postprocess_gains)
{
int ires, jres;
int tg_setting;
@@ -2856,6 +3000,10 @@ rts8801_fullscan (unsigned x,
unsigned char offdutytime;
int result;
int scan_frequency;
+ unsigned intra_channel_offset;
+ unsigned red_green_offset;
+ unsigned green_blue_offset;
+ unsigned total_offsets;
ires = find_resolution_index (xresolution);
jres = find_resolution_index (yresolution);
@@ -2889,47 +3037,32 @@ rts8801_fullscan (unsigned x,
rt_set_movement_pattern (regs, 0x800000);
-
- tg_setting = resparms[jres].tg;
- rt_set_ccd_shift_clock_multiplier (regs, tg_info[tg_setting].tg_cph0p);
- rt_set_ccd_clock_reset_interval (regs, tg_info[tg_setting].tg_crsp);
- rt_set_ccd_clamp_clock_multiplier (regs, tg_info[tg_setting].tg_cclpp);
-
-
- rt_set_one_register (0xc6, 0);
- rt_set_one_register (0xc6, 0);
-
- rt_set_step_size (regs, resparms[jres].step_size);
-
rt_set_direction_forwards (regs);
-
rt_set_stop_when_rewound (regs, 0);
- rt_set_data_feed_on (regs);
- rt_set_calibration_addresses (regs, 0, 0, 0, 0);
+ rt_set_calibration_addresses (regs, 0, 0, 0, 0, 0);
rt_set_basic_calibration (regs,
calib_info[0], calib_info[1], calib_info[2],
calib_info[3], calib_info[4], calib_info[5],
calib_info[6], calib_info[7], calib_info[8]);
regs[0x0b] = 0x70; /* If set to 0x71, the alternative, all values are low */
+ regs[0x40] &= 0xc0;
if (red_calib_offset >= 0
&& green_calib_offset >= 0
- && blue_calib_offset >= 0 &&
- yresolution < 400)
+ && blue_calib_offset >= 0)
{
rt_set_calibration_addresses (regs, red_calib_offset,
green_calib_offset, blue_calib_offset,
- end_calib_offset);
+ end_calib_offset,
+ w);
regs[0x40] |= 0x2f;
- detailed_calib_data = 0;
}
else if (end_calib_offset >= 0)
{
rt_set_calibration_addresses (regs, 0x600, 0x600, 0x600,
- end_calib_offset);
- regs[0x40] &= 0xc0;
+ end_calib_offset, w);
}
rt_set_channel (regs, RT_CHANNEL_ALL);
@@ -2937,23 +3070,9 @@ rts8801_fullscan (unsigned x,
rt_set_merge_channels (regs, 1);
rt_set_colour_mode (regs, 1);
- rt_set_motor_movement_clock_multiplier (regs,
- resparms[jres].
- motor_movement_clock_multiplier);
-
- rt_set_cdss (regs, tg_info[tg_setting].tg_cdss1,
- tg_info[tg_setting].tg_cdss2);
- rt_set_cdsc (regs, tg_info[tg_setting].tg_cdsc1,
- tg_info[tg_setting].tg_cdsc2);
- rt_update_after_setting_cdss2 (regs);
-
rt_set_last_sram_page (regs, (local_sram_size - 1) >> 5);
- regs[0x39] = resparms[jres].reg_39_value;
- regs[0xc3] = (regs[0xc3] & 0xf8) | resparms[jres].reg_c3_value;
- regs[0xc6] = (regs[0xc6] & 0xf8) | resparms[jres].reg_c6_value;
scan_frequency = resparms[jres].scan_frequency;
- rt_set_scan_frequency (regs, scan_frequency);
rt_set_cph0s (regs, resparms[ires].cph0s);
if (resparms[ires].d3_bit_3_value)
regs[0xd3] |= 0x08;
@@ -2962,15 +3081,10 @@ rts8801_fullscan (unsigned x,
if (flags & RTS8801_F_SUPPRESS_MOVEMENT)
regs[0xc3] &= 0x7f;
- rt_set_horizontal_resolution (regs, xresolution);
- rt_set_noscan_distance (regs, y * scan_frequency - 1);
- rt_set_total_distance (regs, scan_frequency *
- (y +
- h +
- resparms[jres].red_green_offset +
- resparms[jres].green_blue_offset +
- resparms[jres].intra_channel_offset) - 1);
+ regs[0xb2] &= 0xf7;
+
+ rt_set_horizontal_resolution (regs, xresolution);
rt_set_scanline_start (regs,
x * (1200 / xresolution) /
@@ -2982,6 +3096,118 @@ rts8801_fullscan (unsigned x,
(resparms[ires].cph0s ? 1 : 2) /
(resparms[ires].d3_bit_3_value ? 1 : 2));
+ if (flags & RTS8801_F_NO_DISPLACEMENTS)
+ {
+ red_green_offset = green_blue_offset = intra_channel_offset = 0;
+ }
+ else
+ {
+ red_green_offset = resparms[jres].red_green_offset;
+ green_blue_offset = resparms[jres].green_blue_offset;
+ intra_channel_offset = resparms[jres].intra_channel_offset;
+ }
+ total_offsets = red_green_offset + green_blue_offset + intra_channel_offset;
+ if (y > total_offsets + 2)
+ y -= total_offsets;
+ h += total_offsets;
+
+ if (yresolution > 75 && !(flags & RTS8801_F_SUPPRESS_MOVEMENT))
+ {
+ int rmres = find_resolution_index (50);
+
+ if (rmres >= 0)
+ {
+ int factor = yresolution / 50;
+ int fastres = y / factor;
+ int remainder = y % factor;
+
+ while (remainder < 2)
+ {
+ --fastres;
+ remainder += factor;
+ }
+
+ if (fastres >= 3)
+ {
+ y = remainder;
+
+ rt_set_noscan_distance(regs, fastres * resparms[rmres].scan_frequency - 2);
+ rt_set_total_distance(regs, fastres * resparms[rmres].scan_frequency - 1);
+
+ rt_set_scan_frequency(regs, 1);
+
+ tg_setting = resparms[rmres].tg;
+ rt_set_ccd_shift_clock_multiplier (regs, tg_info[tg_setting].tg_cph0p);
+ rt_set_ccd_clock_reset_interval (regs, tg_info[tg_setting].tg_crsp);
+ rt_set_ccd_clamp_clock_multiplier (regs, tg_info[tg_setting].tg_cclpp);
+
+ rt_set_one_register (0xc6, 0);
+ rt_set_one_register (0xc6, 0);
+
+ rt_set_step_size (regs, resparms[rmres].step_size);
+
+ rt_set_motor_movement_clock_multiplier (regs,
+ resparms[rmres].
+ motor_movement_clock_multiplier);
+
+ rt_set_cdss (regs, tg_info[tg_setting].tg_cdss1,
+ tg_info[tg_setting].tg_cdss2);
+ rt_set_cdsc (regs, tg_info[tg_setting].tg_cdsc1,
+ tg_info[tg_setting].tg_cdsc2);
+ rt_update_after_setting_cdss2 (regs);
+
+ regs[0x39] = resparms[rmres].reg_39_value;
+ regs[0xc3] = (regs[0xc3] & 0xf8) | resparms[rmres].reg_c3_value;
+ regs[0xc6] = (regs[0xc6] & 0xf8) | resparms[rmres].reg_c6_value;
+
+ rt_set_data_feed_off (regs);
+
+ rt_set_all_registers (regs);
+
+ rt_set_one_register (0x2c, regs[0x2c]);
+
+ if (DBG_LEVEL >= 5)
+ dump_registers (regs);
+
+ rt_start_moving ();
+ while (rt_is_moving ());
+ }
+ }
+ }
+
+
+ rt_set_noscan_distance (regs, y * scan_frequency - 1);
+ rt_set_total_distance (regs, scan_frequency * (y + h) - 1);
+
+ rt_set_scan_frequency (regs, scan_frequency);
+
+ tg_setting = resparms[jres].tg;
+
+ rt_set_ccd_shift_clock_multiplier (regs, tg_info[tg_setting].tg_cph0p);
+ rt_set_ccd_clock_reset_interval (regs, tg_info[tg_setting].tg_crsp);
+ rt_set_ccd_clamp_clock_multiplier (regs, tg_info[tg_setting].tg_cclpp);
+
+ rt_set_one_register (0xc6, 0);
+ rt_set_one_register (0xc6, 0);
+
+ rt_set_step_size (regs, resparms[jres].step_size);
+
+ rt_set_motor_movement_clock_multiplier (regs,
+ resparms[jres].
+ motor_movement_clock_multiplier);
+
+ rt_set_cdss (regs, tg_info[tg_setting].tg_cdss1,
+ tg_info[tg_setting].tg_cdss2);
+ rt_set_cdsc (regs, tg_info[tg_setting].tg_cdsc1,
+ tg_info[tg_setting].tg_cdsc2);
+ rt_update_after_setting_cdss2 (regs);
+
+ regs[0x39] = resparms[jres].reg_39_value;
+ regs[0xc3] = (regs[0xc3] & 0xf8) | resparms[jres].reg_c3_value;
+ regs[0xc6] = (regs[0xc6] & 0xf8) | resparms[jres].reg_c6_value;
+
+ rt_set_data_feed_on (regs);
+
rt_set_all_registers (regs);
rt_set_one_register (0x2c, regs[0x2c]);
@@ -2992,12 +3218,13 @@ rts8801_fullscan (unsigned x,
result = rts8801_doscan (w,
h,
colour,
- resparms[jres].red_green_offset,
- resparms[jres].green_blue_offset,
- resparms[jres].intra_channel_offset,
+ red_green_offset,
+ green_blue_offset,
+ intra_channel_offset,
cbfunc, param, (x & 1), calib_info,
- (regs[0x2f] & 0x04) != 0, detailed_calib_data);
-
+ (regs[0x2f] & 0x04) != 0,
+ postprocess_offsets,
+ postprocess_gains);
return result;
}
@@ -3080,6 +3307,11 @@ sum_channel (unsigned char *p, int n, int bytwo)
static int do_warmup = 1;
+#define DETAILED_PASS_COUNT 3
+#define DETAILED_PASS_OFFSETS 0
+#define DETAILED_PASS_GAINS_FIRSTPASS 1
+#define DETAILED_PASS_GAINS_SECONDPASS 2
+
static int
rts8801_scan (unsigned x,
unsigned y,
@@ -3090,25 +3322,22 @@ rts8801_scan (unsigned x,
unsigned brightness,
unsigned contrast,
rts8801_callback cbfunc,
- void *param)
+ void *param,
+ double gamma)
{
unsigned char calib_info[9];
unsigned char calibbuf[2400];
struct dcalibdata dcd;
struct calibdata cd;
unsigned char *detail_buffer = 0;
- int iCalibOffset;
- int iCalibX;
int iCalibY;
- int iCalibWidth;
int iCalibTarget;
- int iCalibPixels;
int iMoveFlags = 0;
- unsigned int aiLow[3] = { 0, 0, 0 };
- unsigned int aiHigh[3] = { 256, 256, 256 };
- unsigned aiBestOffset[3];
+ unsigned aiBestOffset[6];
+ int aiPassed[6];
int i;
unsigned j;
+ int k;
int calibration_size;
unsigned char *pDetailedCalib;
int red_calibration_offset;
@@ -3120,7 +3349,13 @@ rts8801_scan (unsigned x,
int resolution_index;
int detailed_calibration_rows = 50;
unsigned char *tdetail_buffer;
- detailed_calibration_data detailed_calib_data;
+ int pass;
+ int onechanged;
+ double *postprocess_gains;
+ double *postprocess_offsets;
+ int needs_postprocessed_calibration = 0;
+ double contrast_adjust = (double) contrast / 64;
+ int brightness_adjust = brightness - 0x80;
/* Initialise and power up */
@@ -3149,98 +3384,101 @@ rts8801_scan (unsigned x,
calib_info[2] = calib_info[5] = calib_info[8] = 1;
- calib_info[0] = calib_info[1] = calib_info[3] = calib_info[4] =
- calib_info[6] = calib_info[7] = 0xb4;
-
- iCalibOffset = 0; /* Note that horizontal resolution is always 600dpi for calibration. 330 is 110 dots in (for R,G,B channels) */
- iCalibX = 1;
- iCalibPixels = 50;
- iCalibY = (resolution == 25) ? 1 : 2; /* Was 1200 / resolution, which would take us past the calibration area for 50dpi */
- iCalibWidth = 100;
+ iCalibY = (resolution == 25) ? 1 : 2;
iCalibTarget = 550;
+
+ rt_turn_off_lamp();
- for (i = 0; i < 3; ++i)
- aiBestOffset[i] = 0xb4;
-
+ for (i = 0; i < 6; ++i)
+ {
+ aiBestOffset[i] = 0xbf;
+ aiPassed[i] = 0;
+ }
+
do
{
DBG (30, "Initial calibration pass commences\n");
+ onechanged = 0;
for (i = 0; i < 3; ++i)
- {
- aiBestOffset[i] = (aiHigh[i] + aiLow[i] + 1) / 2;
- }
-
- for (i = 0; i < 3; ++i)
- calib_info[i * 3] = calib_info[i * 3 + 1] = aiBestOffset[i];
-
+ {
+ calib_info[i * 3] = aiBestOffset[i];
+ calib_info[i * 3 + 1] = aiBestOffset[i + 3];
+ }
+
cd.buffer = calibbuf;
cd.space = sizeof (calibbuf);
DBG (30, "Commencing scan for initial calibration pass\n");
- rts8801_fullscan (iCalibX, iCalibY, iCalibWidth, 2, 600, resolution,
+ rts8801_fullscan (1401, iCalibY, 100, 2, 400, resolution,
HP3500_COLOR_SCAN, (rts8801_callback) storefunc, &cd,
- calib_info, iMoveFlags, -1, -1, -1, -1, 0);
+ calib_info, iMoveFlags, -1, -1, -1, -1, 0, 0);
DBG (30, "Completed scan for initial calibration pass\n");
- iMoveFlags = RTS8801_F_SUPPRESS_MOVEMENT;
+ iMoveFlags = RTS8801_F_SUPPRESS_MOVEMENT | RTS8801_F_NO_DISPLACEMENTS;
+ iCalibY = 2;
- for (i = 0; i < 3; ++i)
+ for (i = 0; i < 6; ++i)
{
int sum;
- if (aiBestOffset[i] >= 255)
+ if (aiBestOffset[i] >= 255 || aiPassed[i] > 2)
continue;
- sum = sum_channel (calibbuf + iCalibOffset + i, iCalibPixels, 0);
+ sum = sum_channel (calibbuf + i, 50, 1);
DBG (20, "channel[%d] sum = %d (target %d)\n", i, sum,
iCalibTarget);
- if (sum >= iCalibTarget)
- aiHigh[i] = aiBestOffset[i];
- else
- aiLow[i] = aiBestOffset[i];
+ if (sum < iCalibTarget)
+ {
+ onechanged = 1;
+ ++aiBestOffset[i];
+ }
+ else
+ {
+ ++aiPassed[i];
+ }
}
DBG (30, "Initial calibration pass completed\n");
}
- while (aiLow[0] < aiHigh[0] - 1 && aiLow[1] < aiHigh[1] - 1
- && aiLow[1] < aiHigh[1] + 1);
+ while (onechanged);
DBG (20, "Offsets calculated\n");
- cd.buffer = calibbuf;
- cd.space = sizeof (calibbuf);
- DBG (20, "Scanning for part 2 of initial calibration\n");
- rts8801_fullscan (iCalibX + 2100, iCalibY, iCalibWidth, 2, 600, resolution,
- HP3500_COLOR_SCAN, (rts8801_callback) storefunc, &cd,
- calib_info, RTS8801_F_SUPPRESS_MOVEMENT, -1, -1, -1, -1,
- 0);
- DBG (20, "Scan for part 2 of initial calibration completed\n");
- DBG (20, "Initial calibration completed\n");
+ rt_turn_on_lamp();
+ usleep(500000);
tdetail_buffer =
(unsigned char *) malloc (w * 3 * detailed_calibration_rows);
- aiLow[0] = aiLow[1] = aiLow[2] = 1;
- aiHigh[0] = aiHigh[1] = aiHigh[2] = 64;
+ for (i = 0; i < 3; ++i)
+ {
+ calib_info[i * 3 + 2] = 1;
+ aiPassed[i] = 0;
+ }
+
do
{
struct dcalibdata dcdt;
- for (i = 0; i < 3; ++i)
- calib_info[i * 3 + 2] = (aiLow[i] + aiHigh[i]) / 2;
-
dcdt.buffers[0] = tdetail_buffer;
dcdt.buffers[1] = (tdetail_buffer + w * detailed_calibration_rows);
dcdt.buffers[2] = (dcdt.buffers[1] + w * detailed_calibration_rows);
dcdt.pixelsperrow = w;
dcdt.pixelnow = dcdt.channelnow = dcdt.firstrowdone = 0;
+ DBG (20, "Scanning for part 2 of initial calibration\n");
rts8801_fullscan (x, 4, w, detailed_calibration_rows + 1, resolution,
resolution, HP3500_COLOR_SCAN,
(rts8801_callback) accumfunc, &dcdt, calib_info,
- RTS8801_F_SUPPRESS_MOVEMENT, -1, -1, -1, -1, 0);
+ RTS8801_F_SUPPRESS_MOVEMENT | RTS8801_F_NO_DISPLACEMENTS, -1, -1, -1, -1, 0, 0);
+ DBG (20, "Scan for part 2 of initial calibration completed\n");
+
+ onechanged = 0;
for (i = 0; i < 3; ++i)
{
int largest = 1;
- for (j = 0; j < w; ++j)
+ if (aiPassed[i] > 2 || calib_info[i * 3 + 2] >= 63)
+ continue;
+
+ for (j = 0; j < w; ++j)
{
int val =
calcmedian (dcdt.buffers[i], j, w, detailed_calibration_rows);
@@ -3250,16 +3488,17 @@ rts8801_scan (unsigned x,
}
if (largest < 0xe0)
- aiLow[i] = calib_info[i * 3 + 2];
- else
- aiHigh[i] = calib_info[i * 3 + 2];
+ {
+ ++calib_info[i * 3 + 2];
+ onechanged = 1;
+ }
+ else
+ {
+ ++aiPassed[i];
+ }
}
}
- while (aiLow[0] < aiHigh[0] - 1 && aiLow[1] < aiHigh[1] - 1
- && aiLow[1] < aiHigh[1] + 1);
-
- for (i = 0; i < 3; ++i)
- calib_info[i * 3 + 2] = aiLow[i];
+ while (onechanged);
for (i = 0; i < 3; ++i)
{
@@ -3280,15 +3519,7 @@ rts8801_scan (unsigned x,
dcd.buffers[1] = (detail_buffer + w * detailed_calibration_rows);
dcd.buffers[2] = (dcd.buffers[1] + w * detailed_calibration_rows);
dcd.pixelsperrow = w;
- dcd.pixelnow = dcd.channelnow = dcd.firstrowdone = 0;
-
- DBG (10, "Performing detailed calibration scan\n");
- rts8801_fullscan (x, iCalibY, w, detailed_calibration_rows + 1,
- resolution, resolution, HP3500_COLOR_SCAN,
- (rts8801_callback) accumfunc, &dcd, calib_info,
- RTS8801_F_SUPPRESS_MOVEMENT, -1, -1, -1, -1, 0);
- DBG (10, "Detailed calibration scan completed\n");
/* And now for the detailed calibration */
resolution_index = find_resolution_index (resolution);
@@ -3299,101 +3530,221 @@ rts8801_scan (unsigned x,
base_resolution *= 2;
resolution_divisor = base_resolution / resolution;
- calibration_size = w * resolution_divisor * 6 + 1536;
- red_calibration_offset = 1536;
- blue_calibration_offset =
- red_calibration_offset + w * resolution_divisor * 2;
+ calibration_size = w * resolution_divisor * 6 + 1568 + 96;
+ red_calibration_offset = 0x600;
green_calibration_offset =
- blue_calibration_offset + w * resolution_divisor * 2;
- end_calibration_offset =
+ red_calibration_offset + w * resolution_divisor * 2;
+ blue_calibration_offset =
green_calibration_offset + w * resolution_divisor * 2;
+ end_calibration_offset =
+ blue_calibration_offset + w * resolution_divisor * 2;
pDetailedCalib = (unsigned char *) malloc (calibration_size);
memset (pDetailedCalib, 0, calibration_size);
+
for (i = 0; i < 3; ++i)
{
int idx =
- (i == 0) ? red_calibration_offset : (i ==
- 1) ? green_calibration_offset :
- blue_calibration_offset;
- double g = calib_info[i * 3 + 2];
+ (i == 0) ? red_calibration_offset :
+ (i == 1) ? green_calibration_offset :
+ blue_calibration_offset;
for (j = 0; j < 256; j++)
- {
- int val = j;
-
- if (val < 0)
- val = 0;
- if (val > 255)
- val = 255;
- pDetailedCalib[i * 512 + j * 2] = val;
- pDetailedCalib[i * 512 + j * 2 + 1] = val;
- }
+ {
+ /* Gamma table - appears to be 256 byte pairs for each input
+ * range (so the first entry cover inputs in the range 0 to 1,
+ * the second 1 to 2, and so on), mapping that input range
+ * (including the fractional parts within it) to an output
+ * range.
+ */
+ pDetailedCalib[i * 512 + j * 2] = j;
+ pDetailedCalib[i * 512 + j * 2 + 1] = j;
+ }
for (j = 0; j < w; ++j)
- {
- int multnow;
- int offnow;
-
- /* This seems to be the approach for reg 0x40 & 0x3f == 0x27, which allows detailed
- * calibration to return either higher or lower values.
- */
- int k;
-
- {
- double denom1 =
- calcmedian (dcd.buffers[i], j, w, detailed_calibration_rows);
- double f = 0xff / (denom1 - 2 * g);
- double contrast_adjust = (double) (contrast + 1) / 64;
-
- multnow = f * 64 * contrast_adjust;
- offnow = 4 * g + 128 - brightness;
- }
- if (multnow < 0)
- multnow = 0;
- if (multnow > 255)
- multnow = 255;
- if (offnow < 0)
- offnow = 0;
- if (offnow > 255)
- offnow = 255;
-
- for (k = 0; k < resolution_divisor; ++k)
- {
- /*multnow = j * resolution_divisor + k; */
- pDetailedCalib[idx++] = offnow; /* Subtract this value from the result */
- pDetailedCalib[idx++] = multnow; /* Then multiply by this value divided by 0x40 */
- }
- }
+ {
+ for (k = 0; k < resolution_divisor; ++k)
+ {
+ pDetailedCalib[idx++] = 0;
+ pDetailedCalib[idx++] = 0x80;
+ }
+ }
}
- DBG (10, "\n");
-
rt_set_sram_page (0);
rt_set_one_register (0x93, r93setting);
rt_write_sram (calibration_size, pDetailedCalib);
- /* And finally, perform the scan */
+ postprocess_gains = (double *) malloc(sizeof(double) * 3 * w);
+ postprocess_offsets = (double *) malloc(sizeof(double) * 3 * w);
+ for (pass = 0; pass < DETAILED_PASS_COUNT; ++pass)
+ {
+ int ppidx = 0;
+
+ DBG (10, "Performing detailed calibration scan %d\n", pass);
+
+ switch (pass)
+ {
+ case DETAILED_PASS_OFFSETS:
+ rt_turn_off_lamp();
+ usleep(500000); /* To be sure it has gone off */
+ break;
+
+ case DETAILED_PASS_GAINS_FIRSTPASS:
+ rt_turn_on_lamp();
+ usleep(500000); /* Give the lamp time to settle */
+ break;
+ }
+
+ dcd.pixelnow = dcd.channelnow = dcd.firstrowdone = 0;
+ rts8801_fullscan (x, iCalibY, w, detailed_calibration_rows + 1,
+ resolution, resolution, HP3500_COLOR_SCAN,
+ (rts8801_callback) accumfunc, &dcd,
+ calib_info,
+ RTS8801_F_SUPPRESS_MOVEMENT | RTS8801_F_NO_DISPLACEMENTS,
+ red_calibration_offset,
+ green_calibration_offset,
+ blue_calibration_offset,
+ end_calibration_offset,
+ 0, 0);
+
+ DBG (10, " Detailed calibration scan %d completed\n", pass);
+
+ for (i = 0; i < 3; ++i)
+ {
+ int idx =
+ (i == 0) ? red_calibration_offset :
+ (i == 1) ? green_calibration_offset :
+ blue_calibration_offset;
+
+ for (j = 0; j < w; ++j)
+ {
+ double multnow = 0x80;
+ int offnow = 0;
+
+ /* This seems to be the approach for reg 0x40 & 0x3f == 0x27, which allows detailed
+ * calibration to return either higher or lower values.
+ */
+
+ {
+ double denom1 =
+ calcmedian (dcd.buffers[i], j, w, detailed_calibration_rows);
+
+ switch (pass)
+ {
+ case DETAILED_PASS_OFFSETS:
+ /* The offset is the number needed to be subtracted from "black" at detailed gain = 0x80,
+ * which is the value we started with. For the next round, pull the gain down to 0x20. Our
+ * next scan is a test scan to confirm the offset works.
+ */
+ multnow = 0x20;
+ offnow = denom1;
+ break;
+
+ case DETAILED_PASS_GAINS_FIRSTPASS:
+ multnow = 128.0 / denom1 * 0x20; /* Then bring it up to whatever we need to hit 192 */
+ if (multnow > 255)
+ multnow = 255;
+ offnow = pDetailedCalib[idx];
+ break;
+
+ case DETAILED_PASS_GAINS_SECONDPASS:
+ multnow = 255.0 / denom1 * contrast_adjust * pDetailedCalib[idx+1]; /* And finally to 255 */
+ offnow = pDetailedCalib[idx] - brightness_adjust * 0x80 / multnow;
+
+ if (offnow < 0)
+ {
+ postprocess_offsets[ppidx] = multnow * offnow / 0x80;
+ offnow = 0;
+ needs_postprocessed_calibration = 1;
+ }
+ else if (offnow > 255)
+ {
+ postprocess_offsets[ppidx] = multnow * (offnow - 255) / 0x80;
+ offnow = 255;
+ needs_postprocessed_calibration = 1;
+ }
+ else
+ {
+ postprocess_offsets[ppidx] = 0;
+ }
+ if (multnow > 255)
+ {
+ postprocess_gains[ppidx] = multnow / 255;
+ multnow = 255;
+ needs_postprocessed_calibration = 1;
+ }
+ else
+ {
+ postprocess_gains[ppidx] = 1.0;
+ }
+ break;
+ }
+ }
+ if (offnow > 255)
+ offnow = 255;
+
+ for (k = 0; k < resolution_divisor; ++k)
+ {
+ pDetailedCalib[idx++] = offnow; /* Subtract this value from the result at gains = 0x80*/
+ pDetailedCalib[idx++] = multnow; /* Then multiply by this value divided by 0x80 */
+ }
+ ++ppidx;
+ }
+ }
+
+ if (pass == DETAILED_PASS_GAINS_SECONDPASS)
+ {
+ /* Build gamma table */
+ unsigned char *redgamma = pDetailedCalib;
+ unsigned char *greengamma = redgamma + 512;
+ unsigned char *bluegamma = greengamma + 512;
+ double val;
+ double invgamma = 1.0l / gamma;
+
+ *redgamma++ = *bluegamma++ = *greengamma++ = 0;
+
+ /* The windows driver does a linear interpolation for the next 19 boundaries */
+ val = pow (20.0l / 255, invgamma) * 255;
+
+ for (j = 1; j <= 20; ++j)
+ {
+ *redgamma++ = *bluegamma++ = *greengamma++ = val * j / 20 + 0.5;
+ *redgamma++ = *bluegamma++ = *greengamma++ = val * j / 20 + 0.5;
+ }
+
+ for (; j <= 255; ++j)
+ {
+ val = pow((double) j / 255, invgamma) * 255;
+
+ *redgamma++ = *bluegamma++ = *greengamma++ = val + 0.5;
+ *redgamma++ = *bluegamma++ = *greengamma++ = val + 0.5;
+ }
+ *redgamma++ = *bluegamma++ = *greengamma++ = 255;
+ }
+
+ DBG (10, "\n");
+
+ rt_set_sram_page (0);
+ rt_set_one_register (0x93, r93setting);
+ rt_write_sram (calibration_size, pDetailedCalib);
+ }
+
+ /* And finally, perform the scan */
DBG (10, "Scanning\n");
rts8801_rewind ();
- detailed_calib_data.channeldata[0] =
- pDetailedCalib + red_calibration_offset;
- detailed_calib_data.channeldata[1] =
- pDetailedCalib + green_calibration_offset;
- detailed_calib_data.channeldata[2] =
- pDetailedCalib + blue_calibration_offset;
- detailed_calib_data.resolution_divisor = resolution_divisor;
-
rts8801_fullscan (x, y, w, h, resolution, resolution, colour, cbfunc, param,
calib_info, 0,
red_calibration_offset, green_calibration_offset,
blue_calibration_offset, end_calibration_offset,
- &detailed_calib_data);
+ needs_postprocessed_calibration ? postprocess_offsets : 0,
+ needs_postprocessed_calibration ? postprocess_gains : 0);
rt_turn_off_lamp ();
+
rts8801_rewind ();
rt_set_powersave_mode (1);
@@ -3401,6 +3752,12 @@ rts8801_scan (unsigned x,
free (pDetailedCalib);
if (detail_buffer)
free (detail_buffer);
+ if (tdetail_buffer)
+ free(tdetail_buffer);
+ if (postprocess_gains)
+ free(postprocess_gains);
+ if (postprocess_offsets)
+ free(postprocess_offsets);
return 0;
}
@@ -3464,7 +3821,6 @@ reader_process (void *pv)
sigaction (SIGTERM, &act, 0);
}
-
/* Warm up the lamp again if our last scan ended more than 5 minutes ago. */
time (&t);
do_warmup = (t - scanner->last_scan) > 300;
@@ -3496,7 +3852,8 @@ reader_process (void *pv)
scanner->actres_pixels.right - scanner->actres_pixels.left,
scanner->actres_pixels.bottom - scanner->actres_pixels.top,
scanner->resolution, scanner->mode, scanner->brightness,
- scanner->contrast, (rts8801_callback) writefunc, &winfo) >= 0)
+ scanner->contrast, (rts8801_callback) writefunc, &winfo,
+ scanner->gamma) >= 0)
status = SANE_STATUS_GOOD;
status = SANE_STATUS_IO_ERROR;
close (scanner->pipe_w);
@@ -3517,5 +3874,3 @@ max_string_size (char const **strings)
}
return max_size;
}
-
-
diff --git a/backend/pixma.h b/backend/pixma.h
index f3e3056..b00e688 100644
--- a/backend/pixma.h
+++ b/backend/pixma.h
@@ -110,11 +110,14 @@ typedef uint32_t uint32_t;
/** \addtogroup API
* @{ */
+/** Don't forget to update the backend version in the SANE Backend specification
+ * file: doc/descriptions/pixma.desc !!!
+ */
/** \name Version of the driver */
/**@{*/
#define PIXMA_VERSION_MAJOR 0
#define PIXMA_VERSION_MINOR 17
-#define PIXMA_VERSION_BUILD 32
+#define PIXMA_VERSION_BUILD 34
/**@}*/
/** \name Error codes */
diff --git a/backend/pixma_mp150.c b/backend/pixma_mp150.c
index 49e4e3f..15f8214 100644
--- a/backend/pixma_mp150.c
+++ b/backend/pixma_mp150.c
@@ -234,6 +234,8 @@
#define MG6800_PID 0x178d
#define MG5700_PID 0x178e
+/* 2016 new devices (untested) */
+#define MG3000_PID 0x180b
/* Generation 4 XML messages that encapsulates the Pixma protocol messages */
#define XML_START_1 \
@@ -1867,5 +1869,8 @@ const pixma_config_t pixma_mp150_devices[] = {
DEVICE ("Canon PIXMA MG6800 Series", "MG6800", MG6800_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA MG5700 Series", "MG5700", MG5700_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
+ /* Latest devices (2016) Generation 4 CIS */
+ DEVICE ("Canon PIXMA MG3000 Series", "MG3000", MG3000_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS),
+
END_OF_DEVICE_LIST
};
diff --git a/backend/pixma_mp730.c b/backend/pixma_mp730.c
index 06bc9ee..6bf3f42 100644
--- a/backend/pixma_mp730.c
+++ b/backend/pixma_mp730.c
@@ -459,6 +459,10 @@ step1 (pixma_t * s)
default:
break;
}
+
+ // ignore result from calibrate()
+ // don't interrupt @ PIXMA_STATUS_BUSY
+ error = 0;
}
if (error >= 0)
error = activate (s, 0);
@@ -747,19 +751,23 @@ mp730_finish_scan (pixma_t * s)
query_status (s);
activate (s, 0);
- if (! aborted && s->cfg->pid == IR1020_PID)
- {
- error = abort_session (s);
- if (error < 0)
- {
- PDBG (pixma_dbg
- (1, "WARNING:abort_session() failed %s\n",
- pixma_strerror (error)));
- query_status (s);
- query_status (s);
- activate (s, 0);
- }
- }
+ // MF57x0 devices don't require abort_session() after the last page
+ if (!aborted &&
+ (s->param->source == PIXMA_SOURCE_ADF ||
+ s->param->source == PIXMA_SOURCE_ADFDUP) &&
+ has_paper (s) &&
+ (s->cfg->pid == MF5730_PID ||
+ s->cfg->pid == MF5750_PID ||
+ s->cfg->pid == MF5770_PID ||
+ s->cfg->pid == IR1020_PID))
+ {
+ error = abort_session (s);
+ if (error < 0)
+ PDBG (pixma_dbg
+ (1, "WARNING:abort_session() failed %s\n",
+ pixma_strerror (error)));
+ }
+
mp->buf = mp->lbuf = mp->imgbuf = NULL;
mp->state = state_idle;
/* fall through */
diff --git a/backend/xerox_mfp-tcp.c b/backend/xerox_mfp-tcp.c
index ab19ae6..845ab7e 100644
--- a/backend/xerox_mfp-tcp.c
+++ b/backend/xerox_mfp-tcp.c
@@ -47,9 +47,9 @@
#define RECV_TIMEOUT 1 /* seconds */
extern int sanei_debug_xerox_mfp;
-int tcp_dev_request (struct device *dev,
- SANE_Byte *cmd, size_t cmdlen,
- SANE_Byte *resp, size_t *resplen)
+int tcp_dev_request(struct device *dev,
+ SANE_Byte *cmd, size_t cmdlen,
+ SANE_Byte *resp, size_t *resplen)
{
size_t bytes_recv = 0;
ssize_t rc = 1;
@@ -58,46 +58,46 @@ int tcp_dev_request (struct device *dev,
/* Send request, if any */
if (cmd && cmdlen) {
- len = (size_t)sanei_tcp_write(dev->dn, cmd, cmdlen);
- if (len != cmdlen) {
- DBG (1, "%s: sent only %lu bytes of %lu\n",
- __func__, (u_long)len, (u_long)cmdlen);
- return SANE_STATUS_IO_ERROR;
- }
+ len = (size_t)sanei_tcp_write(dev->dn, cmd, cmdlen);
+ if (len != cmdlen) {
+ DBG(1, "%s: sent only %lu bytes of %lu\n",
+ __func__, (u_long)len, (u_long)cmdlen);
+ return SANE_STATUS_IO_ERROR;
+ }
}
/* Receive response, if expected */
if (resp && resplen) {
- DBG (3, "%s: wait for %i bytes\n", __func__, (int)*resplen);
-
- while (bytes_recv < *resplen && rc > 0) {
- rc = recv(dev->dn, resp+bytes_recv, *resplen-bytes_recv, 0);
-
- if (rc > 0) bytes_recv += rc;
- else {
- DBG(1, "%s: error %s, bytes requested: %i, bytes read: %i\n",
- __func__, strerror(errno), (int)*resplen, (int)bytes_recv);
- *resplen = bytes_recv;
-/*
- TODO:
- do something smarter than that!
-*/
- return SANE_STATUS_GOOD;
- return SANE_STATUS_IO_ERROR;
- }
- }
+ DBG(3, "%s: wait for %i bytes\n", __func__, (int)*resplen);
+
+ while (bytes_recv < *resplen && rc > 0) {
+ rc = recv(dev->dn, resp+bytes_recv, *resplen-bytes_recv, 0);
+
+ if (rc > 0) bytes_recv += rc;
+ else {
+ DBG(1, "%s: error %s, bytes requested: %i, bytes read: %i\n",
+ __func__, strerror(errno), (int)*resplen, (int)bytes_recv);
+ *resplen = bytes_recv;
+ /*
+ TODO:
+ do something smarter than that!
+ */
+ return SANE_STATUS_GOOD;
+ return SANE_STATUS_IO_ERROR;
+ }
+ }
}
*resplen = bytes_recv;
- return SANE_STATUS_GOOD;
+ return SANE_STATUS_GOOD;
}
-SANE_Status tcp_dev_open (struct device *dev)
+SANE_Status tcp_dev_open(struct device *dev)
{
SANE_Status status;
- char* strhost;
- char* strport;
+ char *strhost;
+ char *strport;
int port;
struct servent *sp;
struct timeval tv;
@@ -105,60 +105,60 @@ SANE_Status tcp_dev_open (struct device *dev)
devname = dev->sane.name;
- DBG (3, "%s: open %s\n", __func__, devname);
+ DBG(3, "%s: open %s\n", __func__, devname);
- if (strncmp (devname, "tcp", 3) != 0) return SANE_STATUS_INVAL;
+ if (strncmp(devname, "tcp", 3) != 0) return SANE_STATUS_INVAL;
devname += 3;
- devname = sanei_config_skip_whitespace (devname);
+ devname = sanei_config_skip_whitespace(devname);
if (!*devname) return SANE_STATUS_INVAL;
- devname = sanei_config_get_string (devname, &strhost);
- devname = sanei_config_skip_whitespace (devname);
+ devname = sanei_config_get_string(devname, &strhost);
+ devname = sanei_config_skip_whitespace(devname);
if (*devname)
- devname = sanei_config_get_string (devname, &strport);
+ devname = sanei_config_get_string(devname, &strport);
else
- strport = "9400";
+ strport = "9400";
if (isdigit(*strport)) {
- port = atoi(strport);
+ port = atoi(strport);
} else {
- if ((sp = getservbyname(strport, "tcp"))) {
- port = ntohs(sp->s_port);
- } else {
- DBG (1, "%s: unknown TCP service %s\n", __func__, strport);
- return SANE_STATUS_IO_ERROR;
- }
+ if ((sp = getservbyname(strport, "tcp"))) {
+ port = ntohs(sp->s_port);
+ } else {
+ DBG(1, "%s: unknown TCP service %s\n", __func__, strport);
+ return SANE_STATUS_IO_ERROR;
+ }
}
status = sanei_tcp_open(strhost, port, &dev->dn);
if (status == SANE_STATUS_GOOD) {
- tv.tv_sec = RECV_TIMEOUT;
- tv.tv_usec = 0;
- if (setsockopt (dev->dn, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) {
- DBG(1, "%s: setsockopts %s", __func__, strerror(errno));
- }
+ tv.tv_sec = RECV_TIMEOUT;
+ tv.tv_usec = 0;
+ if (setsockopt(dev->dn, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) {
+ DBG(1, "%s: setsockopts %s", __func__, strerror(errno));
+ }
}
return status;
}
void
-tcp_dev_close (struct device *dev)
+tcp_dev_close(struct device *dev)
{
if (!dev) return;
- DBG (3, "%s: closing dev %p\n", __func__, (void *)dev);
+ DBG(3, "%s: closing dev %p\n", __func__, (void *)dev);
/* finish all operations */
if (dev->scanning) {
- dev->cancel = 1;
- /* flush READ_IMAGE data */
- if (dev->reading) sane_read(dev, NULL, 1, NULL);
- /* send cancel if not sent before */
- if (dev->state != SANE_STATUS_CANCELLED)
- ret_cancel(dev, 0);
+ dev->cancel = 1;
+ /* flush READ_IMAGE data */
+ if (dev->reading) sane_read(dev, NULL, 1, NULL);
+ /* send cancel if not sent before */
+ if (dev->state != SANE_STATUS_CANCELLED)
+ ret_cancel(dev, 0);
}
sanei_tcp_close(dev->dn);
@@ -167,15 +167,15 @@ tcp_dev_close (struct device *dev)
SANE_Status
-tcp_configure_device (const char *devname, SANE_Status (*list_one)(SANE_String_Const devname))
+tcp_configure_device(const char *devname, SANE_Status(*list_one)(SANE_String_Const devname))
{
-/*
- TODO: LAN scanners multicast discovery.
- devname would contain "tcp auto"
-
- We find new devnames and feed them to
- `list_one_device' one by one
-*/
+ /*
+ TODO: LAN scanners multicast discovery.
+ devname would contain "tcp auto"
+
+ We find new devnames and feed them to
+ `list_one_device' one by one
+ */
return list_one(devname);
}
diff --git a/backend/xerox_mfp-usb.c b/backend/xerox_mfp-usb.c
index 0d8d765..6ef1eea 100644
--- a/backend/xerox_mfp-usb.c
+++ b/backend/xerox_mfp-usb.c
@@ -22,90 +22,90 @@
extern int sanei_debug_xerox_mfp;
int
-usb_dev_request (struct device *dev,
- SANE_Byte *cmd, size_t cmdlen,
- SANE_Byte *resp, size_t *resplen)
+usb_dev_request(struct device *dev,
+ SANE_Byte *cmd, size_t cmdlen,
+ SANE_Byte *resp, size_t *resplen)
{
- SANE_Status status;
- size_t len = cmdlen;
-
- if (cmd && cmdlen) {
- status = sanei_usb_write_bulk (dev->dn, cmd, &cmdlen);
- if (status != SANE_STATUS_GOOD) {
- DBG (1, "%s: sanei_usb_write_bulk: %s\n", __func__,
- sane_strstatus (status));
- return SANE_STATUS_IO_ERROR;
+ SANE_Status status;
+ size_t len = cmdlen;
+
+ if (cmd && cmdlen) {
+ status = sanei_usb_write_bulk(dev->dn, cmd, &cmdlen);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: sanei_usb_write_bulk: %s\n", __func__,
+ sane_strstatus(status));
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ if (cmdlen != len) {
+ DBG(1, "%s: sanei_usb_write_bulk: wanted %lu bytes, wrote %lu bytes\n",
+ __func__, (size_t)len, (size_t)cmdlen);
+ return SANE_STATUS_IO_ERROR;
+ }
}
- if (cmdlen != len) {
- DBG (1, "%s: sanei_usb_write_bulk: wanted %lu bytes, wrote %lu bytes\n",
- __func__, (size_t)len, (size_t)cmdlen);
- return SANE_STATUS_IO_ERROR;
- }
- }
-
- if (resp && resplen) {
- status = sanei_usb_read_bulk (dev->dn, resp, resplen);
- if (status != SANE_STATUS_GOOD) {
- DBG (1, "%s: sanei_usb_read_bulk: %s\n", __func__,
- sane_strstatus (status));
- return SANE_STATUS_IO_ERROR;
+ if (resp && resplen) {
+ status = sanei_usb_read_bulk(dev->dn, resp, resplen);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: sanei_usb_read_bulk: %s\n", __func__,
+ sane_strstatus(status));
+ return SANE_STATUS_IO_ERROR;
+ }
}
- }
- return SANE_STATUS_GOOD;
+ return SANE_STATUS_GOOD;
}
SANE_Status
-usb_dev_open (struct device *dev)
+usb_dev_open(struct device *dev)
{
- SANE_Status status;
-
- DBG (3, "%s: open %p\n", __func__, (void *)dev);
- status = sanei_usb_open (dev->sane.name, &dev->dn);
- if (status != SANE_STATUS_GOOD) {
- DBG (1, "%s: sanei_usb_open(%s): %s\n", __func__,
- dev->sane.name, sane_strstatus (status));
- dev->dn = -1;
- return status;
+ SANE_Status status;
+
+ DBG(3, "%s: open %p\n", __func__, (void *)dev);
+ status = sanei_usb_open(dev->sane.name, &dev->dn);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: sanei_usb_open(%s): %s\n", __func__,
+ dev->sane.name, sane_strstatus(status));
+ dev->dn = -1;
+ return status;
}
- sanei_usb_clear_halt (dev->dn);
- return SANE_STATUS_GOOD;
+ sanei_usb_clear_halt(dev->dn);
+ return SANE_STATUS_GOOD;
}
void
-usb_dev_close (struct device *dev)
+usb_dev_close(struct device *dev)
{
- if (!dev)
- return;
- DBG (3, "%s: closing dev %p\n", __func__, (void *)dev);
-
- /* finish all operations */
- if (dev->scanning) {
- dev->cancel = 1;
- /* flush READ_IMAGE data */
- if (dev->reading)
- sane_read(dev, NULL, 1, NULL);
- /* send cancel if not sent before */
- if (dev->state != SANE_STATUS_CANCELLED)
- ret_cancel(dev, 0);
- }
-
- sanei_usb_clear_halt (dev->dn); /* unstall for next users */
- sanei_usb_close (dev->dn);
- dev->dn = -1;
+ if (!dev)
+ return;
+ DBG(3, "%s: closing dev %p\n", __func__, (void *)dev);
+
+ /* finish all operations */
+ if (dev->scanning) {
+ dev->cancel = 1;
+ /* flush READ_IMAGE data */
+ if (dev->reading)
+ sane_read(dev, NULL, 1, NULL);
+ /* send cancel if not sent before */
+ if (dev->state != SANE_STATUS_CANCELLED)
+ ret_cancel(dev, 0);
+ }
+
+ sanei_usb_clear_halt(dev->dn); /* unstall for next users */
+ sanei_usb_close(dev->dn);
+ dev->dn = -1;
}
/* SANE API ignores return code of this callback */
SANE_Status
-usb_configure_device (const char *devname, SANE_Status (*attach) (const char *dev))
+usb_configure_device(const char *devname, SANE_Status(*attach)(const char *dev))
{
- sanei_usb_set_timeout (1000);
- sanei_usb_attach_matching_devices (devname, attach);
- sanei_usb_set_timeout (30000);
- return SANE_STATUS_GOOD;
+ sanei_usb_set_timeout(1000);
+ sanei_usb_attach_matching_devices(devname, attach);
+ sanei_usb_set_timeout(30000);
+ return SANE_STATUS_GOOD;
}
diff --git a/backend/xerox_mfp.c b/backend/xerox_mfp.c
index 0b88441..8b8c895 100644
--- a/backend/xerox_mfp.c
+++ b/backend/xerox_mfp.c
@@ -1,9 +1,12 @@
/*
- * SANE backend for Xerox Phaser 3200MFP
- * Copyright 2008 ABC <abc@telekom.ru>
+ * SANE backend for Xerox Phaser 3200MFP et al.
+ * Copyright 2008-2016 ABC <abc@telekom.ru>
*
- * Network Scanners Support
- * Copyright 2010 Alexander Kuznetsov <acca(at)cpan.org>
+ * Network Scanners Support
+ * Copyright 2010 Alexander Kuznetsov <acca(at)cpan.org>
+ *
+ * Color scanning on Samsung M2870 model and Xerox Cognac 3215 & 3225
+ * models by Laxmeesh Onkar Markod <m.laxmeesh@samsung.com>
*
* This program is licensed under GPL + SANE exception.
* More info at http://www.sane-project.org/license.html
@@ -49,34 +52,34 @@ transport available_transports[TRANSPORTS_MAX] = {
static int resolv_state(int state)
{
- if (state & STATE_DOCUMENT_JAM)
- return SANE_STATUS_JAMMED;
- if (state & STATE_NO_DOCUMENT)
- return SANE_STATUS_NO_DOCS;
- if (state & STATE_COVER_OPEN)
- return SANE_STATUS_COVER_OPEN;
- if (state & STATE_INVALID_AREA)
- return SANE_STATUS_INVAL; /* sane_start: implies SANE_INFO_RELOAD_OPTIONS */
- if (state & STATE_WARMING)
+ if (state & STATE_DOCUMENT_JAM)
+ return SANE_STATUS_JAMMED;
+ if (state & STATE_NO_DOCUMENT)
+ return SANE_STATUS_NO_DOCS;
+ if (state & STATE_COVER_OPEN)
+ return SANE_STATUS_COVER_OPEN;
+ if (state & STATE_INVALID_AREA)
+ return SANE_STATUS_INVAL; /* sane_start: implies SANE_INFO_RELOAD_OPTIONS */
+ if (state & STATE_WARMING)
#ifdef SANE_STATUS_WARMING_UP
- return SANE_STATUS_WARMING_UP;
+ return SANE_STATUS_WARMING_UP;
#else
- return SANE_STATUS_DEVICE_BUSY;
+ return SANE_STATUS_DEVICE_BUSY;
#endif
- if (state & STATE_LOCKING)
+ if (state & STATE_LOCKING)
#ifdef SANE_STATUS_HW_LOCKED
- return SANE_STATUS_HW_LOCKED;
+ return SANE_STATUS_HW_LOCKED;
#else
- return SANE_STATUS_JAMMED;
+ return SANE_STATUS_JAMMED;
#endif
- if (state & ~STATE_NO_ERROR)
- return SANE_STATUS_DEVICE_BUSY;
- return 0;
+ if (state & ~STATE_NO_ERROR)
+ return SANE_STATUS_DEVICE_BUSY;
+ return 0;
}
static char *str_cmd(int cmd)
{
- switch (cmd) {
+ switch (cmd) {
case CMD_ABORT: return "ABORT";
case CMD_INQUIRY: return "INQUIRY";
case CMD_RESERVE_UNIT: return "RESERVE_UNIT";
@@ -85,1431 +88,1442 @@ static char *str_cmd(int cmd)
case CMD_READ: return "READ";
case CMD_READ_IMAGE: return "READ_IMAGE";
case CMD_OBJECT_POSITION: return "OBJECT_POSITION";
- }
- return "unknown";
+ }
+ return "unknown";
}
#define MAX_DUMP 70
const char *encTmpFileName = "/tmp/stmp_enc.tmp";
-static int decompress(struct device *dev, const char *infilename)
+static int decompress(struct device __sane_unused__ *dev,
+ const char __sane_unused__ *infilename)
{
#ifdef HAVE_LIBJPEG
- int rc;
- int row_stride, width, height, pixel_size;
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- unsigned long bmp_size = 0;
- FILE *pInfile = NULL;
- JSAMPARRAY buffer;
-
- if ((pInfile = fopen(infilename, "rb")) == NULL) {
- fprintf(stderr, "can't open %s\n", infilename);
- return -1;
- }
+ int rc;
+ int row_stride, width, height, pixel_size;
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ unsigned long bmp_size = 0;
+ FILE *pInfile = NULL;
+ JSAMPARRAY buffer;
+
+ if ((pInfile = fopen(infilename, "rb")) == NULL) {
+ fprintf(stderr, "can't open %s\n", infilename);
+ return -1;
+ }
- cinfo.err = jpeg_std_error(&jerr);
+ cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_decompress(&cinfo);
+ jpeg_create_decompress(&cinfo);
- jpeg_stdio_src(&cinfo, pInfile);
+ jpeg_stdio_src(&cinfo, pInfile);
- rc = jpeg_read_header(&cinfo, TRUE);
- if (rc != 1) {
- jpeg_destroy_decompress(&cinfo);
- fclose(pInfile);
- return -1;
- }
+ rc = jpeg_read_header(&cinfo, TRUE);
+ if (rc != 1) {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(pInfile);
+ return -1;
+ }
- jpeg_start_decompress(&cinfo);
+ jpeg_start_decompress(&cinfo);
- width = cinfo.output_width;
- height = cinfo.output_height;
- pixel_size = cinfo.output_components;
- bmp_size = width * height * pixel_size;
- dev->decDataSize = bmp_size;
+ width = cinfo.output_width;
+ height = cinfo.output_height;
+ pixel_size = cinfo.output_components;
+ bmp_size = width * height * pixel_size;
+ dev->decDataSize = bmp_size;
- row_stride = width * pixel_size;
+ row_stride = width * pixel_size;
- buffer = (*cinfo.mem->alloc_sarray)
- ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+ buffer = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
- while (cinfo.output_scanline < cinfo.output_height) {
- buffer[0] = dev->decData + \
- (cinfo.output_scanline) * row_stride;
- jpeg_read_scanlines(&cinfo, buffer, 1);
- }
- jpeg_finish_decompress(&cinfo);
- jpeg_destroy_decompress(&cinfo);
- fclose(pInfile);
- return 0;
+ while (cinfo.output_scanline < cinfo.output_height) {
+ buffer[0] = dev->decData + \
+ (cinfo.output_scanline) * row_stride;
+ jpeg_read_scanlines(&cinfo, buffer, 1);
+ }
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ fclose(pInfile);
+ return 0;
#else
- return -1;
+ return -1;
#endif
}
static int copy_decompress_data(struct device *dev, unsigned char *pDest, int maxlen, int *destLen)
{
- int data_size = 0;
- size_t result = 0, retVal = 0;
+ int data_size = 0;
+ size_t result = 0, retVal = 0;
- if ( 0 == dev->decDataSize ) {
- *destLen = 0;
- return retVal;
- }
- data_size = dev->decDataSize - dev->currentDecDataIndex;
- if ( data_size > maxlen ) {
- data_size = maxlen;
- }
- memcpy(pDest, dev->decData+dev->currentDecDataIndex, data_size);
- result = data_size;
- *destLen = result;
- dev->currentDecDataIndex += result;
- retVal = result;
-
- if ( dev->decDataSize == dev->currentDecDataIndex ) {
- dev->currentDecDataIndex = 0;
- dev->decDataSize = 0;
- }
+ if (0 == dev->decDataSize) {
+ *destLen = 0;
+ return retVal;
+ }
+ data_size = dev->decDataSize - dev->currentDecDataIndex;
+ if (data_size > maxlen) {
+ data_size = maxlen;
+ }
+ memcpy(pDest, dev->decData+dev->currentDecDataIndex, data_size);
+ result = data_size;
+ *destLen = result;
+ dev->currentDecDataIndex += result;
+ retVal = result;
+
+ if (dev->decDataSize == dev->currentDecDataIndex) {
+ dev->currentDecDataIndex = 0;
+ dev->decDataSize = 0;
+ }
- return retVal;
+ return retVal;
}
static int decompress_tempfile(struct device *dev)
{
decompress(dev, encTmpFileName);
- remove(encTmpFileName);
- return 0;
+ remove(encTmpFileName);
+ return 0;
}
static int dump_to_tmp_file(struct device *dev)
{
- unsigned char * pSrc = dev->data;
- int srcLen = dev->datalen;
- FILE * pInfile;
- if ((pInfile = fopen(encTmpFileName, "a")) == NULL) {
- fprintf(stderr, "can't open %s\n", encTmpFileName);
- return 0;
- }
+ unsigned char *pSrc = dev->data;
+ int srcLen = dev->datalen;
+ FILE *pInfile;
+ if ((pInfile = fopen(encTmpFileName, "a")) == NULL) {
+ fprintf(stderr, "can't open %s\n", encTmpFileName);
+ return 0;
+ }
- fwrite(pSrc, 1, srcLen, pInfile);
- fclose(pInfile);
- return srcLen;
+ fwrite(pSrc, 1, srcLen, pInfile);
+ fclose(pInfile);
+ return srcLen;
}
-static int isSupportedDevice(struct device *dev)
+static int isSupportedDevice(struct device __sane_unused__ *dev)
{
#ifdef HAVE_LIBJPEG
- /* Checking device which supports JPEG Lossy compression for color scanning*/
- if ( dev->compressionTypes & (1 << 6) )
- return 1;
- else
- return 0;
+ /* Checking device which supports JPEG Lossy compression for color scanning*/
+ if (dev->compressionTypes & (1 << 6))
+ return 1;
+ else
+ return 0;
#else
- return 0;
+ return 0;
#endif
}
static void dbg_dump(struct device *dev)
{
- int i;
- char dbuf[MAX_DUMP * 3 + 1], *dptr = dbuf;
- int nzlen = dev->reslen;
- int dlen = MIN(dev->reslen, MAX_DUMP);
+ int i;
+ char dbuf[MAX_DUMP * 3 + 1], *dptr = dbuf;
+ int nzlen = dev->reslen;
+ int dlen = MIN(dev->reslen, MAX_DUMP);
- for (i = dev->reslen - 1; i >= 0; i--, nzlen--)
- if (dev->res[i] != 0)
- break;
+ for (i = dev->reslen - 1; i >= 0; i--, nzlen--)
+ if (dev->res[i] != 0)
+ break;
- dlen = MIN(dlen, nzlen + 1);
+ dlen = MIN(dlen, nzlen + 1);
- for (i = 0; i < dlen; i++, dptr += 3)
- sprintf(dptr, " %02x", dev->res[i]);
+ for (i = 0; i < dlen; i++, dptr += 3)
+ sprintf(dptr, " %02x", dev->res[i]);
- DBG (5, "[%lu]%s%s\n", (u_long)dev->reslen, dbuf,
- (dlen < (int)dev->reslen)? "..." : "");
+ DBG(5, "[%lu]%s%s\n", (u_long)dev->reslen, dbuf,
+ (dlen < (int)dev->reslen)? "..." : "");
}
/* one command to device */
/* return 0: on error, 1: success */
-static int dev_command (struct device *dev, SANE_Byte * cmd, size_t reqlen)
+static int dev_command(struct device *dev, SANE_Byte *cmd, size_t reqlen)
{
- SANE_Status status;
- size_t sendlen = cmd[3] + 4;
- SANE_Byte *res = dev->res;
-
-
- assert (reqlen <= sizeof (dev->res)); /* requested len */
- dev->reslen = sizeof (dev->res); /* doing full buffer to flush stalled commands */
-
- if (cmd[2] == CMD_SET_WINDOW) {
- /* Set Window have wrong packet length, huh. */
- sendlen = 25;
- }
-
- if (cmd[2] == CMD_READ_IMAGE) {
- /* Read Image is raw data, don't need to read response */
- res = NULL;
- }
-
- dev->state = 0;
- DBG (4, ":: dev_command(%s[%#x], %lu)\n", str_cmd(cmd[2]), cmd[2],
- (u_long)reqlen);
- status = dev->io->dev_request(dev, cmd, sendlen, res, &dev->reslen);
- if (status != SANE_STATUS_GOOD) {
- DBG (1, "%s: dev_request: %s\n", __func__, sane_strstatus (status));
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
- }
+ SANE_Status status;
+ size_t sendlen = cmd[3] + 4;
+ SANE_Byte *res = dev->res;
- if (!res) {
- /* if not need response just return success */
- return 1;
- }
- /* normal command reply, some sanity checking */
- if (dev->reslen < reqlen) {
- DBG (1, "%s: illegal response len %lu, need %lu\n",
- __func__, (u_long)dev->reslen, (u_long)reqlen);
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
- } else {
- size_t pktlen; /* len specified in packet */
+ assert(reqlen <= sizeof(dev->res)); /* requested len */
+ dev->reslen = sizeof(dev->res); /* doing full buffer to flush stalled commands */
+
+ if (cmd[2] == CMD_SET_WINDOW) {
+ /* Set Window have wrong packet length, huh. */
+ sendlen = 25;
+ }
+
+ if (cmd[2] == CMD_READ_IMAGE) {
+ /* Read Image is raw data, don't need to read response */
+ res = NULL;
+ }
+
+ dev->state = 0;
+ DBG(4, ":: dev_command(%s[%#x], %lu)\n", str_cmd(cmd[2]), cmd[2],
+ (u_long)reqlen);
+ status = dev->io->dev_request(dev, cmd, sendlen, res, &dev->reslen);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: dev_request: %s\n", __func__, sane_strstatus(status));
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ }
- if (DBG_LEVEL > 3)
- dbg_dump(dev);
+ if (!res) {
+ /* if not need response just return success */
+ return 1;
+ }
- if (dev->res[0] != RES_CODE) {
- DBG (2, "%s: illegal data header %02x\n", __func__, dev->res[0]);
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
+ /* normal command reply, some sanity checking */
+ if (dev->reslen < reqlen) {
+ DBG(1, "%s: illegal response len %lu, need %lu\n",
+ __func__, (u_long)dev->reslen, (u_long)reqlen);
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ } else {
+ size_t pktlen; /* len specified in packet */
+
+ if (DBG_LEVEL > 3)
+ dbg_dump(dev);
+
+ if (dev->res[0] != RES_CODE) {
+ DBG(2, "%s: illegal data header %02x\n", __func__, dev->res[0]);
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ }
+ pktlen = dev->res[2] + 3;
+ if (dev->reslen != pktlen) {
+ DBG(2, "%s: illegal response len %lu, should be %lu\n",
+ __func__, (u_long)pktlen, (u_long)dev->reslen);
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ }
+ if (dev->reslen > reqlen)
+ DBG(2, "%s: too big packet len %lu, need %lu\n",
+ __func__, (u_long)dev->reslen, (u_long)reqlen);
}
- pktlen = dev->res[2] + 3;
- if (dev->reslen != pktlen) {
- DBG (2, "%s: illegal response len %lu, should be %lu\n",
- __func__, (u_long)pktlen, (u_long)dev->reslen);
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
+
+ dev->state = 0;
+ if (cmd[2] == CMD_SET_WINDOW ||
+ cmd[2] == CMD_OBJECT_POSITION ||
+ cmd[2] == CMD_READ ||
+ cmd[2] == CMD_RESERVE_UNIT) {
+ if (dev->res[1] == STATUS_BUSY)
+ dev->state = SANE_STATUS_DEVICE_BUSY;
+ else if (dev->res[1] == STATUS_CANCEL)
+ dev->state = SANE_STATUS_CANCELLED;
+ else if (dev->res[1] == STATUS_CHECK)
+ dev->state = resolv_state((cmd[2] == CMD_READ)?
+ (dev->res[12] << 8 | dev->res[13]) :
+ (dev->res[4] << 8 | dev->res[5]));
+
+ if (dev->state)
+ DBG(3, "%s(%s[%#x]): => %d: %s\n",
+ __func__, str_cmd(cmd[2]), cmd[2],
+ dev->state, sane_strstatus(dev->state));
}
- if (dev->reslen > reqlen)
- DBG (2, "%s: too big packet len %lu, need %lu\n",
- __func__, (u_long)dev->reslen, (u_long)reqlen);
- }
-
- dev->state = 0;
- if (cmd[2] == CMD_SET_WINDOW ||
- cmd[2] == CMD_OBJECT_POSITION ||
- cmd[2] == CMD_READ ||
- cmd[2] == CMD_RESERVE_UNIT) {
- if (dev->res[1] == STATUS_BUSY)
- dev->state = SANE_STATUS_DEVICE_BUSY;
- else if (dev->res[1] == STATUS_CANCEL)
- dev->state = SANE_STATUS_CANCELLED;
- else if (dev->res[1] == STATUS_CHECK)
- dev->state = resolv_state((cmd[2] == CMD_READ)?
- (dev->res[12] << 8 | dev->res[13]) :
- (dev->res[4] << 8 | dev->res[5]));
-
- if (dev->state)
- DBG (3, "%s(%s[%#x]): => %d: %s\n",
- __func__, str_cmd(cmd[2]), cmd[2],
- dev->state, sane_strstatus(dev->state));
- }
-
- return 1;
+
+ return 1;
}
/* one short command to device */
-static int dev_cmd (struct device *dev, SANE_Byte command)
+static int dev_cmd(struct device *dev, SANE_Byte command)
{
- SANE_Byte cmd[4] = { REQ_CODE_A, REQ_CODE_B };
- cmd[2] = command;
- return dev_command (dev, cmd, (command == CMD_INQUIRY)? 70 : 32);
+ SANE_Byte cmd[4] = { REQ_CODE_A, REQ_CODE_B };
+ cmd[2] = command;
+ return dev_command(dev, cmd, (command == CMD_INQUIRY)? 70 : 32);
}
/* stop scanning operation. return previous status */
static SANE_Status dev_stop(struct device *dev)
{
- int state = dev->state;
-
- DBG (3, "%s: %p, scanning %d, reserved %d\n", __func__,
- (void *)dev, dev->scanning, dev->reserved);
- dev->scanning = 0;
-
- /* release */
- if (!dev->reserved)
- return state;
- dev->reserved = 0;
- dev_cmd(dev, CMD_RELEASE_UNIT);
- DBG (3, "total image %d*%d size %d (win %d*%d), %d*%d %d data: %d, out %d bytes\n",
- dev->para.pixels_per_line, dev->para.lines,
- dev->total_img_size,
- dev->win_width, dev->win_len,
- dev->pixels_per_line, dev->ulines, dev->blocks,
- dev->total_data_size, dev->total_out_size);
- dev->state = state;
- return state;
+ int state = dev->state;
+
+ DBG(3, "%s: %p, scanning %d, reserved %d\n", __func__,
+ (void *)dev, dev->scanning, dev->reserved);
+ dev->scanning = 0;
+
+ /* release */
+ if (!dev->reserved)
+ return state;
+ dev->reserved = 0;
+ dev_cmd(dev, CMD_RELEASE_UNIT);
+ DBG(3, "total image %d*%d size %d (win %d*%d), %d*%d %d data: %d, out %d bytes\n",
+ dev->para.pixels_per_line, dev->para.lines,
+ dev->total_img_size,
+ dev->win_width, dev->win_len,
+ dev->pixels_per_line, dev->ulines, dev->blocks,
+ dev->total_data_size, dev->total_out_size);
+ dev->state = state;
+ return state;
}
SANE_Status ret_cancel(struct device *dev, SANE_Status ret)
{
- dev_cmd(dev, CMD_ABORT);
- if (dev->scanning) {
- dev_stop(dev);
- dev->state = SANE_STATUS_CANCELLED;
- }
- return ret;
+ dev_cmd(dev, CMD_ABORT);
+ if (dev->scanning) {
+ dev_stop(dev);
+ dev->state = SANE_STATUS_CANCELLED;
+ }
+ return ret;
}
static int cancelled(struct device *dev)
{
- if (dev->cancel)
- return ret_cancel(dev, 1);
- return 0;
+ if (dev->cancel)
+ return ret_cancel(dev, 1);
+ return 0;
}
/* issue command and wait until scanner is not busy */
/* return 0 on error/blocking, 1 is ok and ready */
static int dev_cmd_wait(struct device *dev, int cmd)
{
- int sleeptime = 10;
-
- do {
- if (cancelled(dev))
- return 0;
- if (!dev_cmd(dev, cmd)) {
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
- } else if (dev->state) {
- if (dev->state != SANE_STATUS_DEVICE_BUSY)
- return 0;
- else {
- if (dev->non_blocking) {
- dev->state = SANE_STATUS_GOOD;
- return 0;
- } else {
- if (sleeptime > 1000)
- sleeptime = 1000;
- DBG (4, "(%s) sleeping(%d ms).. [%x %x]\n",
- str_cmd(cmd), sleeptime, dev->res[4], dev->res[5]);
- usleep(sleeptime * 1000);
- if (sleeptime < 1000)
- sleeptime *= (sleeptime < 100)? 10 : 2;
- }
- } /* BUSY */
- }
- } while (dev->state == SANE_STATUS_DEVICE_BUSY);
+ int sleeptime = 10;
+
+ do {
+ if (cancelled(dev))
+ return 0;
+ if (!dev_cmd(dev, cmd)) {
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ } else if (dev->state) {
+ if (dev->state != SANE_STATUS_DEVICE_BUSY)
+ return 0;
+ else {
+ if (dev->non_blocking) {
+ dev->state = SANE_STATUS_GOOD;
+ return 0;
+ } else {
+ if (sleeptime > 1000)
+ sleeptime = 1000;
+ DBG(4, "(%s) sleeping(%d ms).. [%x %x]\n",
+ str_cmd(cmd), sleeptime, dev->res[4], dev->res[5]);
+ usleep(sleeptime * 1000);
+ if (sleeptime < 1000)
+ sleeptime *= (sleeptime < 100)? 10 : 2;
+ }
+ } /* BUSY */
+ }
+ } while (dev->state == SANE_STATUS_DEVICE_BUSY);
- return 1;
+ return 1;
}
static int inq_dpi_bits[] = {
- 75, 150, 0, 0,
- 200, 300, 0, 0,
- 600, 0, 0, 1200,
- 100, 0, 0, 2400,
- 0, 4800, 0, 9600
+ 75, 150, 0, 0,
+ 200, 300, 0, 0,
+ 600, 0, 0, 1200,
+ 100, 0, 0, 2400,
+ 0, 4800, 0, 9600
};
static int res_dpi_codes[] = {
- 75, 0, 150, 0,
- 0, 300, 0, 600,
- 1200, 200, 100, 2400,
- 4800, 9600
+ 75, 0, 150, 0,
+ 0, 300, 0, 600,
+ 1200, 200, 100, 2400,
+ 4800, 9600
};
-static int SANE_Word_sort(const void * a, const void * b)
+static int SANE_Word_sort(const void *a, const void *b)
{
- return *(const SANE_Word *)a - *(const SANE_Word *)b;
+ return *(const SANE_Word *)a - *(const SANE_Word *)b;
}
/* resolve inquired dpi list to dpi_list array */
static void resolv_inq_dpi(struct device *dev)
{
- unsigned int i;
- int res = dev->resolutions;
-
- assert(sizeof(inq_dpi_bits) < sizeof(dev->dpi_list));
- for (i = 0; i < sizeof(inq_dpi_bits) / sizeof(int); i++)
- if (inq_dpi_bits[i] && (res & (1 << i)))
- dev->dpi_list[++dev->dpi_list[0]] = inq_dpi_bits[i];
- qsort(&dev->dpi_list[1], dev->dpi_list[0], sizeof(SANE_Word), SANE_Word_sort);
+ unsigned int i;
+ int res = dev->resolutions;
+
+ assert(sizeof(inq_dpi_bits) < sizeof(dev->dpi_list));
+ for (i = 0; i < sizeof(inq_dpi_bits) / sizeof(int); i++)
+ if (inq_dpi_bits[i] && (res & (1 << i)))
+ dev->dpi_list[++dev->dpi_list[0]] = inq_dpi_bits[i];
+ qsort(&dev->dpi_list[1], dev->dpi_list[0], sizeof(SANE_Word), SANE_Word_sort);
}
static unsigned int dpi_to_code(int dpi)
{
- unsigned int i;
+ unsigned int i;
- for (i = 0; i < sizeof(res_dpi_codes) / sizeof(int); i++) {
- if (dpi == res_dpi_codes[i])
- return i;
- }
- return 0;
+ for (i = 0; i < sizeof(res_dpi_codes) / sizeof(int); i++) {
+ if (dpi == res_dpi_codes[i])
+ return i;
+ }
+ return 0;
}
static int string_match_index(const SANE_String_Const s[], SANE_String m)
{
- int i;
-
- for (i = 0; *s; i++) {
- SANE_String_Const x = *s++;
- if (strcasecmp(x, m) == 0)
- return i;
- }
- return 0;
+ int i;
+
+ for (i = 0; *s; i++) {
+ SANE_String_Const x = *s++;
+ if (strcasecmp(x, m) == 0)
+ return i;
+ }
+ return 0;
}
static SANE_String string_match(const SANE_String_Const s[], SANE_String m)
{
- return UNCONST(s[string_match_index(s, m)]);
+ return UNCONST(s[string_match_index(s, m)]);
}
-static size_t max_string_size (SANE_String_Const s[])
+static size_t max_string_size(SANE_String_Const s[])
{
- size_t max = 0;
-
- while (*s) {
- size_t size = strlen(*s++) + 1;
- if (size > max)
- max = size;
- }
- return max;
+ size_t max = 0;
+
+ while (*s) {
+ size_t size = strlen(*s++) + 1;
+ if (size > max)
+ max = size;
+ }
+ return max;
}
static SANE_String_Const doc_sources[] = {
- "Flatbed", "ADF", "Auto", NULL
+ "Flatbed", "ADF", "Auto", NULL
};
static int doc_source_to_code[] = {
- 0x40, 0x20, 0x80
+ 0x40, 0x20, 0x80
};
static SANE_String_Const scan_modes[] = {
- SANE_VALUE_SCAN_MODE_LINEART,
- SANE_VALUE_SCAN_MODE_HALFTONE,
- SANE_VALUE_SCAN_MODE_GRAY,
- SANE_VALUE_SCAN_MODE_COLOR,
- NULL
+ SANE_VALUE_SCAN_MODE_LINEART,
+ SANE_VALUE_SCAN_MODE_HALFTONE,
+ SANE_VALUE_SCAN_MODE_GRAY,
+ SANE_VALUE_SCAN_MODE_COLOR,
+ NULL
};
static int scan_mode_to_code[] = {
- 0x00, 0x01, 0x03, 0x05
+ 0x00, 0x01, 0x03, 0x05
};
static SANE_Range threshold = {
- SANE_FIX(30), SANE_FIX(70), SANE_FIX(10)
+ SANE_FIX(30), SANE_FIX(70), SANE_FIX(10)
};
static void reset_options(struct device *dev)
{
- dev->val[OPT_RESOLUTION].w = 150;
- dev->val[OPT_MODE].s = string_match(scan_modes, SANE_VALUE_SCAN_MODE_COLOR);
-
- /* if docs loaded in adf use it as default source, flatbed oterwise */
- dev->val[OPT_SOURCE].s = UNCONST(doc_sources[(dev->doc_loaded)? 1 : 0]);
-
- dev->val[OPT_THRESHOLD].w = SANE_FIX(50);
-
- /* this is reported maximum window size, will be fixed later */
- dev->win_x_range.min = SANE_FIX(0);
- dev->win_x_range.max = SANE_FIX((double)dev->max_win_width / PNT_PER_MM);
- dev->win_x_range.quant = SANE_FIX(1);
- dev->win_y_range.min = SANE_FIX(0);
- dev->win_y_range.max = SANE_FIX((double)dev->max_win_len / PNT_PER_MM);
- dev->win_y_range.quant = SANE_FIX(1);
- dev->val[OPT_SCAN_TL_X].w = dev->win_x_range.min;
- dev->val[OPT_SCAN_TL_Y].w = dev->win_y_range.min;
- dev->val[OPT_SCAN_BR_X].w = dev->win_x_range.max;
- dev->val[OPT_SCAN_BR_Y].w = dev->win_y_range.max;
+ dev->val[OPT_RESOLUTION].w = 150;
+ dev->val[OPT_MODE].s = string_match(scan_modes, SANE_VALUE_SCAN_MODE_COLOR);
+
+ /* if docs loaded in adf use it as default source, flatbed oterwise */
+ dev->val[OPT_SOURCE].s = UNCONST(doc_sources[(dev->doc_loaded)? 1 : 0]);
+
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(50);
+
+ /* this is reported maximum window size, will be fixed later */
+ dev->win_x_range.min = SANE_FIX(0);
+ dev->win_x_range.max = SANE_FIX((double)dev->max_win_width / PNT_PER_MM);
+ dev->win_x_range.quant = SANE_FIX(1);
+ dev->win_y_range.min = SANE_FIX(0);
+ dev->win_y_range.max = SANE_FIX((double)dev->max_win_len / PNT_PER_MM);
+ dev->win_y_range.quant = SANE_FIX(1);
+ dev->val[OPT_SCAN_TL_X].w = dev->win_x_range.min;
+ dev->val[OPT_SCAN_TL_Y].w = dev->win_y_range.min;
+ dev->val[OPT_SCAN_BR_X].w = dev->win_x_range.max;
+ dev->val[OPT_SCAN_BR_Y].w = dev->win_y_range.max;
}
static void init_options(struct device *dev)
{
- int i;
-
- for (i = 0; i < NUM_OPTIONS; i++) {
- dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- dev->opt[i].size = sizeof(SANE_Word);
- dev->opt[i].type = SANE_TYPE_FIXED;
- dev->val[i].s = NULL;
- }
-
- dev->opt[OPT_NUMOPTIONS].name = SANE_NAME_NUM_OPTIONS;
- dev->opt[OPT_NUMOPTIONS].title = SANE_TITLE_NUM_OPTIONS;
- dev->opt[OPT_NUMOPTIONS].desc = SANE_DESC_NUM_OPTIONS;
- dev->opt[OPT_NUMOPTIONS].type = SANE_TYPE_INT;
- dev->opt[OPT_NUMOPTIONS].cap = SANE_CAP_SOFT_DETECT;
- dev->val[OPT_NUMOPTIONS].w = NUM_OPTIONS;
-
- dev->opt[OPT_GROUP_STD].name = SANE_NAME_STANDARD;
- dev->opt[OPT_GROUP_STD].title = SANE_TITLE_STANDARD;
- dev->opt[OPT_GROUP_STD].desc = SANE_DESC_STANDARD;
- dev->opt[OPT_GROUP_STD].type = SANE_TYPE_GROUP;
- dev->opt[OPT_GROUP_STD].cap = 0;
-
- dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
- dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
- dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
- dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
- dev->opt[OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
- dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
- dev->opt[OPT_RESOLUTION].constraint.word_list = dev->dpi_list;
-
- dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
- dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
- dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
- dev->opt[OPT_MODE].type = SANE_TYPE_STRING;
- dev->opt[OPT_MODE].size = max_string_size(scan_modes);
- dev->opt[OPT_MODE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
- dev->opt[OPT_MODE].constraint.string_list = scan_modes;
-
- dev->opt[OPT_THRESHOLD].name = SANE_NAME_HIGHLIGHT;
- dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
- dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
- dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
- dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_THRESHOLD].constraint.range = &threshold;
-
- dev->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
- dev->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
- dev->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
- dev->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
- dev->opt[OPT_SOURCE].size = max_string_size(doc_sources);
- dev->opt[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
- dev->opt[OPT_SOURCE].constraint.string_list = doc_sources;
-
- dev->opt[OPT_GROUP_GEO].name = SANE_NAME_GEOMETRY;
- dev->opt[OPT_GROUP_GEO].title = SANE_TITLE_GEOMETRY;
- dev->opt[OPT_GROUP_GEO].desc = SANE_DESC_GEOMETRY;
- dev->opt[OPT_GROUP_GEO].type = SANE_TYPE_GROUP;
- dev->opt[OPT_GROUP_GEO].cap = 0;
-
- dev->opt[OPT_SCAN_TL_X].name = SANE_NAME_SCAN_TL_X;
- dev->opt[OPT_SCAN_TL_X].title = SANE_TITLE_SCAN_TL_X;
- dev->opt[OPT_SCAN_TL_X].desc = SANE_DESC_SCAN_TL_X;
- dev->opt[OPT_SCAN_TL_X].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_TL_X].constraint.range = &dev->win_x_range;
-
- dev->opt[OPT_SCAN_TL_Y].name = SANE_NAME_SCAN_TL_Y;
- dev->opt[OPT_SCAN_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
- dev->opt[OPT_SCAN_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
- dev->opt[OPT_SCAN_TL_Y].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_TL_Y].constraint.range = &dev->win_y_range;
-
- dev->opt[OPT_SCAN_BR_X].name = SANE_NAME_SCAN_BR_X;
- dev->opt[OPT_SCAN_BR_X].title = SANE_TITLE_SCAN_BR_X;
- dev->opt[OPT_SCAN_BR_X].desc = SANE_DESC_SCAN_BR_X;
- dev->opt[OPT_SCAN_BR_X].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_BR_X].constraint.range = &dev->win_x_range;
-
- dev->opt[OPT_SCAN_BR_Y].name = SANE_NAME_SCAN_BR_Y;
- dev->opt[OPT_SCAN_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
- dev->opt[OPT_SCAN_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
- dev->opt[OPT_SCAN_BR_Y].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_BR_Y].constraint.range = &dev->win_y_range;
+ int i;
+
+ for (i = 0; i < NUM_OPTIONS; i++) {
+ dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
+ dev->opt[i].size = sizeof(SANE_Word);
+ dev->opt[i].type = SANE_TYPE_FIXED;
+ dev->val[i].s = NULL;
+ }
+
+ dev->opt[OPT_NUMOPTIONS].name = SANE_NAME_NUM_OPTIONS;
+ dev->opt[OPT_NUMOPTIONS].title = SANE_TITLE_NUM_OPTIONS;
+ dev->opt[OPT_NUMOPTIONS].desc = SANE_DESC_NUM_OPTIONS;
+ dev->opt[OPT_NUMOPTIONS].type = SANE_TYPE_INT;
+ dev->opt[OPT_NUMOPTIONS].cap = SANE_CAP_SOFT_DETECT;
+ dev->val[OPT_NUMOPTIONS].w = NUM_OPTIONS;
+
+ dev->opt[OPT_GROUP_STD].name = SANE_NAME_STANDARD;
+ dev->opt[OPT_GROUP_STD].title = SANE_TITLE_STANDARD;
+ dev->opt[OPT_GROUP_STD].desc = SANE_DESC_STANDARD;
+ dev->opt[OPT_GROUP_STD].type = SANE_TYPE_GROUP;
+ dev->opt[OPT_GROUP_STD].cap = 0;
+
+ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
+ dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
+ dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
+ dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
+ dev->opt[OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
+ dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ dev->opt[OPT_RESOLUTION].constraint.word_list = dev->dpi_list;
+
+ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
+ dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
+ dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
+ dev->opt[OPT_MODE].type = SANE_TYPE_STRING;
+ dev->opt[OPT_MODE].size = max_string_size(scan_modes);
+ dev->opt[OPT_MODE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ dev->opt[OPT_MODE].constraint.string_list = scan_modes;
+
+ dev->opt[OPT_THRESHOLD].name = SANE_NAME_HIGHLIGHT;
+ dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
+ dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
+ dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
+ dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_THRESHOLD].constraint.range = &threshold;
+
+ dev->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
+ dev->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
+ dev->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
+ dev->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
+ dev->opt[OPT_SOURCE].size = max_string_size(doc_sources);
+ dev->opt[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ dev->opt[OPT_SOURCE].constraint.string_list = doc_sources;
+
+ dev->opt[OPT_GROUP_GEO].name = SANE_NAME_GEOMETRY;
+ dev->opt[OPT_GROUP_GEO].title = SANE_TITLE_GEOMETRY;
+ dev->opt[OPT_GROUP_GEO].desc = SANE_DESC_GEOMETRY;
+ dev->opt[OPT_GROUP_GEO].type = SANE_TYPE_GROUP;
+ dev->opt[OPT_GROUP_GEO].cap = 0;
+
+ dev->opt[OPT_SCAN_TL_X].name = SANE_NAME_SCAN_TL_X;
+ dev->opt[OPT_SCAN_TL_X].title = SANE_TITLE_SCAN_TL_X;
+ dev->opt[OPT_SCAN_TL_X].desc = SANE_DESC_SCAN_TL_X;
+ dev->opt[OPT_SCAN_TL_X].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_TL_X].constraint.range = &dev->win_x_range;
+
+ dev->opt[OPT_SCAN_TL_Y].name = SANE_NAME_SCAN_TL_Y;
+ dev->opt[OPT_SCAN_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
+ dev->opt[OPT_SCAN_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
+ dev->opt[OPT_SCAN_TL_Y].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_TL_Y].constraint.range = &dev->win_y_range;
+
+ dev->opt[OPT_SCAN_BR_X].name = SANE_NAME_SCAN_BR_X;
+ dev->opt[OPT_SCAN_BR_X].title = SANE_TITLE_SCAN_BR_X;
+ dev->opt[OPT_SCAN_BR_X].desc = SANE_DESC_SCAN_BR_X;
+ dev->opt[OPT_SCAN_BR_X].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_BR_X].constraint.range = &dev->win_x_range;
+
+ dev->opt[OPT_SCAN_BR_Y].name = SANE_NAME_SCAN_BR_Y;
+ dev->opt[OPT_SCAN_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
+ dev->opt[OPT_SCAN_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
+ dev->opt[OPT_SCAN_BR_Y].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_BR_Y].constraint.range = &dev->win_y_range;
}
/* fill parameters from options */
static void set_parameters(struct device *dev)
{
- double px_to_len;
+ double px_to_len;
- dev->para.last_frame = SANE_TRUE;
- dev->para.lines = -1;
- px_to_len = 1200.0 / dev->val[OPT_RESOLUTION].w;
+ dev->para.last_frame = SANE_TRUE;
+ dev->para.lines = -1;
+ px_to_len = 1200.0 / dev->val[OPT_RESOLUTION].w;
#define BETTER_BASEDPI 1
- /* tests prove that 1200dpi base is very inexact
- * so I calculated better values for each axis */
-#if BETTER_BASEDPI
- px_to_len = 1180.0 / dev->val[OPT_RESOLUTION].w;
+ /* tests prove that 1200dpi base is very inexact
+ * so I calculated better values for each axis */
+#if BETTER_BASEDPI
+ px_to_len = 1180.0 / dev->val[OPT_RESOLUTION].w;
#endif
- dev->para.pixels_per_line = dev->win_width / px_to_len;
- dev->para.bytes_per_line = dev->para.pixels_per_line;
+ dev->para.pixels_per_line = dev->win_width / px_to_len;
+ dev->para.bytes_per_line = dev->para.pixels_per_line;
- if ( !isSupportedDevice(dev) ) {
+ if (!isSupportedDevice(dev)) {
#if BETTER_BASEDPI
- px_to_len = 1213.9 / dev->val[OPT_RESOLUTION].w;
+ px_to_len = 1213.9 / dev->val[OPT_RESOLUTION].w;
#endif
- }
- dev->para.lines = dev->win_len / px_to_len;
- if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE) {
- dev->para.format = SANE_FRAME_GRAY;
- dev->para.depth = 1;
- dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
- } else if (dev->composition == MODE_GRAY8) {
- dev->para.format = SANE_FRAME_GRAY;
- dev->para.depth = 8;
- dev->para.bytes_per_line = dev->para.pixels_per_line;
- } else if (dev->composition == MODE_RGB24) {
- dev->para.format = SANE_FRAME_RGB;
- dev->para.depth = 8;
- dev->para.bytes_per_line *= 3;
- } else {
- /* this will never happen */
- DBG (1, "%s: impossible image composition %d\n",
- __func__, dev->composition);
- dev->para.format = SANE_FRAME_GRAY;
- dev->para.depth = 8;
- }
+ }
+ dev->para.lines = dev->win_len / px_to_len;
+ if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE) {
+ dev->para.format = SANE_FRAME_GRAY;
+ dev->para.depth = 1;
+ dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
+ } else if (dev->composition == MODE_GRAY8) {
+ dev->para.format = SANE_FRAME_GRAY;
+ dev->para.depth = 8;
+ dev->para.bytes_per_line = dev->para.pixels_per_line;
+ } else if (dev->composition == MODE_RGB24) {
+ dev->para.format = SANE_FRAME_RGB;
+ dev->para.depth = 8;
+ dev->para.bytes_per_line *= 3;
+ } else {
+ /* this will never happen */
+ DBG(1, "%s: impossible image composition %d\n",
+ __func__, dev->composition);
+ dev->para.format = SANE_FRAME_GRAY;
+ dev->para.depth = 8;
+ }
}
/* resolve all options related to scan window */
/* called after option changed and in set_window */
static int fix_window(struct device *dev)
{
- double win_width_mm, win_len_mm;
- int i;
- int threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
-
- dev->resolution = dpi_to_code(dev->val[OPT_RESOLUTION].w);
- dev->composition = scan_mode_to_code[string_match_index(scan_modes, dev->val[OPT_MODE].s)];
-
- if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE) {
- dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
- } else {
- dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
- }
- if (threshold < 30) {
- dev->val[OPT_THRESHOLD].w = SANE_FIX(30);
- } else if (threshold > 70) {
- dev->val[OPT_THRESHOLD].w = SANE_FIX(70);
- }
- threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
- dev->threshold = (threshold - 30) / 10;
- dev->val[OPT_THRESHOLD].w = SANE_FIX(dev->threshold * 10 + 30);
-
- dev->doc_source = doc_source_to_code[string_match_index(doc_sources, dev->val[OPT_SOURCE].s)];
-
- /* max window len is dependent of document source */
- if (dev->doc_source == DOC_FLATBED ||
- (dev->doc_source == DOC_AUTO && !dev->doc_loaded))
- dev->max_len = dev->max_len_fb;
- else
- dev->max_len = dev->max_len_adf;
-
- /* parameters */
- dev->win_y_range.max = SANE_FIX((double)dev->max_len / PNT_PER_MM);
-
- /* window sanity checking */
- for (i = OPT_SCAN_TL_X; i <= OPT_SCAN_BR_Y; i++) {
- if (dev->val[i].w < dev->opt[i].constraint.range->min)
- dev->val[i].w = dev->opt[i].constraint.range->min;
- if (dev->val[i].w > dev->opt[i].constraint.range->max)
- dev->val[i].w = dev->opt[i].constraint.range->max;
- }
-
- if (dev->val[OPT_SCAN_TL_X].w > dev->val[OPT_SCAN_BR_X].w)
- SWAP_Word(dev->val[OPT_SCAN_TL_X].w, dev->val[OPT_SCAN_BR_X].w);
- if (dev->val[OPT_SCAN_TL_Y].w > dev->val[OPT_SCAN_BR_Y].w)
- SWAP_Word(dev->val[OPT_SCAN_TL_Y].w, dev->val[OPT_SCAN_BR_Y].w);
-
- /* recalculate millimeters to inches */
- dev->win_off_x = SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w) / MM_PER_INCH;
- dev->win_off_y = SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w) / MM_PER_INCH;
-
- /* calc win size in mm */
- win_width_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_X].w) -
- SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w);
- win_len_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_Y].w) -
- SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w);
- /* convert mm to 1200 dpi points */
- dev->win_width = (int)(win_width_mm * PNT_PER_MM);
- dev->win_len = (int)(win_len_mm * PNT_PER_MM);
-
- /* don't scan if window is zero size */
- if (!dev->win_width || !dev->win_len) {
- /* "The scan cannot be started with the current set of options." */
- dev->state = SANE_STATUS_INVAL;
- return 0;
- }
+ double win_width_mm, win_len_mm;
+ int i;
+ int threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
- return 1;
-}
+ dev->resolution = dpi_to_code(dev->val[OPT_RESOLUTION].w);
+ dev->composition = scan_mode_to_code[string_match_index(scan_modes, dev->val[OPT_MODE].s)];
-static int dev_set_window (struct device *dev)
-{
- SANE_Byte cmd[0x19] = {
- REQ_CODE_A, REQ_CODE_B, CMD_SET_WINDOW, 0x13, MSG_SCANNING_PARAM
- };
+ if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE) {
+ dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
+ } else {
+ dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
+ }
+ if (threshold < 30) {
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(30);
+ } else if (threshold > 70) {
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(70);
+ }
+ threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
+ dev->threshold = (threshold - 30) / 10;
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(dev->threshold * 10 + 30);
- if (!fix_window(dev))
- return 0;
+ dev->doc_source = doc_source_to_code[string_match_index(doc_sources, dev->val[OPT_SOURCE].s)];
- cmd[0x05] = dev->win_width >> 24;
- cmd[0x06] = dev->win_width >> 16;
- cmd[0x07] = dev->win_width >> 8;
- cmd[0x08] = dev->win_width;
- cmd[0x09] = dev->win_len >> 24;
- cmd[0x0a] = dev->win_len >> 16;
- cmd[0x0b] = dev->win_len >> 8;
- cmd[0x0c] = dev->win_len;
- cmd[0x0d] = dev->resolution; /* x */
- cmd[0x0e] = dev->resolution; /* y */
- cmd[0x0f] = (SANE_Byte)floor(dev->win_off_x);
- cmd[0x10] = (SANE_Byte)((dev->win_off_x - floor(dev->win_off_x)) * 100);
- cmd[0x11] = (SANE_Byte)floor(dev->win_off_y);
- cmd[0x12] = (SANE_Byte)((dev->win_off_y - floor(dev->win_off_y)) * 100);
- cmd[0x13] = dev->composition;
- /* Set to JPEG Lossy Compression, if mode is color (only for supported model)...
- * else go with Uncompressed (For backard compatibility with old models )*/
- if (dev->composition == MODE_RGB24) {
- if ( isSupportedDevice(dev) ) {
- cmd[0x14] = 0x6;
- }
- }
- cmd[0x16] = dev->threshold;
- cmd[0x17] = dev->doc_source;
-
- DBG (5, "OFF xi: %02x%02x yi: %02x%02x,"
- " WIN xp: %02x%02x%02x%02x yp %02x%02x%02x%02x,"
- " MAX %08x %08x\n",
- cmd[0x0f], cmd[0x10], cmd[0x11], cmd[0x12],
- cmd[0x05], cmd[0x06], cmd[0x07], cmd[0x08],
- cmd[0x09], cmd[0x0a], cmd[0x0b], cmd[0x0c],
- dev->max_win_width, dev->max_win_len);
-
- return dev_command (dev, cmd, 32);
+ /* max window len is dependent of document source */
+ if (dev->doc_source == DOC_FLATBED ||
+ (dev->doc_source == DOC_AUTO && !dev->doc_loaded))
+ dev->max_len = dev->max_len_fb;
+ else
+ dev->max_len = dev->max_len_adf;
+
+ /* parameters */
+ dev->win_y_range.max = SANE_FIX((double)dev->max_len / PNT_PER_MM);
+
+ /* window sanity checking */
+ for (i = OPT_SCAN_TL_X; i <= OPT_SCAN_BR_Y; i++) {
+ if (dev->val[i].w < dev->opt[i].constraint.range->min)
+ dev->val[i].w = dev->opt[i].constraint.range->min;
+ if (dev->val[i].w > dev->opt[i].constraint.range->max)
+ dev->val[i].w = dev->opt[i].constraint.range->max;
+ }
+
+ if (dev->val[OPT_SCAN_TL_X].w > dev->val[OPT_SCAN_BR_X].w)
+ SWAP_Word(dev->val[OPT_SCAN_TL_X].w, dev->val[OPT_SCAN_BR_X].w);
+ if (dev->val[OPT_SCAN_TL_Y].w > dev->val[OPT_SCAN_BR_Y].w)
+ SWAP_Word(dev->val[OPT_SCAN_TL_Y].w, dev->val[OPT_SCAN_BR_Y].w);
+
+ /* recalculate millimeters to inches */
+ dev->win_off_x = SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w) / MM_PER_INCH;
+ dev->win_off_y = SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w) / MM_PER_INCH;
+
+ /* calc win size in mm */
+ win_width_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_X].w) -
+ SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w);
+ win_len_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_Y].w) -
+ SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w);
+ /* convert mm to 1200 dpi points */
+ dev->win_width = (int)(win_width_mm * PNT_PER_MM);
+ dev->win_len = (int)(win_len_mm * PNT_PER_MM);
+
+ /* don't scan if window is zero size */
+ if (!dev->win_width || !dev->win_len) {
+ /* "The scan cannot be started with the current set of options." */
+ dev->state = SANE_STATUS_INVAL;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int dev_set_window(struct device *dev)
+{
+ SANE_Byte cmd[0x19] = {
+ REQ_CODE_A, REQ_CODE_B, CMD_SET_WINDOW, 0x13, MSG_SCANNING_PARAM
+ };
+
+ if (!fix_window(dev))
+ return 0;
+
+ cmd[0x05] = dev->win_width >> 24;
+ cmd[0x06] = dev->win_width >> 16;
+ cmd[0x07] = dev->win_width >> 8;
+ cmd[0x08] = dev->win_width;
+ cmd[0x09] = dev->win_len >> 24;
+ cmd[0x0a] = dev->win_len >> 16;
+ cmd[0x0b] = dev->win_len >> 8;
+ cmd[0x0c] = dev->win_len;
+ cmd[0x0d] = dev->resolution; /* x */
+ cmd[0x0e] = dev->resolution; /* y */
+ cmd[0x0f] = (SANE_Byte)floor(dev->win_off_x);
+ cmd[0x10] = (SANE_Byte)((dev->win_off_x - floor(dev->win_off_x)) * 100);
+ cmd[0x11] = (SANE_Byte)floor(dev->win_off_y);
+ cmd[0x12] = (SANE_Byte)((dev->win_off_y - floor(dev->win_off_y)) * 100);
+ cmd[0x13] = dev->composition;
+ /* Set to JPEG Lossy Compression, if mode is color (only for supported model)...
+ * else go with Uncompressed (For backard compatibility with old models )*/
+ if (dev->composition == MODE_RGB24) {
+ if (isSupportedDevice(dev)) {
+ cmd[0x14] = 0x6;
+ }
+ }
+ cmd[0x16] = dev->threshold;
+ cmd[0x17] = dev->doc_source;
+
+ DBG(5, "OFF xi: %02x%02x yi: %02x%02x,"
+ " WIN xp: %02x%02x%02x%02x yp %02x%02x%02x%02x,"
+ " MAX %08x %08x\n",
+ cmd[0x0f], cmd[0x10], cmd[0x11], cmd[0x12],
+ cmd[0x05], cmd[0x06], cmd[0x07], cmd[0x08],
+ cmd[0x09], cmd[0x0a], cmd[0x0b], cmd[0x0c],
+ dev->max_win_width, dev->max_win_len);
+
+ return dev_command(dev, cmd, 32);
}
static SANE_Status
-dev_inquiry (struct device *dev)
+dev_inquiry(struct device *dev)
{
- SANE_Byte *ptr;
- SANE_Char *optr, *xptr;
-
- if (!dev_cmd (dev, CMD_INQUIRY))
- return SANE_STATUS_IO_ERROR;
- ptr = dev->res;
- if (ptr[3] != MSG_PRODUCT_INFO) {
- DBG (1, "%s: illegal INQUIRY response %02x\n", __func__, ptr[3]);
- return SANE_STATUS_IO_ERROR;
- }
-
- /* parse reported manufacturer/product names */
- dev->sane.vendor = optr = (SANE_Char *) malloc (33);
- for (ptr += 4; ptr < &dev->res[0x24] && *ptr && *ptr != ' ';)
- *optr++ = *ptr++;
- *optr++ = 0;
-
- for (; ptr < &dev->res[0x24] && (!*ptr || *ptr == ' '); ptr++)
- /* skip spaces */;
-
- dev->sane.model = optr = (SANE_Char *) malloc (33);
- xptr = optr; /* is last non space character + 1 */
- for (; ptr < &dev->res[0x24] && *ptr;) {
- if (*ptr != ' ')
- xptr = optr + 1;
- *optr++ = *ptr++;
- }
- *optr++ = 0;
- *xptr = 0;
-
- DBG (1, "%s: found %s/%s\n", __func__, dev->sane.vendor, dev->sane.model);
- dev->sane.type = strdup ("multi-function peripheral");
-
- dev->resolutions = dev->res[0x37] << 16 |
- dev->res[0x24] << 8 |
- dev->res[0x25];
- dev->compositions = dev->res[0x27];
- dev->max_win_width = dev->res[0x28] << 24 |
- dev->res[0x29] << 16 |
- dev->res[0x2a] << 8 |
- dev->res[0x2b];
- dev->max_win_len = dev->res[0x2c] << 24 |
- dev->res[0x2d] << 16 |
- dev->res[0x2e] << 8 |
- dev->res[0x2f];
- dev->max_len_adf = dev->res[0x38] << 24 |
- dev->res[0x39] << 16 |
- dev->res[0x3a] << 8 |
- dev->res[0x3b];
- dev->max_len_fb = dev->res[0x3c] << 24 |
- dev->res[0x3d] << 16 |
- dev->res[0x3e] << 8 |
- dev->res[0x3f];
- dev->line_order = dev->res[0x31];
- dev->compressionTypes = dev->res[0x32];
- dev->doc_loaded = (dev->res[0x35] == 0x02) &&
- (dev->res[0x26] & 0x03);
-
- init_options(dev);
- reset_options(dev);
- fix_window(dev);
- set_parameters(dev);
- resolv_inq_dpi(dev);
-
- return SANE_STATUS_GOOD;
+ SANE_Byte *ptr;
+ SANE_Char *optr, *xptr;
+
+ if (!dev_cmd(dev, CMD_INQUIRY))
+ return SANE_STATUS_IO_ERROR;
+ ptr = dev->res;
+ if (ptr[3] != MSG_PRODUCT_INFO) {
+ DBG(1, "%s: illegal INQUIRY response %02x\n", __func__, ptr[3]);
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ /* parse reported manufacturer/product names */
+ dev->sane.vendor = optr = (SANE_Char *) malloc(33);
+ for (ptr += 4; ptr < &dev->res[0x24] && *ptr && *ptr != ' ';)
+ *optr++ = *ptr++;
+ *optr++ = 0;
+
+ for (; ptr < &dev->res[0x24] && (!*ptr || *ptr == ' '); ptr++)
+ /* skip spaces */;
+
+ dev->sane.model = optr = (SANE_Char *) malloc(33);
+ xptr = optr; /* is last non space character + 1 */
+ for (; ptr < &dev->res[0x24] && *ptr;) {
+ if (*ptr != ' ')
+ xptr = optr + 1;
+ *optr++ = *ptr++;
+ }
+ *optr++ = 0;
+ *xptr = 0;
+
+ DBG(1, "%s: found %s/%s\n", __func__, dev->sane.vendor, dev->sane.model);
+ dev->sane.type = strdup("multi-function peripheral");
+
+ dev->resolutions = dev->res[0x37] << 16 |
+ dev->res[0x24] << 8 |
+ dev->res[0x25];
+ dev->compositions = dev->res[0x27];
+ dev->max_win_width = dev->res[0x28] << 24 |
+ dev->res[0x29] << 16 |
+ dev->res[0x2a] << 8 |
+ dev->res[0x2b];
+ dev->max_win_len = dev->res[0x2c] << 24 |
+ dev->res[0x2d] << 16 |
+ dev->res[0x2e] << 8 |
+ dev->res[0x2f];
+ dev->max_len_adf = dev->res[0x38] << 24 |
+ dev->res[0x39] << 16 |
+ dev->res[0x3a] << 8 |
+ dev->res[0x3b];
+ dev->max_len_fb = dev->res[0x3c] << 24 |
+ dev->res[0x3d] << 16 |
+ dev->res[0x3e] << 8 |
+ dev->res[0x3f];
+ dev->line_order = dev->res[0x31];
+ dev->compressionTypes = dev->res[0x32];
+ dev->doc_loaded = (dev->res[0x35] == 0x02) &&
+ (dev->res[0x26] & 0x03);
+
+ init_options(dev);
+ reset_options(dev);
+ fix_window(dev);
+ set_parameters(dev);
+ resolv_inq_dpi(dev);
+
+ return SANE_STATUS_GOOD;
}
const SANE_Option_Descriptor *
-sane_get_option_descriptor (SANE_Handle h, SANE_Int opt)
+sane_get_option_descriptor(SANE_Handle h, SANE_Int opt)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p, %d\n", __func__, h, opt);
- if (opt >= NUM_OPTIONS || opt < 0)
- return NULL;
- return &dev->opt[opt];
+ DBG(3, "%s: %p, %d\n", __func__, h, opt);
+ if (opt >= NUM_OPTIONS || opt < 0)
+ return NULL;
+ return &dev->opt[opt];
}
SANE_Status
-sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act,
- void *val, SANE_Word * info)
+sane_control_option(SANE_Handle h, SANE_Int opt, SANE_Action act,
+ void *val, SANE_Word *info)
{
- struct device *dev = h;
-
- DBG (3, "%s: %p, %d, <%d>, %p, %p\n", __func__, h, opt, act, val, (void *)info);
- if (!dev || opt >= NUM_OPTIONS || opt < 0)
- return SANE_STATUS_INVAL;
-
- if (info)
- *info = 0;
-
- if (act == SANE_ACTION_GET_VALUE) { /* GET */
- if (dev->opt[opt].type == SANE_TYPE_STRING)
- strcpy(val, dev->val[opt].s);
- else
- *(SANE_Word *)val = dev->val[opt].w;
- } else if (act == SANE_ACTION_SET_VALUE) { /* SET */
- SANE_Parameters xpara = dev->para;
- SANE_Option_Descriptor xopt[NUM_OPTIONS];
- Option_Value xval[NUM_OPTIONS];
- int i;
-
- if (dev->opt[opt].constraint_type == SANE_CONSTRAINT_STRING_LIST) {
- dev->val[opt].s = string_match(dev->opt[opt].constraint.string_list, val);
- if (info && strcasecmp(dev->val[opt].s, val))
- *info |= SANE_INFO_INEXACT;
- } else if (opt == OPT_RESOLUTION)
- dev->val[opt].w = res_dpi_codes[dpi_to_code(*(SANE_Word *)val)];
- else
- dev->val[opt].w = *(SANE_Word *)val;
-
- memcpy(&xopt, &dev->opt, sizeof(xopt));
- memcpy(&xval, &dev->val, sizeof(xval));
- fix_window(dev);
- set_parameters(dev);
-
- /* check for side effects */
- if (info) {
- if (memcmp(&xpara, &dev->para, sizeof(xpara)))
- *info |= SANE_INFO_RELOAD_PARAMS;
- if (memcmp(&xopt, &dev->opt, sizeof(xopt)))
- *info |= SANE_INFO_RELOAD_OPTIONS;
- for (i = 0; i < NUM_OPTIONS; i++)
- if (xval[i].w != dev->val[i].w) {
- if (i == opt)
- *info |= SANE_INFO_INEXACT;
- else
- *info |= SANE_INFO_RELOAD_OPTIONS;
- }
+ struct device *dev = h;
+
+ DBG(3, "%s: %p, %d, <%d>, %p, %p\n", __func__, h, opt, act, val, (void *)info);
+ if (!dev || opt >= NUM_OPTIONS || opt < 0)
+ return SANE_STATUS_INVAL;
+
+ if (info)
+ *info = 0;
+
+ if (act == SANE_ACTION_GET_VALUE) { /* GET */
+ if (dev->opt[opt].type == SANE_TYPE_STRING)
+ strcpy(val, dev->val[opt].s);
+ else
+ *(SANE_Word *)val = dev->val[opt].w;
+ } else if (act == SANE_ACTION_SET_VALUE) { /* SET */
+ SANE_Parameters xpara = dev->para;
+ SANE_Option_Descriptor xopt[NUM_OPTIONS];
+ Option_Value xval[NUM_OPTIONS];
+ int i;
+
+ if (dev->opt[opt].constraint_type == SANE_CONSTRAINT_STRING_LIST) {
+ dev->val[opt].s = string_match(dev->opt[opt].constraint.string_list, val);
+ if (info && strcasecmp(dev->val[opt].s, val))
+ *info |= SANE_INFO_INEXACT;
+ } else if (opt == OPT_RESOLUTION)
+ dev->val[opt].w = res_dpi_codes[dpi_to_code(*(SANE_Word *)val)];
+ else
+ dev->val[opt].w = *(SANE_Word *)val;
+
+ memcpy(&xopt, &dev->opt, sizeof(xopt));
+ memcpy(&xval, &dev->val, sizeof(xval));
+ fix_window(dev);
+ set_parameters(dev);
+
+ /* check for side effects */
+ if (info) {
+ if (memcmp(&xpara, &dev->para, sizeof(xpara)))
+ *info |= SANE_INFO_RELOAD_PARAMS;
+ if (memcmp(&xopt, &dev->opt, sizeof(xopt)))
+ *info |= SANE_INFO_RELOAD_OPTIONS;
+ for (i = 0; i < NUM_OPTIONS; i++)
+ if (xval[i].w != dev->val[i].w) {
+ if (i == opt)
+ *info |= SANE_INFO_INEXACT;
+ else
+ *info |= SANE_INFO_RELOAD_OPTIONS;
+ }
+ }
}
- }
- DBG (4, "%s: %d, <%d> => %08x, %x\n", __func__, opt, act,
- val? *(SANE_Word *)val : 0, info? *info : 0);
- return SANE_STATUS_GOOD;
+ DBG(4, "%s: %d, <%d> => %08x, %x\n", __func__, opt, act,
+ val? *(SANE_Word *)val : 0, info? *info : 0);
+ return SANE_STATUS_GOOD;
}
static void
-dev_free (struct device *dev)
+dev_free(struct device *dev)
{
- if (!dev)
- return;
-
- if (dev->sane.name)
- free (UNCONST(dev->sane.name));
- if (dev->sane.vendor)
- free (UNCONST(dev->sane.vendor));
- if (dev->sane.model)
- free (UNCONST(dev->sane.model));
- if (dev->sane.type)
- free (UNCONST(dev->sane.type));
- if (dev->data)
- free(dev->data);
- if (dev->decData) {
- free(dev->decData);
- dev->decData = NULL;
- }
- memset (dev, 0, sizeof (*dev));
- free (dev);
+ if (!dev)
+ return;
+
+ if (dev->sane.name)
+ free(UNCONST(dev->sane.name));
+ if (dev->sane.vendor)
+ free(UNCONST(dev->sane.vendor));
+ if (dev->sane.model)
+ free(UNCONST(dev->sane.model));
+ if (dev->sane.type)
+ free(UNCONST(dev->sane.type));
+ if (dev->data)
+ free(dev->data);
+ if (dev->decData) {
+ free(dev->decData);
+ dev->decData = NULL;
+ }
+ memset(dev, 0, sizeof(*dev));
+ free(dev);
}
static void
-free_devices (void)
+free_devices(void)
{
- struct device *next;
- struct device *dev;
-
- if (devlist) {
- free (devlist);
- devlist = NULL;
- }
- for (dev = devices_head; dev; dev = next) {
- next = dev->next;
- dev_free (dev);
- }
- devices_head = NULL;
+ struct device *next;
+ struct device *dev;
+
+ if (devlist) {
+ free(devlist);
+ devlist = NULL;
+ }
+ for (dev = devices_head; dev; dev = next) {
+ next = dev->next;
+ dev_free(dev);
+ }
+ devices_head = NULL;
}
static transport *tr_from_devname(SANE_String_Const devname)
{
- if (strncmp("tcp", devname, 3) == 0)
- return &available_transports[TRANSPORT_TCP];
- return &available_transports[TRANSPORT_USB];
+ if (strncmp("tcp", devname, 3) == 0)
+ return &available_transports[TRANSPORT_TCP];
+ return &available_transports[TRANSPORT_USB];
}
static SANE_Status
-list_one_device (SANE_String_Const devname)
+list_one_device(SANE_String_Const devname)
{
- struct device *dev;
- SANE_Status status;
- transport *tr;
-
- DBG (4, "%s: %s\n", __func__, devname);
-
- for (dev = devices_head; dev; dev = dev->next) {
- if (strcmp (dev->sane.name, devname) == 0)
- return SANE_STATUS_GOOD;
- }
-
- tr = tr_from_devname(devname);
-
- dev = calloc (1, sizeof (struct device));
- if (dev == NULL)
- return SANE_STATUS_NO_MEM;
-
- dev->sane.name = strdup (devname);
- dev->io = tr;
- status = tr->dev_open (dev);
- if (status != SANE_STATUS_GOOD) {
- dev_free (dev);
- return status;
- }
-
-/* status = dev_cmd (dev, CMD_ABORT);*/
- status = dev_inquiry (dev);
- tr->dev_close (dev);
- if (status != SANE_STATUS_GOOD) {
- DBG (1, "%s: dev_inquiry(%s): %s\n", __func__,
- dev->sane.name, sane_strstatus (status));
- dev_free (dev);
- return status;
- }
-
- /* good device, add it to list */
- dev->next = devices_head;
- devices_head = dev;
- return SANE_STATUS_GOOD;
+ struct device *dev;
+ SANE_Status status;
+ transport *tr;
+
+ DBG(4, "%s: %s\n", __func__, devname);
+
+ for (dev = devices_head; dev; dev = dev->next) {
+ if (strcmp(dev->sane.name, devname) == 0)
+ return SANE_STATUS_GOOD;
+ }
+
+ tr = tr_from_devname(devname);
+
+ dev = calloc(1, sizeof(struct device));
+ if (dev == NULL)
+ return SANE_STATUS_NO_MEM;
+
+ dev->sane.name = strdup(devname);
+ dev->io = tr;
+ status = tr->dev_open(dev);
+ if (status != SANE_STATUS_GOOD) {
+ dev_free(dev);
+ return status;
+ }
+
+ /* status = dev_cmd (dev, CMD_ABORT);*/
+ status = dev_inquiry(dev);
+ tr->dev_close(dev);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: dev_inquiry(%s): %s\n", __func__,
+ dev->sane.name, sane_strstatus(status));
+ dev_free(dev);
+ return status;
+ }
+
+ /* good device, add it to list */
+ dev->next = devices_head;
+ devices_head = dev;
+ return SANE_STATUS_GOOD;
}
/* SANE API ignores return code of this callback */
static SANE_Status
-list_conf_devices (UNUSED (SANEI_Config * config), const char *devname)
+list_conf_devices(UNUSED(SANEI_Config *config), const char *devname)
{
- return tr_from_devname(devname)->configure_device(devname, list_one_device);
+ return tr_from_devname(devname)->configure_device(devname, list_one_device);
}
SANE_Status
-sane_init (SANE_Int * version_code, SANE_Auth_Callback cb)
+sane_init(SANE_Int *version_code, SANE_Auth_Callback cb)
{
- DBG_INIT ();
- DBG (2, "sane_init: Xerox backend (build %d), version %s null, authorize %s null\n", BACKEND_BUILD,
- (version_code) ? "!=" : "==", (cb) ? "!=" : "==");
+ DBG_INIT();
+ DBG(2, "sane_init: Xerox backend (build %d), version %s null, authorize %s null\n", BACKEND_BUILD,
+ (version_code) ? "!=" : "==", (cb) ? "!=" : "==");
- if (version_code)
- *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BACKEND_BUILD);
+ if (version_code)
+ *version_code = SANE_VERSION_CODE(V_MAJOR, V_MINOR, BACKEND_BUILD);
- sanei_usb_init ();
- return SANE_STATUS_GOOD;
+ sanei_usb_init();
+ return SANE_STATUS_GOOD;
}
void
-sane_exit (void)
+sane_exit(void)
{
- struct device *dev;
+ struct device *dev;
+
+ for (dev = devices_head; dev; dev = dev->next)
+ if (dev->dn != -1)
+ sane_close(dev); /* implies flush */
- for (dev = devices_head; dev; dev = dev->next)
- if (dev->dn != -1)
- sane_close(dev); /* implies flush */
-
- free_devices ();
+ free_devices();
}
SANE_Status
-sane_get_devices (const SANE_Device *** device_list, SANE_Bool local)
+sane_get_devices(const SANE_Device *** device_list, SANE_Bool local)
{
- SANEI_Config config;
- struct device *dev;
- int dev_count;
- int i;
+ SANEI_Config config;
+ struct device *dev;
+ int dev_count;
+ int i;
- DBG (3, "%s: %p, %d\n", __func__, (const void *)device_list, local);
+ DBG(3, "%s: %p, %d\n", __func__, (const void *)device_list, local);
- if (devlist) {
- if (device_list)
- *device_list = devlist;
- return SANE_STATUS_GOOD;
- }
+ if (devlist) {
+ if (device_list)
+ *device_list = devlist;
+ return SANE_STATUS_GOOD;
+ }
- free_devices ();
+ free_devices();
- config.count = 0;
- config.descriptors = NULL;
- config.values = NULL;
- sanei_configure_attach (XEROX_CONFIG_FILE, &config, list_conf_devices);
+ config.count = 0;
+ config.descriptors = NULL;
+ config.values = NULL;
+ sanei_configure_attach(XEROX_CONFIG_FILE, &config, list_conf_devices);
- for (dev_count = 0, dev = devices_head; dev; dev = dev->next)
- dev_count++;
+ for (dev_count = 0, dev = devices_head; dev; dev = dev->next)
+ dev_count++;
- devlist = malloc ((dev_count + 1) * sizeof (*devlist));
- if (!devlist)
- {
- DBG (1, "%s: malloc: no memory\n", __func__);
- return SANE_STATUS_NO_MEM;
+ devlist = malloc((dev_count + 1) * sizeof(*devlist));
+ if (!devlist) {
+ DBG(1, "%s: malloc: no memory\n", __func__);
+ return SANE_STATUS_NO_MEM;
}
- for (i = 0, dev = devices_head; dev; dev = dev->next)
- devlist[i++] = &dev->sane;
- devlist[i++] = NULL;
+ for (i = 0, dev = devices_head; dev; dev = dev->next)
+ devlist[i++] = &dev->sane;
+ devlist[i++] = NULL;
- if (device_list)
- *device_list = devlist;
- return SANE_STATUS_GOOD;
+ if (device_list)
+ *device_list = devlist;
+ return SANE_STATUS_GOOD;
}
void
-sane_close (SANE_Handle h)
+sane_close(SANE_Handle h)
{
- struct device *dev = h;
+ struct device *dev = h;
- if (!dev)
- return;
+ if (!dev)
+ return;
- DBG (3, "%s: %p (%s)\n", __func__, (void *)dev, dev->sane.name);
- dev->io->dev_close(dev);
+ DBG(3, "%s: %p (%s)\n", __func__, (void *)dev, dev->sane.name);
+ dev->io->dev_close(dev);
}
SANE_Status
-sane_open (SANE_String_Const name, SANE_Handle * h)
+sane_open(SANE_String_Const name, SANE_Handle *h)
{
- struct device *dev;
+ struct device *dev;
- DBG (3, "%s: '%s'\n", __func__, name);
+ DBG(3, "%s: '%s'\n", __func__, name);
- if (!devlist)
- sane_get_devices (NULL, SANE_TRUE);
+ if (!devlist)
+ sane_get_devices(NULL, SANE_TRUE);
- if (!name || !*name) {
- /* special case of empty name: open first available device */
- for (dev = devices_head; dev; dev = dev->next) {
- if (dev->dn != -1) {
- if (sane_open (dev->sane.name, h) == SANE_STATUS_GOOD)
- return SANE_STATUS_GOOD;
- }
- }
- } else {
- for (dev = devices_head; dev; dev = dev->next) {
- if (strcmp(name, dev->sane.name) == 0) {
- *h = dev;
- return dev->io->dev_open(dev);
- }
+ if (!name || !*name) {
+ /* special case of empty name: open first available device */
+ for (dev = devices_head; dev; dev = dev->next) {
+ if (dev->dn != -1) {
+ if (sane_open(dev->sane.name, h) == SANE_STATUS_GOOD)
+ return SANE_STATUS_GOOD;
+ }
+ }
+ } else {
+ for (dev = devices_head; dev; dev = dev->next) {
+ if (strcmp(name, dev->sane.name) == 0) {
+ *h = dev;
+ return dev->io->dev_open(dev);
+ }
+ }
}
- }
- return SANE_STATUS_INVAL;
+ return SANE_STATUS_INVAL;
}
SANE_Status
-sane_get_parameters (SANE_Handle h, SANE_Parameters * para)
+sane_get_parameters(SANE_Handle h, SANE_Parameters *para)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p, %p\n", __func__, h, (void *)para);
- if (!para)
- return SANE_STATUS_INVAL;
+ DBG(3, "%s: %p, %p\n", __func__, h, (void *)para);
+ if (!para)
+ return SANE_STATUS_INVAL;
- *para = dev->para;
- return SANE_STATUS_GOOD;
+ *para = dev->para;
+ return SANE_STATUS_GOOD;
}
/* check if image data is ready, and wait if not */
/* 1: image is acquired, 0: error or non_blocking mode */
static int dev_acquire(struct device *dev)
{
- if (!dev_cmd_wait(dev, CMD_READ))
- return dev->state;
-
- dev->state = SANE_STATUS_GOOD;
- dev->vertical = dev->res[0x08] << 8 | dev->res[0x09];
- dev->horizontal = dev->res[0x0a] << 8 | dev->res[0x0b];
- dev->blocklen = dev->res[4] << 24 |
- dev->res[5] << 16 |
- dev->res[6] << 8 |
- dev->res[7];
- dev->final_block = (dev->res[3] == MSG_END_BLOCK)? 1 : 0;
-
- dev->pixels_per_line = dev->horizontal;
- dev->bytes_per_line = dev->horizontal;
-
- if (dev->composition == MODE_RGB24)
- dev->bytes_per_line *= 3;
- else if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE)
- dev->pixels_per_line *= 8;
-
- DBG (4, "acquiring, size per band v: %d, h: %d, %sblock: %d, slack: %d\n",
- dev->vertical, dev->horizontal, dev->final_block? "last " : "",
- dev->blocklen, dev->blocklen - (dev->vertical * dev->bytes_per_line));
-
- if (dev->bytes_per_line > DATASIZE) {
- DBG (1, "%s: unsupported line size: %d bytes > %d\n",
- __func__, dev->bytes_per_line, DATASIZE);
- return ret_cancel(dev, SANE_STATUS_NO_MEM);
- }
-
- dev->reading = 0; /* need to issue READ_IMAGE */
-
- dev->dataindex = 0;
- dev->datalen = 0;
- dev->dataoff = 0;
-
- return 1;
+ if (!dev_cmd_wait(dev, CMD_READ))
+ return dev->state;
+
+ dev->state = SANE_STATUS_GOOD;
+ dev->vertical = dev->res[0x08] << 8 | dev->res[0x09];
+ dev->horizontal = dev->res[0x0a] << 8 | dev->res[0x0b];
+ dev->blocklen = dev->res[4] << 24 |
+ dev->res[5] << 16 |
+ dev->res[6] << 8 |
+ dev->res[7];
+ dev->final_block = (dev->res[3] == MSG_END_BLOCK)? 1 : 0;
+
+ dev->pixels_per_line = dev->horizontal;
+ dev->bytes_per_line = dev->horizontal;
+
+ if (dev->composition == MODE_RGB24)
+ dev->bytes_per_line *= 3;
+ else if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE)
+ dev->pixels_per_line *= 8;
+
+ DBG(4, "acquiring, size per band v: %d, h: %d, %sblock: %d, slack: %d\n",
+ dev->vertical, dev->horizontal, dev->final_block? "last " : "",
+ dev->blocklen, dev->blocklen - (dev->vertical * dev->bytes_per_line));
+
+ if (dev->bytes_per_line > DATASIZE) {
+ DBG(1, "%s: unsupported line size: %d bytes > %d\n",
+ __func__, dev->bytes_per_line, DATASIZE);
+ return ret_cancel(dev, SANE_STATUS_NO_MEM);
+ }
+
+ dev->reading = 0; /* need to issue READ_IMAGE */
+
+ dev->dataindex = 0;
+ dev->datalen = 0;
+ dev->dataoff = 0;
+
+ return 1;
}
static int fill_slack(struct device *dev, SANE_Byte *buf, int maxlen)
{
- const int slack = dev->total_img_size - dev->total_out_size;
- const int havelen = MIN(slack, maxlen);
- int j;
-
- if (havelen <= 0)
- return 0;
- for (j = 0; j < havelen; j++)
- buf[j] = 255;
- return havelen;
+ const int slack = dev->total_img_size - dev->total_out_size;
+ const int havelen = MIN(slack, maxlen);
+ int j;
+
+ if (havelen <= 0)
+ return 0;
+ for (j = 0; j < havelen; j++)
+ buf[j] = 255;
+ return havelen;
}
static int copy_plain_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp)
{
- int j;
- const int linesize = dev->bytes_per_line;
- int k = dev->dataindex;
- *olenp = 0;
- for (j = 0; j < dev->datalen && *olenp < maxlen; j++, k++) {
- const int x = k % linesize;
- const int y = k / linesize;
- if (y >= dev->vertical)
- break; /* slack */
- if (x < dev->para.bytes_per_line &&
- (y + dev->y_off) < dev->para.lines) {
- *buf++ = dev->data[(dev->dataoff + j) & DATAMASK];
- (*olenp)++;
+ int j;
+ const int linesize = dev->bytes_per_line;
+ int k = dev->dataindex;
+ *olenp = 0;
+ for (j = 0; j < dev->datalen && *olenp < maxlen; j++, k++) {
+ const int x = k % linesize;
+ const int y = k / linesize;
+ if (y >= dev->vertical)
+ break; /* slack */
+ if (x < dev->para.bytes_per_line &&
+ (y + dev->y_off) < dev->para.lines) {
+ *buf++ = dev->data[(dev->dataoff + j) & DATAMASK];
+ (*olenp)++;
+ }
}
- }
- dev->dataindex = k;
- return j;
+ dev->dataindex = k;
+ return j;
}
/* return: how much data could be freed from cyclic buffer */
/* convert from RRGGBB to RGBRGB */
-static int copy_mix_bands_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp) {
- int j;
+static int copy_mix_bands_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp)
+{
+ int j;
- const int linesize = dev->bytes_per_line; /* caching real line size */
+ const int linesize = dev->bytes_per_line; /* caching real line size */
- /* line number of the head of input buffer,
- * input buffer is always aligned to whole line */
- const int y_off = dev->dataindex / linesize;
+ /* line number of the head of input buffer,
+ * input buffer is always aligned to whole line */
+ const int y_off = dev->dataindex / linesize;
- int k = dev->dataindex; /* caching current index of input buffer */
+ int k = dev->dataindex; /* caching current index of input buffer */
- /* can only copy as much as full lines we have */
- int havelen = dev->datalen / linesize * linesize - k % linesize;
+ /* can only copy as much as full lines we have */
+ int havelen = dev->datalen / linesize * linesize - k % linesize;
- const int bands = 3;
- *olenp = 0;
+ const int bands = 3;
+ *olenp = 0;
- /* while we have data && they can receive */
- for (j = 0; j < havelen && *olenp < maxlen; j++, k++) {
- const int band = (k % bands) * dev->horizontal;
- const int x = k % linesize / bands;
- const int y = k / linesize - y_off; /* y relative to buffer head */
- const int y_rly = y + y_off + dev->y_off; /* global y */
+ /* while we have data && they can receive */
+ for (j = 0; j < havelen && *olenp < maxlen; j++, k++) {
+ const int band = (k % bands) * dev->horizontal;
+ const int x = k % linesize / bands;
+ const int y = k / linesize - y_off; /* y relative to buffer head */
+ const int y_rly = y + y_off + dev->y_off; /* global y */
- if (x < dev->para.pixels_per_line &&
- y_rly < dev->para.lines) {
- *buf++ = dev->data[(dev->dataoff + band + x + y * linesize) & DATAMASK];
- (*olenp)++;
+ if (x < dev->para.pixels_per_line &&
+ y_rly < dev->para.lines) {
+ *buf++ = dev->data[(dev->dataoff + band + x + y * linesize) & DATAMASK];
+ (*olenp)++;
+ }
}
- }
- dev->dataindex = k;
+ dev->dataindex = k;
- /* how much full lines are finished */
- return (k / linesize - y_off) * linesize;
+ /* how much full lines are finished */
+ return (k / linesize - y_off) * linesize;
}
SANE_Status
-sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * lenp)
+sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp)
{
- SANE_Status status;
- struct device *dev = h;
-
- DBG (3, "%s: %p, %p, %d, %p\n", __func__, h, buf, maxlen, (void *)lenp);
-
- if (lenp)
- *lenp = 0;
- if (!dev)
- return SANE_STATUS_INVAL;
+ SANE_Status status;
+ struct device *dev = h;
+
+ DBG(3, "%s: %p, %p, %d, %p\n", __func__, h, buf, maxlen, (void *)lenp);
+
+ if (lenp)
+ *lenp = 0;
+ if (!dev)
+ return SANE_STATUS_INVAL;
+
+ if (!dev->scanning)
+ return SANE_STATUS_EOF;
+
+ /* if there is no data to read or output from buffer */
+ if (!dev->blocklen && dev->datalen <= PADDING_SIZE) {
+
+ /* copying uncompressed data */
+ if (dev->composition == MODE_RGB24 &&
+ isSupportedDevice(dev) &&
+ dev->decDataSize > 0) {
+ int diff = dev->total_img_size - dev->total_out_size;
+ int bufLen = (diff < maxlen) ? diff : maxlen;
+ if (0 < diff &&
+ 0 < copy_decompress_data(dev, buf, bufLen, lenp)) {
+ dev->total_out_size += *lenp;
+ return SANE_STATUS_GOOD;
+ }
+ }
- if (!dev->scanning)
- return SANE_STATUS_EOF;
-
- /* if there is no data to read or output from buffer */
- if (!dev->blocklen && dev->datalen <= PADDING_SIZE) {
-
- /* copying uncompressed data */
- if ( dev->composition == MODE_RGB24 &&
- isSupportedDevice(dev) &&
- dev->decDataSize > 0) {
- int diff = dev->total_img_size - dev->total_out_size;
- int bufLen = (diff < maxlen) ? diff : maxlen;
- if ( 0 < diff &&
- 0 < copy_decompress_data(dev, buf, bufLen, lenp) ) {
- dev->total_out_size += *lenp;
- return SANE_STATUS_GOOD;
+ /* and we don't need to acquire next block */
+ if (dev->final_block) {
+ int slack = dev->total_img_size - dev->total_out_size;
+
+ /* but we may need to fill slack */
+ if (buf && lenp && slack > 0) {
+ *lenp = fill_slack(dev, buf, maxlen);
+ dev->total_out_size += *lenp;
+ DBG(9, "<> slack: %d, filled: %d, maxlen %d\n",
+ slack, *lenp, maxlen);
+ return SANE_STATUS_GOOD;
+ } else if (slack < 0) {
+ /* this will never happen */
+ DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size);
+ }
+ if (isSupportedDevice(dev) &&
+ dev->composition == MODE_RGB24) {
+ remove(encTmpFileName);
+ }
+ /* that's all */
+ dev_stop(dev);
+ return SANE_STATUS_EOF;
}
- }
- /* and we don't need to acquire next block */
- if (dev->final_block) {
- int slack = dev->total_img_size - dev->total_out_size;
-
- /* but we may need to fill slack */
- if (buf && lenp && slack > 0) {
- *lenp = fill_slack(dev, buf, maxlen);
- dev->total_out_size += *lenp;
- DBG (9, "<> slack: %d, filled: %d, maxlen %d\n",
- slack, *lenp, maxlen);
- return SANE_STATUS_GOOD;
- } else if (slack < 0) {
- /* this will never happen */
- DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size);
- }
- if ( isSupportedDevice(dev) &&
- dev->composition == MODE_RGB24 ) {
- remove(encTmpFileName);
- }
- /* that's all */
- dev_stop(dev);
- return SANE_STATUS_EOF;
+ /* queue next image block */
+ if (!dev_acquire(dev))
+ return dev->state;
}
- /* queue next image block */
- if (!dev_acquire(dev))
- return dev->state;
- }
-
- if (!dev->reading) {
- if (cancelled(dev))
- return dev->state;
- DBG (5, "READ_IMAGE\n");
- if (!dev_cmd(dev, CMD_READ_IMAGE))
- return SANE_STATUS_IO_ERROR;
- dev->reading++;
- dev->ulines += dev->vertical;
- dev->y_off = dev->ulines - dev->vertical;
- dev->total_data_size += dev->blocklen;
- dev->blocks++;
- }
-
- do {
- size_t datalen;
- int clrlen; /* cleared lines len */
- int olen; /* output len */
-
- /* read as much data into the buffer */
- datalen = DATAROOM(dev) & USB_BLOCK_MASK;
- while (datalen && dev->blocklen) {
- SANE_Byte *rbuf = dev->data + DATATAIL(dev);
-
- DBG (9, "<> request len: %lu, [%d, %d; %d]\n",
- (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
- if ((status = dev->io->dev_request(dev, NULL, 0, rbuf, &datalen)) !=
- SANE_STATUS_GOOD)
- return status;
- dev->datalen += datalen;
- dev->blocklen -= datalen;
- DBG (9, "<> got %lu, [%d, %d; %d]\n",
- (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
- if (dev->blocklen < 0)
- return ret_cancel(dev, SANE_STATUS_IO_ERROR);
-
- datalen = DATAROOM(dev) & USB_BLOCK_MASK;
+ if (!dev->reading) {
+ if (cancelled(dev))
+ return dev->state;
+ DBG(5, "READ_IMAGE\n");
+ if (!dev_cmd(dev, CMD_READ_IMAGE))
+ return SANE_STATUS_IO_ERROR;
+ dev->reading++;
+ dev->ulines += dev->vertical;
+ dev->y_off = dev->ulines - dev->vertical;
+ dev->total_data_size += dev->blocklen;
+ dev->blocks++;
}
- if (buf && lenp) { /* read mode */
- /* copy will do minimal of valid data */
- if (dev->para.format == SANE_FRAME_RGB && dev->line_order) {
- if (isSupportedDevice(dev)) {
- clrlen = dump_to_tmp_file(dev);
- /* decompress after reading entire block data*/
- if ( 0 == dev->blocklen ) {
- decompress_tempfile(dev);
- }
- copy_decompress_data(dev, buf, maxlen, &olen);
- } else {
- clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen);
- }
- } else
- clrlen = copy_plain_trim(dev, buf, maxlen, &olen);
-
- dev->datalen -= clrlen;
- dev->dataoff = (dev->dataoff + clrlen) & DATAMASK;
- buf += olen;
- maxlen -= olen;
- *lenp += olen;
- dev->total_out_size += olen;
-
- DBG (9, "<> olen: %d, clrlen: %d, blocklen: %d/%d, maxlen %d (%d %d %d)\n",
- olen, clrlen, dev->blocklen, dev->datalen, maxlen,
- dev->dataindex / dev->bytes_per_line + dev->y_off,
- dev->y_off, dev->para.lines);
-
- /* slack beyond last line */
- if (dev->dataindex / dev->bytes_per_line + dev->y_off >= dev->para.lines) {
- dev->datalen = 0;
- dev->dataoff = 0;
- }
-
- if (!clrlen || maxlen <= 0)
- break;
- } else { /* flush mode */
- dev->datalen = 0;
- dev->dataoff = 0;
- }
+ do {
+ size_t datalen;
+ int clrlen; /* cleared lines len */
+ int olen; /* output len */
+
+ /* read as much data into the buffer */
+ datalen = DATAROOM(dev) & USB_BLOCK_MASK;
+ while (datalen && dev->blocklen) {
+ SANE_Byte *rbuf = dev->data + DATATAIL(dev);
+
+ DBG(9, "<> request len: %lu, [%d, %d; %d]\n",
+ (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
+ if ((status = dev->io->dev_request(dev, NULL, 0, rbuf, &datalen)) !=
+ SANE_STATUS_GOOD)
+ return status;
+ dev->datalen += datalen;
+ dev->blocklen -= datalen;
+ DBG(9, "<> got %lu, [%d, %d; %d]\n",
+ (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
+ if (dev->blocklen < 0)
+ return ret_cancel(dev, SANE_STATUS_IO_ERROR);
+
+ datalen = DATAROOM(dev) & USB_BLOCK_MASK;
+ }
- } while (dev->blocklen);
+ if (buf && lenp) { /* read mode */
+ /* copy will do minimal of valid data */
+ if (dev->para.format == SANE_FRAME_RGB && dev->line_order) {
+ if (isSupportedDevice(dev)) {
+ clrlen = dump_to_tmp_file(dev);
+ /* decompress after reading entire block data*/
+ if (0 == dev->blocklen) {
+ decompress_tempfile(dev);
+ }
+ copy_decompress_data(dev, buf, maxlen, &olen);
+ } else {
+ clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen);
+ }
+ } else
+ clrlen = copy_plain_trim(dev, buf, maxlen, &olen);
+
+ dev->datalen -= clrlen;
+ dev->dataoff = (dev->dataoff + clrlen) & DATAMASK;
+ buf += olen;
+ maxlen -= olen;
+ *lenp += olen;
+ dev->total_out_size += olen;
+
+ DBG(9, "<> olen: %d, clrlen: %d, blocklen: %d/%d, maxlen %d (%d %d %d)\n",
+ olen, clrlen, dev->blocklen, dev->datalen, maxlen,
+ dev->dataindex / dev->bytes_per_line + dev->y_off,
+ dev->y_off, dev->para.lines);
+
+ /* slack beyond last line */
+ if (dev->dataindex / dev->bytes_per_line + dev->y_off >= dev->para.lines) {
+ dev->datalen = 0;
+ dev->dataoff = 0;
+ }
+
+ if (!clrlen || maxlen <= 0)
+ break;
+ } else { /* flush mode */
+ dev->datalen = 0;
+ dev->dataoff = 0;
+ }
- if (lenp)
- DBG (9, " ==> %d\n", *lenp);
+ } while (dev->blocklen);
- return SANE_STATUS_GOOD;
+ if (lenp)
+ DBG(9, " ==> %d\n", *lenp);
+
+ return SANE_STATUS_GOOD;
}
SANE_Status
-sane_start (SANE_Handle h)
+sane_start(SANE_Handle h)
{
- struct device *dev = h;
-
- DBG (3, "%s: %p\n", __func__, h);
-
- dev->cancel = 0;
- dev->scanning = 0;
- dev->total_img_size = 0;
- dev->total_out_size = 0;
- dev->total_data_size = 0;
- dev->blocks = 0;
-
- if (!dev->reserved) {
- if (!dev_cmd_wait(dev, CMD_RESERVE_UNIT))
- return dev->state;
- dev->reserved++;
- }
-
- if (!dev_set_window(dev) ||
- (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
- return dev_stop(dev);
-
- if (!dev_cmd_wait(dev, CMD_OBJECT_POSITION))
- return dev_stop(dev);
-
- if (!dev_cmd(dev, CMD_READ) ||
- (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
- return dev_stop(dev);
-
- dev->scanning = 1;
- dev->final_block = 0;
- dev->blocklen = 0;
- dev->pixels_per_line = 0;
- dev->bytes_per_line = 0;
- dev->ulines = 0;
-
- set_parameters(dev);
-
- if (!dev->data && !(dev->data = malloc(DATASIZE)))
- return ret_cancel(dev, SANE_STATUS_NO_MEM);
-
- if (!dev->decData && !(dev->decData = malloc(POST_DATASIZE)))
- return ret_cancel(dev, SANE_STATUS_NO_MEM);
-
- if (!dev_acquire(dev))
- return dev->state;
-
- /* make sure to have dev->para <= of real size */
- if (dev->para.pixels_per_line > dev->pixels_per_line) {
- dev->para.pixels_per_line = dev->pixels_per_line;
- dev->para.bytes_per_line = dev->pixels_per_line;
- }
-
- if (dev->composition == MODE_RGB24)
- dev->para.bytes_per_line = dev->para.pixels_per_line * 3;
- else if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE) {
- dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
- dev->para.pixels_per_line = dev->para.bytes_per_line * 8;
- } else {
- dev->para.bytes_per_line = dev->para.pixels_per_line;
- }
+ struct device *dev = h;
+
+ DBG(3, "%s: %p\n", __func__, h);
+
+ dev->cancel = 0;
+ dev->scanning = 0;
+ dev->total_img_size = 0;
+ dev->total_out_size = 0;
+ dev->total_data_size = 0;
+ dev->blocks = 0;
- dev->total_img_size = dev->para.bytes_per_line * dev->para.lines;
+ if (!dev->reserved) {
+ if (!dev_cmd_wait(dev, CMD_RESERVE_UNIT))
+ return dev->state;
+ dev->reserved++;
+ }
+
+ if (!dev_set_window(dev) ||
+ (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
+ return dev_stop(dev);
+
+ if (!dev_cmd_wait(dev, CMD_OBJECT_POSITION))
+ return dev_stop(dev);
+
+ if (!dev_cmd(dev, CMD_READ) ||
+ (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
+ return dev_stop(dev);
+
+ dev->scanning = 1;
+ dev->final_block = 0;
+ dev->blocklen = 0;
+ dev->pixels_per_line = 0;
+ dev->bytes_per_line = 0;
+ dev->ulines = 0;
+
+ set_parameters(dev);
+
+ if (!dev->data && !(dev->data = malloc(DATASIZE)))
+ return ret_cancel(dev, SANE_STATUS_NO_MEM);
+
+ if (!dev->decData && !(dev->decData = malloc(POST_DATASIZE)))
+ return ret_cancel(dev, SANE_STATUS_NO_MEM);
- if ( isSupportedDevice(dev) &&
- dev->composition == MODE_RGB24 ) {
- remove(encTmpFileName);
- }
- dev->currentDecDataIndex = 0;
+ if (!dev_acquire(dev))
+ return dev->state;
+
+ /* make sure to have dev->para <= of real size */
+ if (dev->para.pixels_per_line > dev->pixels_per_line) {
+ dev->para.pixels_per_line = dev->pixels_per_line;
+ dev->para.bytes_per_line = dev->pixels_per_line;
+ }
- return SANE_STATUS_GOOD;
+ if (dev->composition == MODE_RGB24)
+ dev->para.bytes_per_line = dev->para.pixels_per_line * 3;
+ else if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE) {
+ dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
+ dev->para.pixels_per_line = dev->para.bytes_per_line * 8;
+ } else {
+ dev->para.bytes_per_line = dev->para.pixels_per_line;
+ }
+
+ dev->total_img_size = dev->para.bytes_per_line * dev->para.lines;
+
+ if (isSupportedDevice(dev) &&
+ dev->composition == MODE_RGB24) {
+ int fd;
+ remove(encTmpFileName);
+
+ /* Precreate temporary file in exclusive mode. */
+ fd = open(encTmpFileName, O_CREAT|O_EXCL, 0600);
+ if (fd == -1) {
+ DBG(3, "%s: %p, can't create temporary file %s: %s\n", __func__,
+ (void *)dev, encTmpFileName, strerror(errno));
+ return ret_cancel(dev, SANE_STATUS_ACCESS_DENIED);
+ }
+ close(fd);
+ }
+ dev->currentDecDataIndex = 0;
+
+ return SANE_STATUS_GOOD;
}
-SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking)
+SANE_Status sane_set_io_mode(SANE_Handle h, SANE_Bool non_blocking)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p, %d\n", __func__, h, non_blocking);
+ DBG(3, "%s: %p, %d\n", __func__, h, non_blocking);
- if (non_blocking)
- return SANE_STATUS_UNSUPPORTED;
+ if (non_blocking)
+ return SANE_STATUS_UNSUPPORTED;
- dev->non_blocking = non_blocking;
- return SANE_STATUS_GOOD;
+ dev->non_blocking = non_blocking;
+ return SANE_STATUS_GOOD;
}
-SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp)
+SANE_Status sane_get_select_fd(SANE_Handle h, SANE_Int *fdp)
{
- DBG (3, "%s: %p, %p\n", __func__, h, (void *)fdp);
- /* supporting of this will require thread creation */
- return SANE_STATUS_UNSUPPORTED;
+ DBG(3, "%s: %p, %p\n", __func__, h, (void *)fdp);
+ /* supporting of this will require thread creation */
+ return SANE_STATUS_UNSUPPORTED;
}
-void sane_cancel (SANE_Handle h)
+void sane_cancel(SANE_Handle h)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p\n", __func__, h);
- dev->cancel = 1;
+ DBG(3, "%s: %p\n", __func__, h);
+ dev->cancel = 1;
}
/* xerox_mfp.c */
diff --git a/backend/xerox_mfp.h b/backend/xerox_mfp.h
index 2cec992..3d93f06 100644
--- a/backend/xerox_mfp.h
+++ b/backend/xerox_mfp.h
@@ -1,9 +1,12 @@
/*
- * SANE backend for Xerox Phaser 3200MFP
- * Copyright 2008 ABC <abc@telekom.ru>
+ * SANE backend for Xerox Phaser 3200MFP et al.
+ * Copyright 2008-2016 ABC <abc@telekom.ru>
*
- * Network scanners support
- * Copyright 2010 Alexander Kuznetsov <acca(at)cpan.org>
+ * Network Scanners Support
+ * Copyright 2010 Alexander Kuznetsov <acca(at)cpan.org>
+ *
+ * Color scanning on Samsung M2870 model and Xerox Cognac 3215 & 3225
+ * models by Laxmeesh Onkar Markod <m.laxmeesh@samsung.com>
*
* This program is licensed under GPL + SANE exception.
* More info at http://www.sane-project.org/license.html
@@ -29,135 +32,136 @@
#define SWAP_Word(x, y) { SANE_Word z = x; x = y; y = z; }
enum options {
- OPT_NUMOPTIONS,
- OPT_GROUP_STD,
- OPT_RESOLUTION, /* dpi*/
- OPT_MODE, /* color */
- OPT_THRESHOLD, /* brightness */
- OPT_SOURCE, /* affects max window size */
- OPT_GROUP_GEO,
- OPT_SCAN_TL_X, /* for (OPT_SCAN_TL_X to OPT_SCAN_BR_Y) */
- OPT_SCAN_TL_Y,
- OPT_SCAN_BR_X,
- OPT_SCAN_BR_Y,
- NUM_OPTIONS
+ OPT_NUMOPTIONS,
+ OPT_GROUP_STD,
+ OPT_RESOLUTION, /* dpi*/
+ OPT_MODE, /* color */
+ OPT_THRESHOLD, /* brightness */
+ OPT_SOURCE, /* affects max window size */
+ OPT_GROUP_GEO,
+ OPT_SCAN_TL_X, /* for (OPT_SCAN_TL_X to OPT_SCAN_BR_Y) */
+ OPT_SCAN_TL_Y,
+ OPT_SCAN_BR_X,
+ OPT_SCAN_BR_Y,
+ NUM_OPTIONS
};
typedef struct transport transport;
struct device {
- struct device *next;
- SANE_Device sane;
- int dn; /* usb file descriptor */
- SANE_Byte res[1024]; /* buffer for responses */
- size_t reslen; /* response len */
- SANE_Option_Descriptor opt[NUM_OPTIONS];
- Option_Value val[NUM_OPTIONS];
- SANE_Parameters para;
- SANE_Bool non_blocking;
- int scanning; /* scanning is started */
- int cancel; /* cancel flag */
- int state; /* current state */
- int reserved; /* CMD_RESERVE_UNIT */
- int reading; /* READ_IMAGE is sent */
-
- SANE_Byte *data; /* postprocessing cyclic buffer 64k */
- int datalen; /* how data in buffer */
- int dataoff; /* offset of data */
- int dataindex; /* sequental number */
+ struct device *next;
+ SANE_Device sane;
+ int dn; /* usb file descriptor */
+ SANE_Byte res[1024]; /* buffer for responses */
+ size_t reslen; /* response len */
+ SANE_Option_Descriptor opt[NUM_OPTIONS];
+ Option_Value val[NUM_OPTIONS];
+ SANE_Parameters para;
+ SANE_Bool non_blocking;
+ int scanning; /* scanning is started */
+ int cancel; /* cancel flag */
+ int state; /* current state */
+ int reserved; /* CMD_RESERVE_UNIT */
+ int reading; /* READ_IMAGE is sent */
+
+ SANE_Byte *data; /* postprocessing cyclic buffer 64k */
+ int datalen; /* how data in buffer */
+ int dataoff; /* offset of data */
+ int dataindex; /* sequental number */
#define DATAMASK 0xffff /* mask of data buffer */
#define DATASIZE (DATAMASK + 1) /* size of data buffer */
- /* 64K will be enough to hold whole line of 2400 dpi of 23cm */
+ /* 64K will be enough to hold whole line of 2400 dpi of 23cm */
#define DATATAIL(dev) ((dev->dataoff + dev->datalen) & DATAMASK)
#define DATAROOM(dev) dataroom(dev)
#define POST_DATASIZE 0xFFFFFF
- SANE_Byte *decData;
- int decDataSize;
- int currentDecDataIndex;
- /* data from CMD_INQUIRY: */
- int resolutions; /* supported resolution bitmask */
- int compositions; /* supported image compositions bitmask */
- int max_len; /* effective max len for current doc source */
- int max_win_width;
- int max_win_len;
- int max_len_adf;
- int max_len_fb;
- int line_order; /* if need post processing */
- SANE_Word dpi_list[30]; /* allowed resolutions */
- int doc_loaded;
-
- SANE_Range win_x_range;
- SANE_Range win_y_range;
-
- /* CMD_SET_WINDOW parameters we set: */
- int win_width; /* in 1200dpi points */
- int win_len;
- double win_off_x; /* in inches (byte.byte) */
- double win_off_y;
- int resolution; /* dpi indexed values */
- int composition; /* MODE_ */
- int doc_source; /* document source */
- int threshold; /* brightness */
- int compressionTypes;
-
- /* CMD_READ data. It is per block only, image could be in many blocks */
- int blocklen; /* image data block len (padding incl.) */
- int vertical; /* lines in block (padded) */
- int horizontal; /* b/w: bytes, gray/color: pixels (padded) */
- int final_block;
- int pixels_per_line;
- int bytes_per_line;
- int ulines; /* up to this block including */
- int y_off; /* up to this block excluding*/
- int blocks;
-
- /* stat */
- int total_img_size; /* predicted image size */
- int total_out_size; /* total we sent to user */
- int total_data_size; /* total of what scanner sent us */
-
- /* transport to use */
- transport *io;
+ SANE_Byte *decData;
+ int decDataSize;
+ int currentDecDataIndex;
+ /* data from CMD_INQUIRY: */
+ int resolutions; /* supported resolution bitmask */
+ int compositions; /* supported image compositions bitmask */
+ int max_len; /* effective max len for current doc source */
+ int max_win_width;
+ int max_win_len;
+ int max_len_adf;
+ int max_len_fb;
+ int line_order; /* if need post processing */
+ SANE_Word dpi_list[30]; /* allowed resolutions */
+ int doc_loaded;
+
+ SANE_Range win_x_range;
+ SANE_Range win_y_range;
+
+ /* CMD_SET_WINDOW parameters we set: */
+ int win_width; /* in 1200dpi points */
+ int win_len;
+ double win_off_x; /* in inches (byte.byte) */
+ double win_off_y;
+ int resolution; /* dpi indexed values */
+ int composition; /* MODE_ */
+ int doc_source; /* document source */
+ int threshold; /* brightness */
+ int compressionTypes;
+
+ /* CMD_READ data. It is per block only, image could be in many blocks */
+ int blocklen; /* image data block len (padding incl.) */
+ int vertical; /* lines in block (padded) */
+ int horizontal; /* b/w: bytes, gray/color: pixels (padded) */
+ int final_block;
+ int pixels_per_line;
+ int bytes_per_line;
+ int ulines; /* up to this block including */
+ int y_off; /* up to this block excluding*/
+ int blocks;
+
+ /* stat */
+ int total_img_size; /* predicted image size */
+ int total_out_size; /* total we sent to user */
+ int total_data_size; /* total of what scanner sent us */
+
+ /* transport to use */
+ transport *io;
};
/* Transport abstract layer */
struct transport {
- char* ttype;
-
- int (*dev_request) (struct device *dev,
- SANE_Byte *cmd, size_t cmdlen,
- SANE_Byte *resp, size_t *resplen);
- SANE_Status (*dev_open) (struct device *dev);
- void (*dev_close) (struct device *dev);
- SANE_Status (*configure_device) (const char *devname, SANE_Status (*cb)(SANE_String_Const devname));
+ char *ttype;
+
+ int (*dev_request)(struct device *dev,
+ SANE_Byte *cmd, size_t cmdlen,
+ SANE_Byte *resp, size_t *resplen);
+ SANE_Status(*dev_open)(struct device *dev);
+ void (*dev_close)(struct device *dev);
+ SANE_Status(*configure_device)(const char *devname, SANE_Status(*cb)(SANE_String_Const devname));
};
/* USB transport */
-int usb_dev_request (struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen);
-SANE_Status usb_dev_open (struct device *dev);
-void usb_dev_close (struct device *dev);
-SANE_Status usb_configure_device (const char *devname, SANE_Status (*cb)(SANE_String_Const devname));
+int usb_dev_request(struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen);
+SANE_Status usb_dev_open(struct device *dev);
+void usb_dev_close(struct device *dev);
+SANE_Status usb_configure_device(const char *devname, SANE_Status(*cb)(SANE_String_Const devname));
/* TCP unicast */
-int tcp_dev_request (struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen);
-SANE_Status tcp_dev_open (struct device *dev);
-void tcp_dev_close (struct device *dev);
-SANE_Status tcp_configure_device (const char *devname, SANE_Status (*cb)(SANE_String_Const devname));
+int tcp_dev_request(struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen);
+SANE_Status tcp_dev_open(struct device *dev);
+void tcp_dev_close(struct device *dev);
+SANE_Status tcp_configure_device(const char *devname, SANE_Status(*cb)(SANE_String_Const devname));
/* device wants transfer buffer to be multiple of 512 */
#define USB_BLOCK_SIZE 512
#define USB_BLOCK_MASK ~(USB_BLOCK_SIZE - 1)
-static inline int dataroom(struct device *dev) {
- int tail = DATATAIL(dev);
- if (tail < dev->dataoff)
- return dev->dataoff - tail;
- else if (dev->datalen == DATASIZE) {
- return 0;
- } else
- return DATASIZE - tail;
+static inline int dataroom(struct device *dev)
+{
+ int tail = DATATAIL(dev);
+ if (tail < dev->dataoff)
+ return dev->dataoff - tail;
+ else if (dev->datalen == DATASIZE) {
+ return 0;
+ } else
+ return DATASIZE - tail;
}
/* Functions from original xerox_mfp.c, used in -usb.c and -tcp.c */
diff --git a/configure b/configure
index a0add3a..623864a 100755
--- a/configure
+++ b/configure
@@ -670,6 +670,8 @@ COMPILE_SANED_TRUE
configdir
locksanedir
SCSI_LIBS
+have_usblib_FALSE
+have_usblib_TRUE
USB_LIBS
USB_CFLAGS
SYSTEMD_LIBS
@@ -20128,6 +20130,14 @@ if test xyes = "x$with_usb" && test xyes != "x$have_usb"; then :
as_fn_error $? "USB support requested but required libraries not found." "$LINENO" 5
fi
+ if test x != "x$USB_LIBS"; then
+ have_usblib_TRUE=
+ have_usblib_FALSE='#'
+else
+ have_usblib_TRUE='#'
+ have_usblib_FALSE=
+fi
+
@@ -21504,6 +21514,10 @@ Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${have_usblib_TRUE}" && test -z "${have_usblib_FALSE}"; then
+ as_fn_error $? "conditional \"have_usblib\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${COMPILE_SANED_TRUE}" && test -z "${COMPILE_SANED_FALSE}"; then
as_fn_error $? "conditional \"COMPILE_SANED\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/configure.ac b/configure.ac
index 9beb471..bab215f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -426,7 +426,7 @@ AS_IF([test xno != "x$with_usb"],
AS_IF([test xyes = "x$with_usb" && test xyes != "x$have_usb"],
[AC_MSG_ERROR([USB support requested but required libraries not found.])
])
-dnl AM_CONDITIONAL([have_usb], [test x != "x$USB_LIBS])
+AM_CONDITIONAL([have_usblib], [test x != "x$USB_LIBS"])
dnl ************
dnl SCSI Support
@@ -732,7 +732,7 @@ AC_ARG_WITH(api-spec,
[with_api_spec=check])
dnl Test for all tools that may be involved. These tests are fast and
dnl running them allows for the Makefile targets to be formulated such
-dnl that you non-requested formats can be made using a one-off without
+dnl that any non-requested formats can be made using a one-off without
dnl the need to reconfigure.
AC_PATH_PROG(MAKEINDEX, makeindex, no)
AC_PATH_PROG(DVIPS, dvips, no)
diff --git a/doc/descriptions/pixma.desc b/doc/descriptions/pixma.desc
index 0c0be5d..9113a83 100644
--- a/doc/descriptions/pixma.desc
+++ b/doc/descriptions/pixma.desc
@@ -11,7 +11,7 @@
; See doc/descriptions.txt for details.
:backend "pixma" ; name of backend
-:version "0.17.30" ; version of backend (or "unmaintained")
+:version "0.17.34" ; version of backend (or "unmaintained")
:manpage "sane-pixma" ; name of manpage (if it exists)
;:comment "Devices marked as experimantal are disabled by default. See the manual page for how to enable them."
@@ -100,6 +100,12 @@
:status :complete
:comment "All resolutions supported (up to 600DPI)."
+:model "PIXMA MG3000 Series"
+:interface "USB WiFi"
+:usbid "0x04a9" "0x180b"
+:status :untested
+:comment "Testers needed!"
+
:model "PIXMA MG3100 Series"
:interface "USB WiFi"
:usbid "0x04a9" "0x1752"
diff --git a/doc/sane-avision.man b/doc/sane-avision.man
index 299bb72..6a991b6 100644
--- a/doc/sane-avision.man
+++ b/doc/sane-avision.man
@@ -36,6 +36,7 @@ a hash mark (#) are ignored. A sample configuration file is shown below:
\
option force\-a4
option force\-a3
+ option skip\-adf
option disable\-gamma\-table
option disable\-calibration
\
@@ -61,6 +62,15 @@ known to return bogus data are marked in the backend
so if you need this option please report this to the
backend maintainer. USE WITH CARE!
.TP
+skip\-adf:
+Forces the backend to ignore an inconsistent ADF
+status returned by the scanner (ADF not present, but
+ADF model number non-zero). Without this option, the
+backend will make several attempts to reset the ADF
+and retry the query in this situation, and will fail
+with a "not supported" error if the ADF still doesn't
+respond.
+.TP
disable\-gamma\-table:
Disables the usage of the scanner's gamma-table. You
might try this if your scans hang or only produces
diff --git a/doc/sane-pixma.man b/doc/sane-pixma.man
index 784d5a6..c8e0348 100644
--- a/doc/sane-pixma.man
+++ b/doc/sane-pixma.man
@@ -1,4 +1,4 @@
-.TH "sane\-pixma" "5" "12 Apr 2016" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
+.TH "sane\-pixma" "5" "08 Oct 2016" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.IX sane\-pixma
.SH NAME
sane\-pixma \- SANE backend for Canon Multi-Function Printers and CanoScan Scanners
@@ -85,7 +85,7 @@ Feedback in the sane\-devel mailing list welcome.
.RS
PIXMA E400, E460, E480, E500, E510, E560, E600, E610
.br
-PIXMA MG4100, MG5400, MG6500, MG6600, MG6800, MG6900
+PIXMA MG3000, MG4100, MG5400, MG6500, MG6600, MG6800, MG6900
.br
PIXMA MG8100
.br
diff --git a/doc/sane-xerox_mfp.man b/doc/sane-xerox_mfp.man
index 0f896ce..0ffa3e8 100644
--- a/doc/sane-xerox_mfp.man
+++ b/doc/sane-xerox_mfp.man
@@ -1,47 +1,20 @@
.TH sane\-xerox_mfp 5 "15 Dec 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.IX sane\-xerox_mfp
.SH NAME
-sane\-xerox_mfp \- SANE backend for Xerox Phaser 3200MFP device
+sane\-xerox_mfp \- SANE backend for Xerox Phaser 3200MFP device et al.
.SH DESCRIPTION
The
.B sane\-xerox_mfp
library implements a SANE (Scanner Access Now Easy) backend that provides
-access to the following USB and network multifunction-peripheral:
-.PP
-.RS
-Phaser 3200MFP
-.br
-Dell MFP Laser Printer 1815dn
-.br
-Xerox Phaser 6110MFP
-.br
-Samsung CLX-3170fn & CLX-3175FW
-.br
-Samsung SCX-4200
-.br
-Samsung SCX-4300
-.br
-Samsung SCX-4500
-.br
-Samsung SCX-4500W
-.br
-Samsung SCX4725-FN
-.br
-Xerox WorkCentre 3119 Series
-.RE
-.PP
-If you own a scanner other than the ones listed above that works with this
-backend, please let us know this by sending the scanner's exact model name and
-the USB vendor and device ids (e.g. from
-.IR /proc/bus/usb/devices ,
-.I sane\-find\-scanner
-or syslog) to us. Even if the scanner's name is only slightly different from
-the models mentioned above, please let us know.
+access to several Samsung-based Samsung, Xerox, and Dell scanners.
+Please see full list of supported devices at
+http://www.sane\-project.org/sane\-supported\-devices.html
+
.SH CONFIGURATION
.I @CONFIGDIR@/xerox_mfp.conf
USB scanners do not need any configuration.
-For SCX-4500W in network mode you need to specify
+For SCX\-4500W in network mode you need to specify
.PP
.RS
.B tcp host_address [port]
@@ -70,14 +43,24 @@ debug levels increase the verbosity of the output.
Example:
export SANE_DEBUG_XEROX_MFP=4
-.SH AUTHOR
-Alex Belkin <abc@telekom.ru>
-Samsung SCX-4500W scan over network support
-Alexander Kuznetsov <acca(at)cpan.org>
-.SH BUGS:
+.SH LIMITATIONS
Multicast autoconfiguration for LAN scanners is not implemented yet. IPv6 addressing never been tested.
+.SH BUGS AND SUPPORT
+If you have found a bug or need support please follow open\-source way of acquiring support via
+mail\-lists http://www.sane\-project.org/mailing\-lists.html or SANE bug tracker
+http://www.sane\-project.org/bugs.html
+
+.SH AUTHORS
+Alex Belkin <abc@telekom.ru>
+.br
+Samsung SCX\-4500W scan over network support by
+Alexander Kuznetsov <acca(at)cpan.org>
+.br
+Color scanning on Samsung M2870 model and Xerox Cognac 3215 & 3225 models by
+Laxmeesh Onkar Markod <m.laxmeesh@samsung.com>
+
.SH "SEE ALSO"
.BR sane (7),
.BR sane\-usb (5)
diff --git a/doc/sane.man b/doc/sane.man
index 4fad9a9..3eadf42 100644
--- a/doc/sane.man
+++ b/doc/sane.man
@@ -524,6 +524,12 @@ The sane\-umax1220u backend supports the UMAX Astra 1220U (USB) flatbed scanner
(and also the UMAX Astra 2000U, sort of). See
.BR sane\-umax1220u (5)
for details.
+.TP
+.B xerox_mfp
+The sane\-xerox_mfp backend supports multiple Samsung-based Samsung, Xerox, and Dell
+scanners. See
+.BR sane\-xerox_mfp (5)
+for details.
.PP
Also, have a look at the backend information page at
.I http://www.sane\-project.org/sane\-supported\-devices.html
@@ -917,7 +923,8 @@ for details).
.BR sane\-umax (5),
.BR sane\-umax_pp (5),
.BR sane\-usb (5),
-.BR sane\-v4l (5)
+.BR sane\-v4l (5),
+.BR sane\-xerox_mfp (5)
.SH AUTHOR
David Mosberger-Tang and many many more (see
diff --git a/sanei/sanei_pp.c b/sanei/sanei_pp.c
index 6146d1e..8e68f25 100644
--- a/sanei/sanei_pp.c
+++ b/sanei/sanei_pp.c
@@ -126,9 +126,7 @@ inb( u_long port )
#elif defined(HAVE_LIBIEEE1284)
# include <ieee1284.h>
#else
-# if defined(__GNUC__)
-# warning "No I/O support for this architecture!"
-# endif
+# pragma message "No I/O support for this architecture!"
# define IO_SUPPORT_MISSING
#endif
diff --git a/sanei/sanei_usb.c b/sanei/sanei_usb.c
index ea39e36..61d5cb8 100644
--- a/sanei/sanei_usb.c
+++ b/sanei/sanei_usb.c
@@ -2174,7 +2174,7 @@ sanei_usb_close (SANE_Int dn)
}
void
-sanei_usb_set_timeout (SANE_Int timeout)
+sanei_usb_set_timeout (SANE_Int __sane_unused__ timeout)
{
#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB)
libusb_timeout = timeout;
@@ -2186,7 +2186,6 @@ sanei_usb_set_timeout (SANE_Int timeout)
SANE_Status
sanei_usb_clear_halt (SANE_Int dn)
{
- int ret;
char *env;
int workaround = 0;
@@ -2205,6 +2204,7 @@ sanei_usb_clear_halt (SANE_Int dn)
}
#ifdef HAVE_LIBUSB_LEGACY
+ int ret;
/* This call seems to be required by Linux xhci driver
* even though it should be a no-op. Without it, the
@@ -2228,6 +2228,7 @@ sanei_usb_clear_halt (SANE_Int dn)
}
#elif defined(HAVE_LIBUSB)
+ int ret;
/* This call seems to be required by Linux xhci driver
* even though it should be a no-op. Without it, the
@@ -2257,7 +2258,7 @@ sanei_usb_clear_halt (SANE_Int dn)
}
SANE_Status
-sanei_usb_reset (SANE_Int dn)
+sanei_usb_reset (SANE_Int __sane_unused__ dn)
{
#ifdef HAVE_LIBUSB_LEGACY
int ret;
@@ -3129,7 +3130,9 @@ sanei_usb_set_altinterface (SANE_Int dn, SANE_Int alternate)
}
extern SANE_Status
-sanei_usb_get_descriptor( SANE_Int dn, struct sanei_usb_dev_descriptor *desc )
+sanei_usb_get_descriptor( SANE_Int dn,
+ struct sanei_usb_dev_descriptor __sane_unused__
+ *desc )
{
if (dn >= device_number || dn < 0)
{
diff --git a/tools/Makefile.am b/tools/Makefile.am
index dee0ec8..70c87ee 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -34,7 +34,10 @@ CLEANFILES = $(bin_SCRIPTS) $(dist_noinst_SCRIPTS)
EXTRA_DIST = check-po.awk libtool-get-dll-ext mustek600iin-off.c \
RenSaneDlls.cmd README xerox
-sane_find_scanner_SOURCES = sane-find-scanner.c check-usb-chip.c
+sane_find_scanner_SOURCES = sane-find-scanner.c
+if have_usblib
+sane_find_scanner_SOURCES += check-usb-chip.c
+endif
sane_find_scanner_LDADD = ../sanei/libsanei.la ../lib/liblib.la \
$(USB_LIBS) $(IEEE1284_LIBS) $(SCSI_LIBS) \
../backend/sane_strstatus.lo
diff --git a/tools/Makefile.in b/tools/Makefile.in
index a3ef3b8..77e9d72 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -85,6 +85,7 @@ bin_PROGRAMS = sane-find-scanner$(EXEEXT) gamma4scanimage$(EXEEXT) \
noinst_PROGRAMS = sane-desc$(EXEEXT) $(am__EXEEXT_2)
@INSTALL_UMAX_PP_TOOLS_TRUE@am__append_1 = umax_pp
@INSTALL_UMAX_PP_TOOLS_FALSE@am__append_2 = umax_pp
+@have_usblib_TRUE@am__append_3 = check-usb-chip.c
subdir = tools
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/mkinstalldirs $(srcdir)/sane-config.in \
@@ -122,8 +123,11 @@ am__v_lt_1 =
am_sane_desc_OBJECTS = sane-desc.$(OBJEXT)
sane_desc_OBJECTS = $(am_sane_desc_OBJECTS)
sane_desc_DEPENDENCIES = ../sanei/libsanei.la ../lib/liblib.la
+am__sane_find_scanner_SOURCES_DIST = sane-find-scanner.c \
+ check-usb-chip.c
+@have_usblib_TRUE@am__objects_1 = check-usb-chip.$(OBJEXT)
am_sane_find_scanner_OBJECTS = sane-find-scanner.$(OBJEXT) \
- check-usb-chip.$(OBJEXT)
+ $(am__objects_1)
sane_find_scanner_OBJECTS = $(am_sane_find_scanner_OBJECTS)
sane_find_scanner_DEPENDENCIES = ../sanei/libsanei.la ../lib/liblib.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
@@ -197,7 +201,7 @@ am__v_CCLD_1 =
SOURCES = $(gamma4scanimage_SOURCES) $(sane_desc_SOURCES) \
$(sane_find_scanner_SOURCES) $(umax_pp_SOURCES)
DIST_SOURCES = $(gamma4scanimage_SOURCES) $(sane_desc_SOURCES) \
- $(sane_find_scanner_SOURCES) $(umax_pp_SOURCES)
+ $(am__sane_find_scanner_SOURCES_DIST) $(umax_pp_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -434,7 +438,7 @@ EXTRA_DIST = check-po.awk libtool-get-dll-ext mustek600iin-off.c \
RenSaneDlls.cmd README xerox hotplug/README \
hotplug/libusbscanner hotplug-ng/README \
hotplug-ng/libsane.hotplug openbsd/attach openbsd/detach
-sane_find_scanner_SOURCES = sane-find-scanner.c check-usb-chip.c
+sane_find_scanner_SOURCES = sane-find-scanner.c $(am__append_3)
sane_find_scanner_LDADD = ../sanei/libsanei.la ../lib/liblib.la \
$(USB_LIBS) $(IEEE1284_LIBS) $(SCSI_LIBS) \
../backend/sane_strstatus.lo