diff options
Diffstat (limited to 'backend/xerox_mfp-tcp.c')
-rw-r--r-- | backend/xerox_mfp-tcp.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/backend/xerox_mfp-tcp.c b/backend/xerox_mfp-tcp.c new file mode 100644 index 0000000..2addb0d --- /dev/null +++ b/backend/xerox_mfp-tcp.c @@ -0,0 +1,182 @@ +/* + * SANE backend for + * Samsung SCX-4500W + * + * Network Scanners Support + * Copyright 2010 Alexander Kuznetsov <acca(at)cpan.org> + * + * 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 <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +#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 */ |