/* * 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 #ifdef HAVE_SYS_SOCKET_H #include #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 */