summaryrefslogtreecommitdiff
path: root/backend/xerox_mfp-tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/xerox_mfp-tcp.c')
-rw-r--r--backend/xerox_mfp-tcp.c182
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 */