kopia lustrzana https://gitlab.com/sane-project/backends
epsonds: added support for network scanners
rodzic
f13ca02b86
commit
9b389a61c5
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -10,3 +10,7 @@ usb
|
|||
# e.g.:
|
||||
# usb 0x4b8 0x14c
|
||||
|
||||
# Network
|
||||
#
|
||||
# net 192.168.1.123
|
||||
net autodiscovery
|
||||
|
|
|
@ -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;
|
||||
|
|
Ładowanie…
Reference in New Issue