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 35static ssize_t 36sanei_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 66static ssize_t 67sanei_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 96ssize_t 97sanei_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 163size_t 164sanei_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 241SANE_Status 242sanei_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 254SANE_Status 255sanei_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