epsonds: added support for network scanners

merge-requests/1/head
Alessandro Zummo 2016-06-21 00:43:39 +02:00
rodzic f13ca02b86
commit 9b389a61c5
10 zmienionych plików z 502 dodań i 46 usunięć

Wyświetl plik

@ -449,7 +449,8 @@ libsane_epson2_la_LIBADD = $(COMMON_LIBS) libepson2.la ../sanei/sanei_init_debug
EXTRA_DIST += epson2.conf.in
libepsonds_la_SOURCES = epsonds.c epsonds.h epsonds-usb.c epsonds-usb.h epsonds-io.c epsonds-io.h \
epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h
epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h \
epsonds-net.c epsonds-net.h
libepsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
nodist_libsane_epsonds_la_SOURCES = epsonds-s.c
@ -458,7 +459,8 @@ libsane_epsonds_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_epsonds_la_LIBADD = $(COMMON_LIBS) libepsonds.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo \
../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \
$(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \
$(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SOCKET_LIBS)
EXTRA_DIST += epsonds.conf.in
libfujitsu_la_SOURCES = fujitsu.c fujitsu.h fujitsu-scsi.h

Wyświetl plik

@ -215,7 +215,7 @@ libepsonds_la_LIBADD =
am_libepsonds_la_OBJECTS = libepsonds_la-epsonds.lo \
libepsonds_la-epsonds-usb.lo libepsonds_la-epsonds-io.lo \
libepsonds_la-epsonds-cmd.lo libepsonds_la-epsonds-ops.lo \
libepsonds_la-epsonds-jpeg.lo
libepsonds_la-epsonds-jpeg.lo libepsonds_la-epsonds-net.lo
libepsonds_la_OBJECTS = $(am_libepsonds_la_OBJECTS)
libfujitsu_la_LIBADD =
am_libfujitsu_la_OBJECTS = libfujitsu_la-fujitsu.lo
@ -670,9 +670,10 @@ libsane_epsonds_la_DEPENDENCIES = $(COMMON_LIBS) libepsonds.la \
../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
../sanei/sanei_config.lo ../sanei/sanei_config2.lo \
sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \
../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
nodist_libsane_epsonds_la_OBJECTS = libsane_epsonds_la-epsonds-s.lo
libsane_epsonds_la_OBJECTS = $(nodist_libsane_epsonds_la_OBJECTS)
libsane_epsonds_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@ -1911,6 +1912,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -2297,7 +2299,8 @@ libsane_epson2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson2
libsane_epson2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_epson2_la_LIBADD = $(COMMON_LIBS) libepson2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(SCSI_LIBS) $(USB_LIBS) $(SOCKET_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
libepsonds_la_SOURCES = epsonds.c epsonds.h epsonds-usb.c epsonds-usb.h epsonds-io.c epsonds-io.h \
epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h
epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h \
epsonds-net.c epsonds-net.h
libepsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
nodist_libsane_epsonds_la_SOURCES = epsonds-s.c
@ -2306,7 +2309,8 @@ libsane_epsonds_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_epsonds_la_LIBADD = $(COMMON_LIBS) libepsonds.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo \
../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \
$(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \
$(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SOCKET_LIBS)
libfujitsu_la_SOURCES = fujitsu.c fujitsu.h fujitsu-scsi.h
libfujitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=fujitsu
@ -3432,6 +3436,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-cmd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-io.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-jpeg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-net.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-ops.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-usb.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds.Plo@am__quote@
@ -3954,6 +3959,13 @@ libepsonds_la-epsonds-jpeg.lo: epsonds-jpeg.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-jpeg.lo `test -f 'epsonds-jpeg.c' || echo '$(srcdir)/'`epsonds-jpeg.c
libepsonds_la-epsonds-net.lo: epsonds-net.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-net.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-net.Tpo -c -o libepsonds_la-epsonds-net.lo `test -f 'epsonds-net.c' || echo '$(srcdir)/'`epsonds-net.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-net.Tpo $(DEPDIR)/libepsonds_la-epsonds-net.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-net.c' object='libepsonds_la-epsonds-net.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-net.lo `test -f 'epsonds-net.c' || echo '$(srcdir)/'`epsonds-net.c
libfujitsu_la-fujitsu.lo: fujitsu.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfujitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libfujitsu_la-fujitsu.lo -MD -MP -MF $(DEPDIR)/libfujitsu_la-fujitsu.Tpo -c -o libfujitsu_la-fujitsu.lo `test -f 'fujitsu.c' || echo '$(srcdir)/'`fujitsu.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfujitsu_la-fujitsu.Tpo $(DEPDIR)/libfujitsu_la-fujitsu.Plo

Wyświetl plik

@ -21,6 +21,7 @@
#include "epsonds-io.h"
#include "epsonds-cmd.h"
#include "epsonds-ops.h"
#include "epsonds-net.h"
static SANE_Status
esci2_parse_block(char *buf, int len, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len))
@ -132,49 +133,39 @@ static SANE_Status esci2_cmd(epsonds_scanner* s,
{
SANE_Status status;
unsigned int more;
char rbuf[64];
char header[12], rbuf[64];
DBG(8, "%s: %4s len %lu, payload len: %lu\n", __func__, cmd, len, plen);
if (len < 12) {
DBG(1, "%s: command is too short (%lu)\n", __func__, len);
memset(header, 0x00, sizeof(header));
memset(rbuf, 0x00, sizeof(rbuf));
// extra safety check, will not happen
if (len != 12) {
DBG(1, "%s: command has wrong size (%lu != 12)\n", __func__, len);
return SANE_STATUS_INVAL;
}
/* merge the payload size and send the RequestBlock */
if (payload && plen) {
sprintf(rbuf, "%4.4sx%07x", cmd, (unsigned int)plen);
DBG(8, " %s (%lu)\n", rbuf, plen);
eds_send(s, rbuf, 12, &status);
} else {
eds_send(s, cmd, len, &status);
}
// merge ParameterBlock size
sprintf(header, "%4.4sx%07x", cmd, (unsigned int)plen);
// send RequestBlock, request immediate response if there's no payload
status = eds_txrx(s, header, len, rbuf, (plen > 0) ? 0 : 64);
if (status != SANE_STATUS_GOOD) {
return status;
}
/* send ParameterBlock */
if (payload && plen) {
/* send ParameterBlock, request response */
if (plen) {
eds_send(s, payload, plen, &status);
DBG(8, " %12.12s (%lu)\n", header, plen);
status = eds_txrx(s, payload, plen, rbuf, 64);
if (status != SANE_STATUS_GOOD) {
return status;
}
}
/* receive DataHeaderBlock */
memset(rbuf, 0x00, sizeof(rbuf));
eds_recv(s, rbuf, 64, &status);
if (status != SANE_STATUS_GOOD) {
return status;
}
/* rxbuf holds the DataHeaderBlock, which should be
* parsed to know if we need to read more data
*/
@ -196,6 +187,10 @@ static SANE_Status esci2_cmd(epsonds_scanner* s,
char *pbuf = malloc(more);
if (pbuf) {
if (s->hw->connection == SANE_EPSONDS_NET) {
epsonds_net_request_read(s, more);
}
ssize_t read = eds_recv(s, pbuf, more, &status);
if (read != more) {
}
@ -853,7 +848,7 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
return SANE_STATUS_CANCELLED;
/* request image data */
eds_send(s, "IMG x0000000", 12, &status);
eds_send(s, "IMG x0000000", 12, &status, 64);
if (status != SANE_STATUS_GOOD) {
return status;
}
@ -882,6 +877,10 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
}
/* ALWAYS read image data */
if (s->hw->connection == SANE_EPSONDS_NET) {
epsonds_net_request_read(s, more);
}
read = eds_recv(s, s->buf, more, &status);
if (status != SANE_STATUS_GOOD) {
return status;

Wyświetl plik

@ -22,12 +22,13 @@
#include "epsonds.h"
#include "epsonds-io.h"
#include "epsonds-net.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status)
size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status, size_t reply_len)
{
DBG(32, "%s: size = %lu\n", __func__, (u_long) length);
@ -43,7 +44,9 @@ size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *statu
}
if (s->hw->connection == SANE_EPSONDS_NET) {
/* XXX */
return epsonds_net_write(s, 0x2000, buf, length, reply_len, status);
} else if (s->hw->connection == SANE_EPSONDS_USB) {
size_t n = length;
@ -67,7 +70,7 @@ size_t eds_recv(epsonds_scanner *s, void *buf, size_t length, SANE_Status *statu
DBG(30, "%s: size = %ld, buf = %p\n", __func__, (long) length, buf);
if (s->hw->connection == SANE_EPSONDS_NET) {
/* XXX */
n = epsonds_net_read(s, buf, length, status);
} else if (s->hw->connection == SANE_EPSONDS_USB) {
/* !!! only report an error if we don't read anything */
@ -97,7 +100,7 @@ SANE_Status eds_txrx(epsonds_scanner* s, char *txbuf, size_t txlen,
SANE_Status status;
size_t done;
done = eds_send(s, txbuf, txlen, &status);
done = eds_send(s, txbuf, txlen, &status, rxlen);
if (status != SANE_STATUS_GOOD) {
DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status));
return status;
@ -108,6 +111,10 @@ SANE_Status eds_txrx(epsonds_scanner* s, char *txbuf, size_t txlen,
return SANE_STATUS_IO_ERROR;
}
if (rxlen == 0) {
return status;
}
done = eds_recv(s, rxbuf, rxlen, &status);
if (status != SANE_STATUS_GOOD) {
DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status));
@ -154,6 +161,7 @@ SANE_Status eds_fsy(epsonds_scanner *s)
SANE_Status eds_fsx(epsonds_scanner *s)
{
// SANE_Status status = eds_control(s, "\x1CZ", 2);
SANE_Status status = eds_control(s, "\x1CX", 2);
if (status == SANE_STATUS_GOOD) {
s->locked = 1;

Wyświetl plik

@ -17,7 +17,7 @@
#define USB_TIMEOUT (6 * 1000)
#define USB_SHORT_TIMEOUT (1 * 800)
size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status);
size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status, size_t reply_len);
size_t eds_recv(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status);
SANE_Status eds_txrx(epsonds_scanner *s, char *txbuf, size_t txlen,

Wyświetl plik

@ -0,0 +1,278 @@
/*
* epsonds-net.c - SANE library for Epson scanners.
*
* Copyright (C) 2006-2016 Tower Technologies
* Author: Alessandro Zummo <a.zummo@towertech.it>
*
* This file is part of the SANE package.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*/
#define DEBUG_DECLARE_ONLY
#include "sane/config.h"
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include "sane/sane.h"
#include "sane/saneopts.h"
#include "sane/sanei_tcp.h"
#include "sane/sanei_config.h"
#include "sane/sanei_backend.h"
#include "epsonds.h"
#include "epsonds-net.h"
#include "byteorder.h"
#include "sane/sanei_debug.h"
static int
epsonds_net_read_raw(epsonds_scanner *s, unsigned char *buf, ssize_t wanted,
SANE_Status *status)
{
int ready, read = -1;
fd_set readable;
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&readable);
FD_SET(s->fd, &readable);
ready = select(s->fd + 1, &readable, NULL, NULL, &tv);
if (ready > 0) {
read = sanei_tcp_read(s->fd, buf, wanted);
} else {
DBG(15, "%s: select failed: %d\n", __func__, ready);
}
*status = SANE_STATUS_GOOD;
if (read < wanted) {
*status = SANE_STATUS_IO_ERROR;
}
return read;
}
int
epsonds_net_read(epsonds_scanner *s, unsigned char *buf, ssize_t wanted,
SANE_Status * status)
{
ssize_t size;
ssize_t read = 0;
unsigned char header[12];
/* read from buffer, if available */
if (wanted && s->netptr != s->netbuf) {
DBG(23, "reading %lu from buffer at %p, %lu available\n",
(u_long) wanted, s->netptr, (u_long) s->netlen);
memcpy(buf, s->netptr, wanted);
read = wanted;
s->netlen -= wanted;
if (s->netlen == 0) {
DBG(23, "%s: freeing %p\n", __func__, s->netbuf);
free(s->netbuf);
s->netbuf = s->netptr = NULL;
s->netlen = 0;
}
return read;
}
/* receive net header */
size = epsonds_net_read_raw(s, header, 12, status);
if (size != 12) {
return 0;
}
if (header[0] != 'I' || header[1] != 'S') {
DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]);
*status = SANE_STATUS_IO_ERROR;
return 0;
}
// incoming payload size
size = be32atoh(&header[6]);
DBG(23, "%s: wanted = %lu, available = %lu\n", __func__,
(u_long) wanted, (u_long) size);
*status = SANE_STATUS_GOOD;
if (size == wanted) {
DBG(15, "%s: full read\n", __func__);
if (size) {
read = epsonds_net_read_raw(s, buf, size, status);
}
if (s->netbuf) {
free(s->netbuf);
s->netbuf = NULL;
s->netlen = 0;
}
if (read < 0) {
return 0;
}
} else if (wanted < size) {
DBG(23, "%s: long tail\n", __func__);
read = epsonds_net_read_raw(s, s->netbuf, size, status);
if (read != size) {
return 0;
}
memcpy(buf, s->netbuf, wanted);
read = wanted;
free(s->netbuf);
s->netbuf = NULL;
s->netlen = 0;
} else {
DBG(23, "%s: partial read\n", __func__);
read = epsonds_net_read_raw(s, s->netbuf, size, status);
if (read != size) {
return 0;
}
s->netlen = size - wanted;
s->netptr += wanted;
read = wanted;
DBG(23, "0,4 %02x %02x\n", s->netbuf[0], s->netbuf[4]);
DBG(23, "storing %lu to buffer at %p, next read at %p, %lu bytes left\n",
(u_long) size, s->netbuf, s->netptr, (u_long) s->netlen);
memcpy(buf, s->netbuf, wanted);
}
return read;
}
SANE_Status
epsonds_net_request_read(epsonds_scanner *s, size_t len)
{
SANE_Status status;
epsonds_net_write(s, 0x2000, NULL, 0, len, &status);
return status;
}
int
epsonds_net_write(epsonds_scanner *s, unsigned int cmd, const unsigned char *buf,
size_t buf_size, size_t reply_len, SANE_Status *status)
{
unsigned char *h1, *h2, *payload;
unsigned char *packet = malloc(12 + 8);
/* XXX check allocation failure */
h1 = packet; // packet header
h2 = packet + 12; // data header
if (reply_len) {
s->netbuf = s->netptr = malloc(reply_len);
s->netlen = reply_len;
DBG(24, "allocated %lu bytes at %p\n",
(u_long) reply_len, s->netbuf);
}
DBG(24, "%s: cmd = %04x, buf = %p, buf_size = %lu, reply_len = %lu\n",
__func__, cmd, buf, (u_long) buf_size, (u_long) reply_len);
memset(h1, 0x00, 12);
memset(h2, 0x00, 8);
h1[0] = 'I';
h1[1] = 'S';
h1[2] = cmd >> 8; // packet type
h1[3] = cmd; // data type
h1[4] = 0x00;
h1[5] = 0x0C; // data offset
DBG(24, "H1[0]: %02x %02x %02x %02x\n", h1[0], h1[1], h1[2], h1[3]);
// 0x20 passthru
// 0x21 job control
if (buf_size) {
htobe32a(&h1[6], buf_size);
}
if((cmd >> 8) == 0x20) {
htobe32a(&h1[6], buf_size + 8); // data size (data header + payload)
htobe32a(&h2[0], buf_size); // payload size
htobe32a(&h2[4], reply_len); // expected answer size
DBG(24, "H1[6]: %02x %02x %02x %02x (%lu)\n", h1[6], h1[7], h1[8], h1[9], (u_long) (buf_size + 8));
DBG(24, "H2[0]: %02x %02x %02x %02x (%lu)\n", h2[0], h2[1], h2[2], h2[3], (u_long) buf_size);
DBG(24, "H2[4]: %02x %02x %02x %02x (%lu)\n", h2[4], h2[5], h2[6], h2[7], (u_long) reply_len);
}
if ((cmd >> 8) == 0x20 && (buf_size || reply_len)) {
// send header + data header
sanei_tcp_write(s->fd, packet, 12 + 8);
} else {
sanei_tcp_write(s->fd, packet, 12);
}
// send payload
if (buf_size)
sanei_tcp_write(s->fd, buf, buf_size);
free(packet);
*status = SANE_STATUS_GOOD;
return buf_size;
}
SANE_Status
epsonds_net_lock(struct epsonds_scanner *s)
{
SANE_Status status;
unsigned char buf[7] = "\x01\xa0\x04\x00\x00\x01\x2c";
DBG(1, "%s\n", __func__);
epsonds_net_write(s, 0x2100, buf, 7, 0, &status);
epsonds_net_read(s, buf, 1, &status);
// buf[0] should be ACK, 0x06
return status;
}
SANE_Status
epsonds_net_unlock(struct epsonds_scanner *s)
{
SANE_Status status;
DBG(1, "%s\n", __func__);
epsonds_net_write(s, 0x2101, NULL, 0, 0, &status);
/* epsonds_net_read(s, buf, 1, &status); */
return status;
}

Wyświetl plik

@ -0,0 +1,16 @@
#ifndef _EPSONDS_NET_H_
#define _EPSONDS_NET_H_
#include <sys/types.h>
#include "../include/sane/sane.h"
extern int epsonds_net_read(struct epsonds_scanner *s, unsigned char *buf, ssize_t buf_size,
SANE_Status *status);
extern int epsonds_net_write(struct epsonds_scanner *s, unsigned int cmd, const unsigned char *buf,
size_t buf_size, size_t reply_len,
SANE_Status *status);
extern SANE_Status epsonds_net_lock(struct epsonds_scanner *s);
extern SANE_Status epsonds_net_unlock(struct epsonds_scanner *s);
extern SANE_Status epsonds_net_request_read(epsonds_scanner *s, size_t len);
#endif

Wyświetl plik

@ -41,9 +41,12 @@
#include "sane/config.h"
#include <ctype.h>
#include <unistd.h>
#include "sane/saneopts.h"
#include "sane/sanei_config.h"
#include "sane/sanei_tcp.h"
#include "sane/sanei_udp.h"
#include "epsonds.h"
#include "epsonds-usb.h"
@ -51,6 +54,8 @@
#include "epsonds-cmd.h"
#include "epsonds-ops.h"
#include "epsonds-jpeg.h"
#include "epsonds-net.h"
/*
* Definition of the mode_param struct, that is used to
@ -115,6 +120,7 @@ max_string_size(const SANE_String_Const strings[])
}
static SANE_Status attach_one_usb(SANE_String_Const devname);
static SANE_Status attach_one_net(SANE_String_Const devname);
static void
print_params(const SANE_Parameters params)
@ -140,7 +146,10 @@ close_scanner(epsonds_scanner *s)
esci2_fin(s);
}
if (s->hw->connection == SANE_EPSONDS_USB) {
if (s->hw->connection == SANE_EPSONDS_NET) {
epsonds_net_unlock(s);
sanei_tcp_close(s->fd);
} else if (s->hw->connection == SANE_EPSONDS_USB) {
sanei_usb_close(s->fd);
}
@ -154,6 +163,49 @@ free:
DBG(7, "%s: ZZZ\n", __func__);
}
static void
e2_network_discovery(void)
{
fd_set rfds;
int fd, len;
SANE_Status status;
char *ip, *query = "EPSONP\x00\xff\x00\x00\x00\x00\x00\x00\x00";
unsigned char buf[76];
struct timeval to;
status = sanei_udp_open_broadcast(&fd);
if (status != SANE_STATUS_GOOD)
return;
sanei_udp_write_broadcast(fd, 3289, (unsigned char *) query, 15);
DBG(5, "%s, sent discovery packet\n", __func__);
to.tv_sec = 1;
to.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
sanei_udp_set_nonblock(fd, SANE_TRUE);
while (select(fd + 1, &rfds, NULL, NULL, &to) > 0) {
if ((len = sanei_udp_recvfrom(fd, buf, 76, &ip)) == 76) {
DBG(5, " response from %s\n", ip);
/* minimal check, protocol unknown */
if (strncmp((char *) buf, "EPSON", 5) == 0)
attach_one_net(ip);
}
}
DBG(5, "%s, end\n", __func__);
sanei_udp_close(fd);
}
static SANE_Status
open_scanner(epsonds_scanner *s)
{
@ -166,7 +218,52 @@ open_scanner(epsonds_scanner *s)
return SANE_STATUS_GOOD; /* no need to open the scanner */
}
if (s->hw->connection == SANE_EPSONDS_USB) {
if (s->hw->connection == SANE_EPSONDS_NET) {
unsigned char buf[5];
/* device name has the form net:ipaddr */
status = sanei_tcp_open(&s->hw->sane.name[4], 1865, &s->fd);
if (status == SANE_STATUS_GOOD) {
ssize_t read;
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
s->netlen = 0;
DBG(32, "awaiting welcome message\n");
/* the scanner sends a kind of welcome msg */
// XXX check command type, answer to connect is 0x80
read = eds_recv(s, buf, 3, &status);
if (read != 3) {
sanei_tcp_close(s->fd);
s->fd = -1;
return SANE_STATUS_IO_ERROR;
}
DBG(32, "welcome message received, locking the scanner...\n");
/* lock the scanner for use by sane */
status = epsonds_net_lock(s);
if (status != SANE_STATUS_GOOD) {
DBG(1, "%s cannot lock scanner: %s\n", s->hw->sane.name,
sane_strstatus(status));
sanei_tcp_close(s->fd);
s->fd = -1;
return status;
}
DBG(32, "scanner locked\n");
}
} else if (s->hw->connection == SANE_EPSONDS_USB) {
status = sanei_usb_open(s->hw->sane.name, &s->fd);
@ -224,12 +321,20 @@ device_detect(const char *name, int type, SANE_Status *status)
struct epsonds_scanner *s;
struct epsonds_device *dev;
DBG(1, "%s\n", __func__);
DBG(1, "%s, %s, type: %d\n", __func__, name, type);
/* try to find the device in our list */
for (dev = first_dev; dev; dev = dev->next) {
if (strcmp(dev->sane.name, name) == 0) {
DBG(1, " found cached device\n");
// the device might have been just probed, sleep a bit.
if (dev->connection == SANE_EPSONDS_NET) {
sleep(1);
}
return scanner_create(dev, status);
}
}
@ -254,8 +359,9 @@ device_detect(const char *name, int type, SANE_Status *status)
dev->connection = type;
dev->model = strdup("(undetermined)");
dev->name = strdup(name);
dev->sane.name = name;
dev->sane.name = dev->name;
dev->sane.vendor = "Epson";
dev->sane.model = dev->model;
dev->sane.type = "ESC/I-2";
@ -287,11 +393,11 @@ device_detect(const char *name, int type, SANE_Status *status)
if (*status != SANE_STATUS_GOOD)
goto close;
/* assume 1 and 8 bit are always supported */
// assume 1 and 8 bit are always supported
eds_add_depth(s->hw, 1);
eds_add_depth(s->hw, 8);
/* setup area according to available options */
// setup area according to available options
if (s->hw->has_fb) {
dev->x_range = &dev->fbf_x_range;
@ -353,6 +459,19 @@ attach_one_usb(const char *dev)
return attach(dev, SANE_EPSONDS_USB);
}
static SANE_Status
attach_one_net(const char *dev)
{
char name[39 + 4];
DBG(7, "%s: dev = %s\n", __func__, dev);
strcpy(name, "net:");
strcat(name, dev);
return attach(name, SANE_EPSONDS_NET);
}
static SANE_Status
attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)
{
@ -384,6 +503,16 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)
epsonds_usb_product_ids[i], attach_one_usb);
}
} else if (strncmp(line, "net", 3) == 0) {
/* remove the "net" sub string */
const char *name = sanei_config_skip_whitespace(line + 3);
if (strncmp(name, "autodiscovery", 13) == 0)
e2_network_discovery();
else
attach_one_net(name);
} else {
DBG(0, "unable to parse config line: %s\n", line);
}
@ -673,7 +802,11 @@ sane_open(SANE_String_Const name, SANE_Handle *handle)
} else {
if (strncmp(name, "libusb:", 7) == 0) {
if (strncmp(name, "net:", 4) == 0) {
s = device_detect(name, SANE_EPSONDS_NET, &status);
if (s == NULL)
return status;
} else if (strncmp(name, "libusb:", 7) == 0) {
s = device_detect(name, SANE_EPSONDS_USB, &status);
if (s == NULL)
return status;

Wyświetl plik

@ -10,3 +10,7 @@ usb
# e.g.:
# usb 0x4b8 0x14c
# Network
#
# net 192.168.1.123
net autodiscovery

Wyświetl plik

@ -87,7 +87,7 @@ typedef enum
{ /* hardware connection to the scanner */
SANE_EPSONDS_NODEV, /* default, no HW specified yet */
SANE_EPSONDS_USB, /* USB interface */
SANE_EPSONDS_NET /* network interface (unsupported)*/
SANE_EPSONDS_NET /* network interface */
} epsonds_conn_type;
/* hardware description */
@ -173,6 +173,10 @@ struct epsonds_scanner
struct jpeg_decompress_struct jpeg_cinfo;
struct jpeg_error_mgr jpeg_err;
SANE_Bool jpeg_header_seen;
/* network buffers */
unsigned char *netbuf, *netptr;
size_t netlen;
};
typedef struct epsonds_scanner epsonds_scanner;