1 /*
2 * epson2_net.c - SANE library for Epson scanners.
3 *
4 * Copyright (C) 2006 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
18 #ifdef HAVE_SYS_SELECT_H
19 #include <sys/select.h>
20 #endif
21
22 #include "sane/sane.h"
23 #include "sane/saneopts.h"
24 #include "sane/sanei_tcp.h"
25 #include "sane/sanei_config.h"
26 #include "sane/sanei_backend.h"
27
28 #include "epson2.h"
29 #include "epson2_net.h"
30
31 #include "byteorder.h"
32
33 #include "sane/sanei_debug.h"
34
35 static ssize_t
sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, SANE_Status *status)36 sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, ssize_t wanted,
37 SANE_Status *status)
38 {
39 int ready;
40 ssize_t read = -1;
41 fd_set readable;
42 struct timeval tv;
43
44 tv.tv_sec = 10;
45 tv.tv_usec = 0;
46
47 FD_ZERO(&readable);
48 FD_SET(s->fd, &readable);
49
50 ready = select(s->fd + 1, &readable, NULL, NULL, &tv);
51 if (ready > 0) {
52 read = sanei_tcp_read(s->fd, buf, wanted);
53 } else {
54 DBG(15, "%s: select failed: %d\n", __func__, ready);
55 }
56
57 *status = SANE_STATUS_GOOD;
58
59 if (read < wanted) {
60 *status = SANE_STATUS_IO_ERROR;
61 }
62
63 return read;
64 }
65
66 static ssize_t
sanei_epson_net_read_buf(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, SANE_Status * status)67 sanei_epson_net_read_buf(Epson_Scanner *s, unsigned char *buf, ssize_t wanted,
68 SANE_Status * status)
69 {
70 ssize_t read = 0;
71
72 DBG(23, "%s: reading up to %lu from buffer at %p, %lu available\n",
73 __func__, (u_long) wanted, (void *) s->netptr, (u_long) s->netlen);
74
75 if ((size_t) wanted > s->netlen) {
76 *status = SANE_STATUS_IO_ERROR;
77 wanted = s->netlen;
78 }
79
80 memcpy(buf, s->netptr, wanted);
81 read = wanted;
82
83 s->netptr += read;
84 s->netlen -= read;
85
86 if (s->netlen == 0) {
87 DBG(23, "%s: freeing %p\n", __func__, (void *) s->netbuf);
88 free(s->netbuf);
89 s->netbuf = s->netptr = NULL;
90 s->netlen = 0;
91 }
92
93 return read;
94 }
95
96 ssize_t
sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, SANE_Status * status)97 sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted,
98 SANE_Status * status)
99 {
100 if (wanted < 0) {
101 *status = SANE_STATUS_INVAL;
102 return 0;
103 }
104
105 size_t size;
106 ssize_t read = 0;
107 unsigned char header[12];
108
109 /* read from remainder of buffer */
110 if (s->netptr) {
111 return sanei_epson_net_read_buf(s, buf, wanted, status);
112 }
113
114 /* receive net header */
115 read = sanei_epson_net_read_raw(s, header, 12, status);
116 if (read != 12) {
117 return 0;
118 }
119
120 /* validate header */
121 if (header[0] != 'I' || header[1] != 'S') {
122 DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]);
123 *status = SANE_STATUS_IO_ERROR;
124 return 0;
125 }
126
127 /* parse payload size */
128 size = be32atoh(&header[6]);
129
130 *status = SANE_STATUS_GOOD;
131
132 if (!s->netbuf) {
133 DBG(15, "%s: direct read\n", __func__);
134 DBG(23, "%s: wanted = %lu, available = %lu\n", __func__,
135 (u_long) wanted, (u_long) size);
136
137 if ((size_t) wanted > size) {
138 wanted = size;
139 }
140
141 read = sanei_epson_net_read_raw(s, buf, wanted, status);
142 } else {
143 DBG(15, "%s: buffered read\n", __func__);
144 DBG(23, "%s: bufferable = %lu, available = %lu\n", __func__,
145 (u_long) s->netlen, (u_long) size);
146
147 if (s->netlen > size) {
148 s->netlen = size;
149 }
150
151 /* fill buffer */
152 read = sanei_epson_net_read_raw(s, s->netbuf, s->netlen, status);
153 s->netptr = s->netbuf;
154 s->netlen = (read > 0 ? read : 0);
155
156 /* copy wanted part */
157 read = sanei_epson_net_read_buf(s, buf, wanted, status);
158 }
159
160 return read;
161 }
162
163 size_t
sanei_epson_net_write(Epson_Scanner *s, unsigned int cmd, const unsigned char *buf, size_t buf_size, size_t reply_len, SANE_Status *status)164 sanei_epson_net_write(Epson_Scanner *s, unsigned int cmd, const unsigned char *buf,
165 size_t buf_size, size_t reply_len, SANE_Status *status)
166 {
167 unsigned char *h1, *h2, *payload;
168 unsigned char *packet = malloc(12 + 8 + buf_size);
169
170 if (!packet) {
171 *status = SANE_STATUS_NO_MEM;
172 return 0;
173 }
174
175 h1 = packet;
176 h2 = packet + 12;
177 payload = packet + 12 + 8;
178
179 if (reply_len) {
180 if (s->netbuf) {
181 DBG(23, "%s, freeing %p, %ld bytes unprocessed\n",
182 __func__, (void *) s->netbuf, (u_long) s->netlen);
183 free(s->netbuf);
184 s->netbuf = s->netptr = NULL;
185 s->netlen = 0;
186 }
187 s->netbuf = malloc(reply_len);
188 if (!s->netbuf) {
189 free(packet);
190 *status = SANE_STATUS_NO_MEM;
191 return 0;
192 }
193 s->netlen = reply_len;
194 DBG(24, "%s: allocated %lu bytes at %p\n", __func__,
195 (u_long) s->netlen, (void *) s->netbuf);
196 }
197
198 DBG(24, "%s: cmd = %04x, buf = %p, buf_size = %lu, reply_len = %lu\n",
199 __func__, cmd, (void *) buf, (u_long) buf_size, (u_long) reply_len);
200
201 memset(h1, 0x00, 12);
202 memset(h2, 0x00, 8);
203
204 h1[0] = 'I';
205 h1[1] = 'S';
206
207 h1[2] = cmd >> 8;
208 h1[3] = cmd;
209
210 h1[4] = 0x00;
211 h1[5] = 0x0C; /* Don't know what's that */
212
213 DBG(24, "H1[0]: %02x %02x %02x %02x\n", h1[0], h1[1], h1[2], h1[3]);
214
215 if((cmd >> 8) == 0x20) {
216 htobe32a(&h1[6], buf_size + 8);
217
218 htobe32a(&h2[0], buf_size);
219 htobe32a(&h2[4], reply_len);
220
221 DBG(24, "H1[6]: %02x %02x %02x %02x (%lu)\n", h1[6], h1[7], h1[8], h1[9], (u_long) (buf_size + 8));
222 DBG(24, "H2[0]: %02x %02x %02x %02x (%lu)\n", h2[0], h2[1], h2[2], h2[3], (u_long) buf_size);
223 DBG(24, "H2[4]: %02x %02x %02x %02x (%lu)\n", h2[4], h2[5], h2[6], h2[7], (u_long) reply_len);
224 }
225
226 if ((cmd >> 8) == 0x20 && (buf_size || reply_len)) {
227 if (buf_size)
228 memcpy(payload, buf, buf_size);
229
230 sanei_tcp_write(s->fd, packet, 12 + 8 + buf_size);
231 }
232 else
233 sanei_tcp_write(s->fd, packet, 12);
234
235 free(packet);
236
237 *status = SANE_STATUS_GOOD;
238 return buf_size;
239 }
240
241 SANE_Status
sanei_epson_net_lock(struct Epson_Scanner *s)242 sanei_epson_net_lock(struct Epson_Scanner *s)
243 {
244 SANE_Status status;
245 unsigned char buf[1];
246
247 DBG(1, "%s\n", __func__);
248
249 sanei_epson_net_write(s, 0x2100, NULL, 0, 0, &status);
250 sanei_epson_net_read(s, buf, 1, &status);
251 return status;
252 }
253
254 SANE_Status
sanei_epson_net_unlock(struct Epson_Scanner *s)255 sanei_epson_net_unlock(struct Epson_Scanner *s)
256 {
257 SANE_Status status;
258
259 DBG(1, "%s\n", __func__);
260
261 sanei_epson_net_write(s, 0x2101, NULL, 0, 0, &status);
262 /* sanei_epson_net_read(s, buf, 1, &status); */
263 return status;
264 }
265