kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			183 wiersze
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			183 wiersze
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
| /*
 | |
|  *	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",
 | |
|                 __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;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     *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", __func__, 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", __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));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| void
 | |
| tcp_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_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 */
 |