• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * epsonds-io.c - Epson ESC/I-2 driver, low level I/O.
3  *
4  * Copyright (C) 2015 Tower Technologies
5  * Author: Alessandro Zummo <a.zummo@towertech.it>
6  *
7  * This file is part of the SANE package.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation, version 2.
12  */
13 
14 #define DEBUG_DECLARE_ONLY
15 
16 #include "sane/config.h"
17 #include <ctype.h>
18 #include <unistd.h>     /* sleep */
19 #ifdef HAVE_SYS_TYPES_H
20 #include <sys/types.h>
21 #endif
22 
23 #include "epsonds.h"
24 #include "epsonds-io.h"
25 #include "epsonds-net.h"
26 
27 #ifdef HAVE_SYS_TYPES_H
28 #include <sys/types.h>
29 #endif
30 
eds_send(epsonds_scanner * s,void * buf,size_t length,SANE_Status * status,size_t reply_len)31 size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status, size_t reply_len)
32 {
33 	DBG(32, "%s: size = %lu\n", __func__, (u_long) length);
34 
35 	if (length == 2) {
36 
37 		char *cmd = buf;
38 
39 		switch (cmd[0]) {
40 		case FS:
41 			DBG(9, "%s: FS %c\n", __func__, cmd[1]);
42 			break;
43 		}
44 	}
45 
46 	if (s->hw->connection == SANE_EPSONDS_NET) {
47 
48 		return epsonds_net_write(s, 0x2000, buf, length, reply_len, status);
49 
50 	} else if (s->hw->connection == SANE_EPSONDS_USB) {
51 
52 		size_t n = length;
53 
54 		*status = sanei_usb_write_bulk(s->fd, buf, &n);
55 
56 		return n;
57 	}
58 
59 	/* never reached */
60 
61 	*status = SANE_STATUS_INVAL;
62 
63 	return 0;
64 }
65 
eds_recv(epsonds_scanner * s,void * buf,size_t length,SANE_Status * status)66 size_t eds_recv(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status)
67 {
68 	size_t n = length; /* network interface needs to read header back even data is 0.*/
69 
70 	DBG(30, "%s: size = %ld, buf = %p\n", __func__, (long) length, buf);
71 
72 	*status = SANE_STATUS_GOOD;
73 
74 	if (s->hw->connection == SANE_EPSONDS_NET) {
75 		n = epsonds_net_read(s, buf, length, status);
76 	} else if (s->hw->connection == SANE_EPSONDS_USB) {
77 
78 		/* !!! only report an error if we don't read anything */
79 		if (n) {
80 			*status = sanei_usb_read_bulk(s->fd, (SANE_Byte *)buf,
81 						    (size_t *) &n);
82 			if (n > 0)
83 				*status = SANE_STATUS_GOOD;
84 		}
85 	}
86 
87 	if (n < length) {
88 		DBG(1, "%s: expected = %lu, got = %ld, canceling: %d\n", __func__,
89 		    (u_long)length, (long)n, s->canceling);
90 
91 		*status = SANE_STATUS_IO_ERROR;
92 	}
93 
94 	return n;
95 }
96 
97 /* Simple function to exchange a fixed amount of data with the scanner */
98 
eds_txrx(epsonds_scanner * s,char * txbuf,size_t txlen,char * rxbuf,size_t rxlen)99 SANE_Status eds_txrx(epsonds_scanner* s, char *txbuf, size_t txlen,
100 	    char *rxbuf, size_t rxlen)
101 {
102 	SANE_Status status;
103 	size_t done;
104 
105 	done = eds_send(s, txbuf, txlen, &status, rxlen);
106 	if (status != SANE_STATUS_GOOD) {
107 		DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status));
108 		return status;
109 	}
110 
111 	if (done != txlen) {
112 		DBG(1, "%s: tx err, short write\n", __func__);
113 		return SANE_STATUS_IO_ERROR;
114 	}
115 
116 	done = eds_recv(s, rxbuf, rxlen, &status);
117 	if (status != SANE_STATUS_GOOD) {
118 		DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status));
119 	}
120 
121 	return status;
122 }
123 
124 /* This function should be used to send codes that only requires the scanner
125  * to give back an ACK or a NAK, namely FS X or FS Y
126  */
127 
eds_control(epsonds_scanner * s,void * buf,size_t buf_size)128 SANE_Status eds_control(epsonds_scanner *s, void *buf, size_t buf_size)
129 {
130 	char result;
131 	SANE_Status status;
132 
133 	DBG(12, "%s: size = %lu\n", __func__, (u_long) buf_size);
134 
135 	status = eds_txrx(s, buf, buf_size, &result, 1);
136 	if (status != SANE_STATUS_GOOD) {
137 		DBG(1, "%s: failed, %s\n", __func__, sane_strstatus(status));
138 		return status;
139 	}
140 
141 	if (result == ACK)
142 		return SANE_STATUS_GOOD;
143 
144 	if (result == NAK) {
145 		DBG(3, "%s: NAK\n", __func__);
146 		return SANE_STATUS_INVAL;
147 	}
148 
149 	DBG(1, "%s: result is neither ACK nor NAK but 0x%02x\n",
150 		__func__, result);
151 
152 	return SANE_STATUS_INVAL;
153 }
154 
eds_fsy(epsonds_scanner * s)155 SANE_Status eds_fsy(epsonds_scanner *s)
156 {
157 	return eds_control(s, "\x1CY", 2);
158 }
159 
eds_fsx(epsonds_scanner * s)160 SANE_Status eds_fsx(epsonds_scanner *s)
161 {
162 //	SANE_Status status = eds_control(s, "\x1CZ", 2);
163 	SANE_Status status = eds_control(s, "\x1CX", 2);
164 	if (status == SANE_STATUS_GOOD) {
165 		s->locked = 1;
166 	}
167 
168 	return status;
169 }
170 
eds_lock(epsonds_scanner * s)171 SANE_Status eds_lock(epsonds_scanner *s)
172 {
173 	SANE_Status status;
174 
175 	DBG(5, "%s\n", __func__);
176 
177 	if (s->hw->connection == SANE_EPSONDS_USB) {
178 		sanei_usb_set_timeout(USB_SHORT_TIMEOUT);
179 	}
180 
181 	status = eds_fsx(s);
182 
183 	if (s->hw->connection == SANE_EPSONDS_USB) {
184 		sanei_usb_set_timeout(USB_TIMEOUT);
185 	}
186 
187 	return status;
188 }
189