From 842c98d204167bfe6e72fcda4e76de8386cb0ba6 Mon Sep 17 00:00:00 2001 From: Alex Belkin Date: Thu, 30 Sep 2010 15:11:56 +0400 Subject: [PATCH] Added Samsung SCX-4500W scan over network support for xerox_mfp backend (by Alexander Kuznetsov). autoconf and automake reconfigure. --- Makefile.in | 1 + backend/Makefile.am | 4 +- backend/Makefile.in | 38 +++++-- backend/xerox_mfp-tcp.c | 178 ++++++++++++++++++++++++++++++++ backend/xerox_mfp-usb.c | 112 ++++++++++++++++++++ backend/xerox_mfp.c | 124 +++++++--------------- backend/xerox_mfp.conf.in | 7 ++ backend/xerox_mfp.h | 41 +++++++- doc/Makefile.in | 1 + doc/descriptions/xerox_mfp.desc | 4 + doc/sane-xerox_mfp.man | 53 ++++++++-- frontend/Makefile.in | 1 + include/Makefile.in | 1 + japi/Makefile.in | 1 + lib/Makefile.in | 1 + po/Makefile.in | 1 + sanei/Makefile.in | 1 + testsuite/Makefile.in | 1 + tools/Makefile.in | 1 + 19 files changed, 462 insertions(+), 109 deletions(-) create mode 100644 backend/xerox_mfp-tcp.c create mode 100644 backend/xerox_mfp-usb.c diff --git a/Makefile.in b/Makefile.in index e014f12cc..3f52b80a5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -210,6 +210,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/backend/Makefile.am b/backend/Makefile.am index 8eb16cc0d..9d9149a8a 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -1046,13 +1046,13 @@ libsane_v4l_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_v4l_la_LIBADD = $(COMMON_LIBS) libv4l.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(LIBV4L_LIBS) EXTRA_DIST += v4l.conf.in -libxerox_mfp_la_SOURCES = xerox_mfp.c xerox_mfp.h +libxerox_mfp_la_SOURCES = xerox_mfp.c xerox_mfp-usb.c xerox_mfp-tcp.c xerox_mfp.h libxerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) -libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) +libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += xerox_mfp.conf.in libdll_la_SOURCES = dll.c diff --git a/backend/Makefile.in b/backend/Makefile.in index 8506a6cf5..38df4a813 100644 --- a/backend/Makefile.in +++ b/backend/Makefile.in @@ -572,9 +572,9 @@ libsane_fujitsu_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libsane_fujitsu_la_LDFLAGS) $(LDFLAGS) -o $@ libsane_genesys_la_DEPENDENCIES = $(COMMON_LIBS) libgenesys.la \ - ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ - ../sanei/sanei_config.lo sane_strstatus.lo \ - ../sanei/sanei_usb.lo ../sanei/sanei_magic.lo $(am__DEPENDENCIES_1) \ + ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo \ + ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo \ + sane_strstatus.lo ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_genesys_la_OBJECTS = libsane_genesys_la-genesys-s.lo libsane_genesys_la_OBJECTS = $(nodist_libsane_genesys_la_OBJECTS) @@ -1189,8 +1189,9 @@ libsane_v4l_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ libsane_xerox_mfp_la_DEPENDENCIES = $(COMMON_LIBS) libxerox_mfp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ - ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) nodist_libsane_xerox_mfp_la_OBJECTS = \ libsane_xerox_mfp_la-xerox_mfp-s.lo libsane_xerox_mfp_la_OBJECTS = $(nodist_libsane_xerox_mfp_la_OBJECTS) @@ -1258,7 +1259,9 @@ libv4l_la_LIBADD = am_libv4l_la_OBJECTS = libv4l_la-v4l.lo libv4l_la_OBJECTS = $(am_libv4l_la_OBJECTS) libxerox_mfp_la_LIBADD = -am_libxerox_mfp_la_OBJECTS = libxerox_mfp_la-xerox_mfp.lo +am_libxerox_mfp_la_OBJECTS = libxerox_mfp_la-xerox_mfp.lo \ + libxerox_mfp_la-xerox_mfp-usb.lo \ + libxerox_mfp_la-xerox_mfp-tcp.lo libxerox_mfp_la_OBJECTS = $(am_libxerox_mfp_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -1532,6 +1535,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ @@ -1998,7 +2002,7 @@ libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys nodist_libsane_genesys_la_SOURCES = genesys-s.c libsane_genesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys libsane_genesys_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) -libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) +libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libgphoto2_i_la_SOURCES = gphoto2.c gphoto2.h libgphoto2_i_la_CPPFLAGS = $(AM_CPPFLAGS) @GPHOTO2_CPPFLAGS@ -DBACKEND_NAME=gphoto2 nodist_libsane_gphoto2_la_SOURCES = gphoto2-s.c @@ -2345,12 +2349,12 @@ nodist_libsane_v4l_la_SOURCES = v4l-s.c libsane_v4l_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=v4l libsane_v4l_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_v4l_la_LIBADD = $(COMMON_LIBS) libv4l.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(LIBV4L_LIBS) -libxerox_mfp_la_SOURCES = xerox_mfp.c xerox_mfp.h +libxerox_mfp_la_SOURCES = xerox_mfp.c xerox_mfp-usb.c xerox_mfp-tcp.c xerox_mfp.h libxerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) -libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) +libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libdll_la_SOURCES = dll.c BUILT_SOURCES = dll-preload.h libdll_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll @@ -3038,6 +3042,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libumax_pp_la-umax_pp_low.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libumax_pp_la-umax_pp_mid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libv4l_la-v4l.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxerox_mfp_la-xerox_mfp.Plo@am__quote@ .c.o: @@ -4517,6 +4523,20 @@ libxerox_mfp_la-xerox_mfp.lo: xerox_mfp.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxerox_mfp_la-xerox_mfp.lo `test -f 'xerox_mfp.c' || echo '$(srcdir)/'`xerox_mfp.c +libxerox_mfp_la-xerox_mfp-usb.lo: xerox_mfp-usb.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxerox_mfp_la-xerox_mfp-usb.lo -MD -MP -MF $(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Tpo -c -o libxerox_mfp_la-xerox_mfp-usb.lo `test -f 'xerox_mfp-usb.c' || echo '$(srcdir)/'`xerox_mfp-usb.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Tpo $(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xerox_mfp-usb.c' object='libxerox_mfp_la-xerox_mfp-usb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxerox_mfp_la-xerox_mfp-usb.lo `test -f 'xerox_mfp-usb.c' || echo '$(srcdir)/'`xerox_mfp-usb.c + +libxerox_mfp_la-xerox_mfp-tcp.lo: xerox_mfp-tcp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxerox_mfp_la-xerox_mfp-tcp.lo -MD -MP -MF $(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Tpo -c -o libxerox_mfp_la-xerox_mfp-tcp.lo `test -f 'xerox_mfp-tcp.c' || echo '$(srcdir)/'`xerox_mfp-tcp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Tpo $(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xerox_mfp-tcp.c' object='libxerox_mfp_la-xerox_mfp-tcp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxerox_mfp_la-xerox_mfp-tcp.lo `test -f 'xerox_mfp-tcp.c' || echo '$(srcdir)/'`xerox_mfp-tcp.c + mostlyclean-libtool: -rm -f *.lo diff --git a/backend/xerox_mfp-tcp.c b/backend/xerox_mfp-tcp.c new file mode 100644 index 000000000..4bf89a45f --- /dev/null +++ b/backend/xerox_mfp-tcp.c @@ -0,0 +1,178 @@ +/* + * SANE backend for + * Samsung SCX-4500W + * + * Network Scanners Support + * Copyright 2010 Alexander Kuznetsov + * + * This program is licensed under GPL + SANE exception. + * More info at http://www.sane-project.org/license.html + * + */ + +#undef BACKEND_NAME +#define BACKEND_NAME xerox_mfp +#define DEBUG_DECLARE_ONLY +#define DEBUG_NOT_STATIC + +#include "sane/config.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sane/saneopts.h" +#include "sane/sanei_scsi.h" +#include "sane/sanei_usb.h" +#include "sane/sanei_pio.h" +#include "sane/sanei_tcp.h" +#include "sane/sanei_udp.h" +#include "sane/sanei_backend.h" +#include "sane/sanei_config.h" + +#include "xerox_mfp.h" + + +#define RECV_TIMEOUT 1 /* seconds */ +extern int sanei_debug_xerox_mfp; + +int tcp_dev_request (struct device *dev, + SANE_Byte *cmd, size_t cmdlen, + SANE_Byte *resp, size_t *resplen) +{ + size_t bytes_recv = 0; + ssize_t rc = 1; + size_t len; + + + /* Send request, if any */ + if (cmd && cmdlen) { + len = (size_t)sanei_tcp_write(dev->dn, cmd, cmdlen); + if (len != cmdlen) { + DBG (1, "%s: sent only %lu bytes of %lu\n", + __FUNCTION__, (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", __FUNCTION__, (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", + __FUNCTION__, strerror(errno), (int)*resplen, (int)bytes_recv); + *resplen = bytes_recv; +/* + TODO: + do something smarter than that! +*/ + return SANE_STATUS_GOOD; + return SANE_STATUS_IO_ERROR; + } + } + } + + *resplen = bytes_recv; + + return SANE_STATUS_GOOD; +} + +SANE_Status tcp_dev_open (struct device *dev) +{ + SANE_Status status; + char* strhost; + char* strport; + int port; + struct servent *sp; + struct timeval tv; + SANE_String_Const devname; + + + devname = dev->sane.name; + DBG (3, "%s: open %s\n", __FUNCTION__, devname); + + if (strncmp (devname, "tcp", 3) != 0) return SANE_STATUS_INVAL; + devname += 3; + devname = sanei_config_skip_whitespace (devname); + if (!*devname) return SANE_STATUS_INVAL; + + devname = sanei_config_get_string (devname, &strhost); + devname = sanei_config_skip_whitespace (devname); + + if (*devname) + devname = sanei_config_get_string (devname, &strport); + else + strport = "9400"; + + + if (isdigit(*strport)) { + port = atoi(strport); + } else { + if ((sp = getservbyname(strport, "tcp"))) { + port = ntohs(sp->s_port); + } else { + DBG (1, "%s: unknown TCP service %s\n", __FUNCTION__, 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", __FUNCTION__, strerror(errno)); + } + } + + return status; +} + +void +tcp_dev_close (struct device *dev) +{ + if (!dev) return; + + DBG (3, "%s: closing dev %p\n", __FUNCTION__, (void *)dev); + + /* finish all operations */ + if (dev->scanning) { + dev->cancel = 1; + /* flush READ_IMAGE data */ + if (dev->reading) sane_read(dev, NULL, 1, NULL); + /* send cancel if not sent before */ + if (dev->state != SANE_STATUS_CANCELLED) + ret_cancel(dev, 0); + } + + sanei_tcp_close(dev->dn); + dev->dn = -1; +} + + +SANE_Status +tcp_configure_device (const char *devname, SANE_Status (*list_one)(SANE_String_Const devname)) +{ +/* + TODO: LAN scanners multicast discovery. + devname would contain "tcp auto" + + We find new devnames and feed them to + `list_one_device' one by one +*/ + return list_one(devname); +} + +/* xerox_mfp-tcp.c */ diff --git a/backend/xerox_mfp-usb.c b/backend/xerox_mfp-usb.c new file mode 100644 index 000000000..b9b56d8f3 --- /dev/null +++ b/backend/xerox_mfp-usb.c @@ -0,0 +1,112 @@ +/* + * SANE backend for Xerox Phaser 3200MFP + * Copyright 2008 ABC + * + * This program is licensed under GPL + SANE exception. + * More info at http://www.sane-project.org/license.html + */ + +#undef BACKEND_NAME +#define BACKEND_NAME xerox_mfp +#define DEBUG_DECLARE_ONLY +#define DEBUG_NOT_STATIC +#include "sane/config.h" +#include "sane/saneopts.h" +#include "sane/sanei_config.h" +#include "sane/sanei_backend.h" +#include "sane/sanei_debug.h" +#include "sane/sanei_usb.h" +#include "xerox_mfp.h" + + +extern int sanei_debug_xerox_mfp; + +int +usb_dev_request (struct device *dev, + SANE_Byte *cmd, size_t cmdlen, + SANE_Byte *resp, size_t *resplen) +{ + SANE_Status status; + size_t len = cmdlen; + + if (cmd && cmdlen) { + status = sanei_usb_write_bulk (dev->dn, cmd, &cmdlen); + if (status != SANE_STATUS_GOOD) { + DBG (1, "%s: sanei_usb_write_bulk: %s\n", __FUNCTION__, + 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", + __FUNCTION__, (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", __FUNCTION__, + sane_strstatus (status)); + return SANE_STATUS_IO_ERROR; + } + } + + return SANE_STATUS_GOOD; +} + + +SANE_Status +usb_dev_open (struct device *dev) +{ + SANE_Status status; + + DBG (3, "%s: open %p\n", __FUNCTION__, (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", __FUNCTION__, + dev->sane.name, sane_strstatus (status)); + dev->dn = -1; + return status; + } + sanei_usb_clear_halt (dev->dn); + return SANE_STATUS_GOOD; +} + +void +usb_dev_close (struct device *dev) +{ + if (!dev) + return; + DBG (3, "%s: closing dev %p\n", __FUNCTION__, (void *)dev); + + /* finish all operations */ + if (dev->scanning) { + dev->cancel = 1; + /* flush READ_IMAGE data */ + if (dev->reading) + sane_read(dev, NULL, 1, NULL); + /* send cancel if not sent before */ + if (dev->state != SANE_STATUS_CANCELLED) + ret_cancel(dev, 0); + } + + sanei_usb_clear_halt (dev->dn); /* unstall for next users */ + sanei_usb_close (dev->dn); + dev->dn = -1; +} + + +/* SANE API ignores return code of this callback */ +SANE_Status +usb_configure_device (const char *devname, SANE_Status (*attach) (const char *dev)) +{ + sanei_usb_set_timeout (1000); + sanei_usb_attach_matching_devices (devname, attach); + sanei_usb_set_timeout (30000); + return SANE_STATUS_GOOD; +} + + +/* xerox_mfp-usb.c */ diff --git a/backend/xerox_mfp.c b/backend/xerox_mfp.c index ab0f773fd..e08b50fc2 100644 --- a/backend/xerox_mfp.c +++ b/backend/xerox_mfp.c @@ -2,10 +2,16 @@ * SANE backend for Xerox Phaser 3200MFP * Copyright 2008 ABC * + * Network Scanners Support + * Copyright 2010 Alexander Kuznetsov + * * This program is licensed under GPL + SANE exception. * More info at http://www.sane-project.org/license.html */ +#define DEBUG_NOT_STATIC +#define BACKEND_NAME xerox_mfp + #include "../include/sane/config.h" #include "../include/lassert.h" #include @@ -22,50 +28,20 @@ #include "../include/sane/sanei_thread.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" -#define BACKEND_NAME xerox_mfp #include "../include/sane/sanei_backend.h" #include "xerox_mfp.h" -#define BACKEND_BUILD 11 +#define BACKEND_BUILD 12 #define XEROX_CONFIG_FILE "xerox_mfp.conf" static const SANE_Device **devlist = NULL; /* sane_get_devices array */ static struct device *devices_head = NULL; /* sane_get_devices list */ -static int -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", __FUNCTION__, - 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", - __FUNCTION__, (u_long)len, (u_long)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", __FUNCTION__, - sane_strstatus (status)); - return SANE_STATUS_IO_ERROR; - } - } - - return SANE_STATUS_GOOD; -} +transport available_transports[] = { + { "usb", usb_dev_request, usb_dev_open, usb_dev_close, usb_configure_device }, + { "tcp", tcp_dev_request, tcp_dev_open, tcp_dev_close, tcp_configure_device }, + { 0 } +}; static int resolv_state(int state) { @@ -155,7 +131,7 @@ static int dev_command (struct device *dev, SANE_Byte * cmd, size_t reqlen) dev->state = 0; DBG (4, ":: dev_command(%s[%#x], %lu)\n", str_cmd(cmd[2]), cmd[2], (u_long)reqlen); - status = dev_request (dev, cmd, sendlen, res, &dev->reslen); + status = dev->io->dev_request(dev, cmd, sendlen, res, &dev->reslen); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: dev_request: %s\n", __FUNCTION__, sane_strstatus (status)); dev->state = SANE_STATUS_IO_ERROR; @@ -251,7 +227,7 @@ static SANE_Status dev_stop(struct device *dev) return state; } -static SANE_Status ret_cancel(struct device *dev, SANE_Status ret) +SANE_Status ret_cancel(struct device *dev, SANE_Status ret) { dev_cmd(dev, CMD_ABORT); if (dev->scanning) { @@ -810,46 +786,6 @@ sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act, return SANE_STATUS_GOOD; } -static SANE_Status -dev_open (struct device *dev) -{ - SANE_Status status; - - DBG (3, "%s: open %p\n", __FUNCTION__, (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", __FUNCTION__, - dev->sane.name, sane_strstatus (status)); - dev->dn = -1; - return status; - } - sanei_usb_clear_halt (dev->dn); - return SANE_STATUS_GOOD; -} - -static void -dev_close (struct device *dev) -{ - if (!dev) - return; - DBG (3, "%s: closing dev %p\n", __FUNCTION__, (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; -} - static void dev_free (struct device *dev) { @@ -894,6 +830,7 @@ list_one_device (SANE_String_Const devname) { struct device *dev; SANE_Status status; + transport *tr; DBG (4, "%s: %s\n", __FUNCTION__, devname); @@ -902,12 +839,20 @@ list_one_device (SANE_String_Const devname) return SANE_STATUS_GOOD; } + for (tr = available_transports; tr->ttype; tr++) { + if (!strncmp (devname, tr->ttype, strlen(tr->ttype))) + break; + } + if (!tr->ttype) + return SANE_STATUS_INVAL; + dev = calloc (1, sizeof (struct device)); if (dev == NULL) return SANE_STATUS_NO_MEM; dev->sane.name = strdup (devname); - status = dev_open (dev); + dev->io = tr; + status = tr->dev_open (dev); if (status != SANE_STATUS_GOOD) { dev_free (dev); return status; @@ -915,7 +860,7 @@ list_one_device (SANE_String_Const devname) /* status = dev_cmd (dev, CMD_ABORT);*/ status = dev_inquiry (dev); - dev_close (dev); + tr->dev_close (dev); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: dev_inquiry(%s): %s\n", __FUNCTION__, dev->sane.name, sane_strstatus (status)); @@ -933,8 +878,13 @@ list_one_device (SANE_String_Const devname) static SANE_Status list_conf_devices (UNUSED (SANEI_Config * config), const char *devname) { - sanei_usb_attach_matching_devices (devname, list_one_device); - return SANE_STATUS_GOOD; + transport *tr; + + for (tr = available_transports; tr->ttype; tr++) { + if (!strncmp (devname, tr->ttype, strlen(tr->ttype))) + return tr->configure_device(devname, list_one_device); + } + return SANE_STATUS_INVAL; } SANE_Status @@ -980,15 +930,11 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local) } free_devices (); - sanei_usb_set_timeout (1000); config.count = 0; config.descriptors = NULL; config.values = NULL; sanei_configure_attach (XEROX_CONFIG_FILE, &config, list_conf_devices); - sanei_usb_attach_matching_devices ("usb 0x0924 0x3da4", list_one_device); - - sanei_usb_set_timeout (30000); for (dev_count = 0, dev = devices_head; dev; dev = dev->next) dev_count++; @@ -1018,7 +964,7 @@ sane_close (SANE_Handle h) return; DBG (3, "%s: %p (%s)\n", __FUNCTION__, (void *)dev, dev->sane.name); - dev_close (dev); + dev->io->dev_close(dev); } SANE_Status @@ -1043,7 +989,7 @@ sane_open (SANE_String_Const name, SANE_Handle * h) for (dev = devices_head; dev; dev = dev->next) { if (strcmp(name, dev->sane.name) == 0) { *h = dev; - return dev_open(dev); + return dev->io->dev_open(dev); } } } @@ -1250,7 +1196,7 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * lenp) DBG (9, "<> request len: %lu, [%d, %d; %d]\n", (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen); - if ((status = dev_request (dev, NULL, 0, rbuf, &datalen)) != + if ((status = dev->io->dev_request(dev, NULL, 0, rbuf, &datalen)) != SANE_STATUS_GOOD) return status; dev->datalen += datalen; diff --git a/backend/xerox_mfp.conf.in b/backend/xerox_mfp.conf.in index 44b9167f8..cdb5e6cb8 100644 --- a/backend/xerox_mfp.conf.in +++ b/backend/xerox_mfp.conf.in @@ -1,5 +1,8 @@ #xerox_mfp.conf +#Xerox Phaser 3200MFP +usb 0x0924 0x3da4 + #Dell MFP Laser Printer 1815dn usb 0x413c 0x5124 @@ -42,3 +45,7 @@ usb 0x0924 0x4293 #Xerox WorkCentre 3220 usb 0x0924 0x4294 +# Samsung SCX-4500W, network mode +# tcp HOST_ADDR PORT +# Uncomment and configure: +#tcp scx4500 9400 diff --git a/backend/xerox_mfp.h b/backend/xerox_mfp.h index 094b40fab..500dd26ff 100644 --- a/backend/xerox_mfp.h +++ b/backend/xerox_mfp.h @@ -2,10 +2,16 @@ * SANE backend for Xerox Phaser 3200MFP * Copyright 2008 ABC * + * Network scanners support + * Copyright 2010 Alexander Kuznetsov + * * This program is licensed under GPL + SANE exception. * More info at http://www.sane-project.org/license.html */ +#ifndef xerox_mfp_h +#define xerox_mfp_h + #ifdef __GNUC__ #define UNUSED(x) x __attribute__((unused)) #else @@ -37,6 +43,8 @@ enum options { NUM_OPTIONS }; +typedef struct transport transport; + struct device { struct device *next; SANE_Device sane; @@ -103,8 +111,36 @@ struct device { int total_img_size; /* predicted image size */ int total_out_size; /* total we sent to user */ int total_data_size; /* total of what scanner sent us */ + + /* transport to use */ + transport *io; }; + +/* Transport abstract layer */ +struct transport { + char* ttype; + + int (*dev_request) (struct device *dev, + SANE_Byte *cmd, size_t cmdlen, + SANE_Byte *resp, size_t *resplen); + SANE_Status (*dev_open) (struct device *dev); + void (*dev_close) (struct device *dev); + SANE_Status (*configure_device) (const char *devname, SANE_Status (*cb)(SANE_String_Const devname)); +}; + +/* USB transport */ +int usb_dev_request (struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen); +SANE_Status usb_dev_open (struct device *dev); +void usb_dev_close (struct device *dev); +SANE_Status usb_configure_device (const char *devname, SANE_Status (*cb)(SANE_String_Const devname)); + +/* TCP unicast */ +int tcp_dev_request (struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen); +SANE_Status tcp_dev_open (struct device *dev); +void tcp_dev_close (struct device *dev); +SANE_Status tcp_configure_device (const char *devname, SANE_Status (*cb)(SANE_String_Const devname)); + /* device wants transfer buffer to be multiple of 512 */ #define USB_BLOCK_SIZE 512 #define USB_BLOCK_MASK ~(USB_BLOCK_SIZE - 1) @@ -119,6 +155,9 @@ static inline int dataroom(struct device *dev) { return DATASIZE - tail; } +/* Functions from original xerox_mfp.c, used in -usb.c and -tcp.c */ +SANE_Status ret_cancel(struct device *dev, SANE_Status ret); + /* a la SCSI commands. */ /* request len, response len, exception */ #define CMD_ABORT 0x06 /* 4, 32 */ #define CMD_INQUIRY 0x12 /* 4, 70 */ @@ -174,4 +213,4 @@ static inline int dataroom(struct device *dev) { #define DOC_FLATBED 0x40 #define DOC_AUTO 0x80 -/* xerox_mfp.h */ +#endif /* xerox_mfp_h */ diff --git a/doc/Makefile.in b/doc/Makefile.in index 55c88e4fd..f12db2dab 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -173,6 +173,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/doc/descriptions/xerox_mfp.desc b/doc/descriptions/xerox_mfp.desc index 4b6c7b2cf..e476666f7 100644 --- a/doc/descriptions/xerox_mfp.desc +++ b/doc/descriptions/xerox_mfp.desc @@ -77,3 +77,7 @@ :interface "USB" :usbid "0x04e8" "0x3434" :status :good + +:model "SCX-4500W" +:interface "Ethernet" +:status :basic diff --git a/doc/sane-xerox_mfp.man b/doc/sane-xerox_mfp.man index 143a8e0d0..0f896ce59 100644 --- a/doc/sane-xerox_mfp.man +++ b/doc/sane-xerox_mfp.man @@ -6,10 +6,28 @@ sane\-xerox_mfp \- SANE backend for Xerox Phaser 3200MFP device The .B sane\-xerox_mfp library implements a SANE (Scanner Access Now Easy) backend that provides -access to the following Xerox USB multifunction-peripheral: +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 @@ -20,9 +38,24 @@ the USB vendor and device ids (e.g. from or syslog) to us. Even if the scanner's name is only slightly different from the models mentioned above, please let us know. .SH CONFIGURATION -None required. +.I @CONFIGDIR@/xerox_mfp.conf +USB scanners do not need any configuration. + +For SCX-4500W in network mode you need to specify +.PP +.RS +.B tcp host_address [port] +.RE +.PP +The +.B host_address +is passed through resolver, thus can be a dotted quad or a name from /etc/hosts or resolvable through DNS. .SH FILES .TP +.I @CONFIGDIR@/xerox_mfp.conf +The backend configuration file. By default all scanner types/models are enabled, you +may want to comment out unwanted. +.TP .I @LIBDIR@/libsane\-xerox_mfp.a The static library implementing this backend. .TP @@ -37,12 +70,16 @@ debug levels increase the verbosity of the output. Example: export SANE_DEBUG_XEROX_MFP=4 - -.SH "SEE ALSO" -.BR sane (7), -.BR sane\-usb (5), -.br - .SH AUTHOR Alex Belkin +Samsung SCX-4500W scan over network support +Alexander Kuznetsov +.SH BUGS: +Multicast autoconfiguration for LAN scanners is not implemented yet. IPv6 addressing never been tested. + +.SH "SEE ALSO" +.BR sane (7), +.BR sane\-usb (5) +.br + diff --git a/frontend/Makefile.in b/frontend/Makefile.in index 7a40819a8..19cbb601a 100644 --- a/frontend/Makefile.in +++ b/frontend/Makefile.in @@ -172,6 +172,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/include/Makefile.in b/include/Makefile.in index 14714d0eb..0e0e35138 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -158,6 +158,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/japi/Makefile.in b/japi/Makefile.in index 2db52a099..78a88483b 100644 --- a/japi/Makefile.in +++ b/japi/Makefile.in @@ -181,6 +181,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/lib/Makefile.in b/lib/Makefile.in index dc849a30b..fc630f0a9 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -156,6 +156,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/po/Makefile.in b/po/Makefile.in index 4790aaf48..849557cb2 100644 --- a/po/Makefile.in +++ b/po/Makefile.in @@ -133,6 +133,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/sanei/Makefile.in b/sanei/Makefile.in index 65269d23b..46e399403 100644 --- a/sanei/Makefile.in +++ b/sanei/Makefile.in @@ -172,6 +172,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 8c9669b75..f63e7b331 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -131,6 +131,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ diff --git a/tools/Makefile.in b/tools/Makefile.in index b031d2510..f20dad6bf 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -191,6 +191,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@