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