kopia lustrzana https://gitlab.com/sane-project/backends
epsonds: Merge to master
rodzic
911be8af68
commit
1e88e1504e
|
@ -511,11 +511,20 @@ libepsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
|
|||
nodist_libsane_epsonds_la_SOURCES = epsonds-s.c
|
||||
libsane_epsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds
|
||||
libsane_epsonds_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
|
||||
if have_libavahi
|
||||
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_tcp.lo ../sanei/sanei_udp.lo \
|
||||
$(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SOCKET_LIBS) $(AVAHI_LIBS)
|
||||
else
|
||||
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_tcp.lo ../sanei/sanei_udp.lo \
|
||||
$(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SOCKET_LIBS)
|
||||
endif
|
||||
EXTRA_DIST += epsonds.conf.in
|
||||
|
||||
libfujitsu_la_SOURCES = fujitsu.c fujitsu.h fujitsu-scsi.h
|
||||
|
|
|
@ -134,6 +134,7 @@ static SANE_Status esci2_cmd(epsonds_scanner* s,
|
|||
SANE_Status status;
|
||||
unsigned int more;
|
||||
char header[13], rbuf[64]; /* add one more byte for header buffer to correct buffer overflow issue,*/
|
||||
char *buf;
|
||||
|
||||
DBG(8, "%s: %4s len %lu, payload len: %lu\n", __func__, cmd, len, plen);
|
||||
|
||||
|
@ -151,6 +152,21 @@ static SANE_Status esci2_cmd(epsonds_scanner* s,
|
|||
|
||||
// send RequestBlock, request immediate response if there's no payload
|
||||
status = eds_txrx(s, header, len, rbuf, (plen > 0) ? 0 : 64);
|
||||
|
||||
/* pointer to the token's value */
|
||||
buf = rbuf + 12;
|
||||
/* nrd / nrdBUSY */
|
||||
DBG(8, "buf = %s\n",buf);
|
||||
if (strncmp("#nrd", buf, 4) == 0) {
|
||||
buf += 4;
|
||||
DBG(8, "buf = %s\n",buf);
|
||||
if (strncmp("BUSY", buf, 4) == 0) {
|
||||
DBG(8, "device busy\n");
|
||||
DBG(8, "SANE_STATUS:%d\n", SANE_STATUS_DEVICE_BUSY);
|
||||
return SANE_STATUS_DEVICE_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != SANE_STATUS_GOOD) {
|
||||
return status;
|
||||
}
|
||||
|
@ -227,6 +243,21 @@ SANE_Status esci2_fin(epsonds_scanner *s)
|
|||
DBG(5, "%s\n", __func__);
|
||||
|
||||
status = esci2_cmd_simple(s, "FIN x0000000", NULL);
|
||||
|
||||
for(int i = 0; i < 10; i++) {
|
||||
|
||||
if(status == SANE_STATUS_DEVICE_BUSY || status == SANE_STATUS_IO_ERROR) {
|
||||
status = esci2_cmd_simple(s, "FIN x0000000", NULL);
|
||||
}
|
||||
else {
|
||||
DBG(1, "break\n");
|
||||
break;
|
||||
}
|
||||
DBG(1, "sleep(5)\n");
|
||||
sleep(5);
|
||||
|
||||
}
|
||||
|
||||
s->locked = 0;
|
||||
return status;
|
||||
}
|
||||
|
@ -264,13 +295,13 @@ static char *decode_binary(char *buf, int len)
|
|||
|
||||
memcpy(tmp, buf, 4);
|
||||
tmp[4] = '\0';
|
||||
len -= 4;
|
||||
|
||||
if (buf[0] != 'h')
|
||||
return NULL;
|
||||
|
||||
hl = strtol(tmp + 1, NULL, 16);
|
||||
if (hl > len) hl = len;
|
||||
if (hl > len)
|
||||
hl = len;
|
||||
if (hl) {
|
||||
|
||||
char *v = malloc(hl + 1);
|
||||
|
@ -313,9 +344,6 @@ static SANE_Status info_cb(void *userdata, char *token, int len)
|
|||
epsonds_scanner *s = (epsonds_scanner *)userdata;
|
||||
char *value;
|
||||
|
||||
if (DBG_LEVEL >= 11) {
|
||||
debug_token(DBG_LEVEL, __func__, token, len);
|
||||
}
|
||||
|
||||
/* pointer to the token's value */
|
||||
value = token + 3;
|
||||
|
@ -333,7 +361,6 @@ static SANE_Status info_cb(void *userdata, char *token, int len)
|
|||
s->hw->model = decode_string(value, len);
|
||||
s->hw->sane.model = s->hw->model;
|
||||
DBG(1, " product: %s\n", s->hw->model);
|
||||
/* we will free the string later */
|
||||
}
|
||||
|
||||
if (strncmp("VER", token, 3) == 0) {
|
||||
|
@ -421,6 +448,7 @@ static SANE_Status info_cb(void *userdata, char *token, int len)
|
|||
int max = decode_value(value + 4 + 8, 8);
|
||||
|
||||
DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max);
|
||||
eds_set_adf_area(s->hw, min, max, 100);
|
||||
}
|
||||
|
||||
if (strncmp("AMIN", value, 4) == 0) {
|
||||
|
@ -437,10 +465,39 @@ static SANE_Status info_cb(void *userdata, char *token, int len)
|
|||
int max = decode_value(value + 4 + 8, 8);
|
||||
|
||||
DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (len == 16) {
|
||||
|
||||
if (strncmp("AREA", value, 4) == 0) {
|
||||
|
||||
int min = decode_value(value + 4, 4);
|
||||
int max = decode_value(value + 4 + 4, 8);
|
||||
|
||||
DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max);
|
||||
|
||||
eds_set_adf_area(s->hw, min, max, 100);
|
||||
}
|
||||
|
||||
if (strncmp("AMAX", value, 4) == 0) {
|
||||
|
||||
// d
|
||||
int min = decode_value(value + 4, 4);
|
||||
// i
|
||||
int max = decode_value(value + 4 + 4, 8);
|
||||
|
||||
DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (len == 12) {
|
||||
|
||||
|
@ -483,6 +540,22 @@ static SANE_Status info_cb(void *userdata, char *token, int len)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (len == 16) {
|
||||
|
||||
/* AREAi0000850i0001400 */
|
||||
if (strncmp("AREA", value, 4) == 0) {
|
||||
//d
|
||||
int min = decode_value(value + 4, 4);
|
||||
//i
|
||||
int max = decode_value(value + 4 + 4, 8);
|
||||
|
||||
DBG(1, " FB: area %dx%d @ 100dpi\n", min, max);
|
||||
|
||||
eds_set_fbf_area(s->hw, min, max, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 8) {
|
||||
|
||||
if (strncmp("ALGNLEFT", value, len) == 0) {
|
||||
|
@ -602,6 +675,7 @@ static SANE_Status capa_cb(void *userdata, char *token, int len)
|
|||
|
||||
if (strncmp("ADFCRP ", token, 3 + 4) == 0) {
|
||||
DBG(1, " ADF: image cropping\n");
|
||||
s->hw->adf_has_crp = 1;
|
||||
}
|
||||
|
||||
if (strncmp("ADFFAST", token, 3 + 4) == 0) {
|
||||
|
@ -636,6 +710,23 @@ static SANE_Status capa_cb(void *userdata, char *token, int len)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (strncmp("COLLIST", token, 3 + 4) == 0)
|
||||
{
|
||||
char *p = token + 3 + 4;
|
||||
int count = (len - 4);
|
||||
int readBytes = 0;
|
||||
s->hw->has_mono = 0;
|
||||
while (readBytes < count) {
|
||||
if (strncmp(p, "M001", 4) == 0)
|
||||
{
|
||||
s->hw->has_mono = 1;
|
||||
}
|
||||
readBytes+=4;
|
||||
p+=4;
|
||||
}
|
||||
}
|
||||
|
||||
/* RSMRANGi0000050i0000600 */
|
||||
|
||||
if (strncmp("RSMRANG", token, 3 + 4) == 0) {
|
||||
|
@ -659,17 +750,24 @@ static SANE_Status capa_cb(void *userdata, char *token, int len)
|
|||
|
||||
char *p = token + 3 + 4;
|
||||
|
||||
if (p[0] == 'i') {
|
||||
|
||||
int i;
|
||||
int count = (len - 4) / 8;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
int count = (len - 4);
|
||||
int readBytes = 0;
|
||||
|
||||
while (readBytes < count) {
|
||||
if(*p == 'i')
|
||||
{
|
||||
eds_add_resolution(s->hw, decode_value(p, 8));
|
||||
p += 8;
|
||||
readBytes += 8;
|
||||
}else if(*p == 'd')
|
||||
{
|
||||
eds_add_resolution(s->hw, decode_value(p, 4));
|
||||
p += 4;
|
||||
readBytes +=4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
|
@ -684,16 +782,26 @@ SANE_Status esci2_capa(epsonds_scanner *s)
|
|||
|
||||
static SANE_Status stat_cb(void *userdata, char *token, int len)
|
||||
{
|
||||
/*
|
||||
epsonds_scanner *s = (epsonds_scanner *)userdata;
|
||||
char *value = token + 3;
|
||||
*/
|
||||
|
||||
userdata = userdata;
|
||||
|
||||
if (DBG_LEVEL >= 11) {
|
||||
debug_token(DBG_LEVEL, __func__, token, len);
|
||||
}
|
||||
|
||||
if (strncmp("ERR", token, 3) == 0) {
|
||||
if (strncmp("ADF PE ", value, len) == 0) {
|
||||
DBG(1, " PE : paper empty\n");
|
||||
return SANE_STATUS_NO_DOCS;
|
||||
}
|
||||
|
||||
if (strncmp("ADF OPN", value, len) == 0) {
|
||||
DBG(1, " conver open\n");
|
||||
return SANE_STATUS_COVER_OPEN;
|
||||
}
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -742,10 +850,10 @@ static SANE_Status para_cb(void *userdata, char *token, int len)
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status esci2_para(epsonds_scanner *s, char *parameters)
|
||||
SANE_Status esci2_para(epsonds_scanner *s, char *parameters, int len)
|
||||
{
|
||||
DBG(8, "%s: %s\n", __func__, parameters);
|
||||
return esci2_cmd(s, "PARAx0000000", 12, parameters, strlen(parameters), NULL, ¶_cb);
|
||||
return esci2_cmd(s, "PARAx0000000", 12, parameters, len, NULL, ¶_cb);
|
||||
}
|
||||
|
||||
SANE_Status esci2_mech(epsonds_scanner *s, char *parameters)
|
||||
|
@ -784,12 +892,105 @@ static SANE_Status img_cb(void *userdata, char *token, int len)
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
if (len == 12 && strncmp("pst", token, 3) == 0) {
|
||||
|
||||
s->dummy = decode_value(token + 3 + 4, 4);
|
||||
|
||||
DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
|
||||
__func__,
|
||||
decode_value(token + 3, 4),
|
||||
decode_value(token + 3 + 4 + 4, 4),
|
||||
s->dummy);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
if (len == 16 && strncmp("pst", token, 3) == 0) {
|
||||
|
||||
s->dummy = decode_value(token + 3 + 4, 4);
|
||||
|
||||
DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
|
||||
__func__,
|
||||
decode_value(token + 3, 4),
|
||||
decode_value(token + 3 + 4 + 4, 8),
|
||||
s->dummy);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
if (len == 20 && strncmp("pst", token, 3) == 0) {
|
||||
|
||||
s->dummy = decode_value(token + 3 + 8, 4);
|
||||
|
||||
DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n",
|
||||
__func__,
|
||||
decode_value(token + 3, 8),
|
||||
decode_value(token + 3 + 8 + 4, 8),
|
||||
s->dummy);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
// i0001696i0002347
|
||||
if (len == 16 && strncmp("pen", token, 3) == 0) {
|
||||
DBG(10, "%s: page end\n", __func__);
|
||||
s->eof = 1;
|
||||
if (s->isflatbedScan)
|
||||
{
|
||||
s->scanning = 0;
|
||||
}
|
||||
DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n",
|
||||
__func__,
|
||||
decode_value(token + 3, 8),
|
||||
decode_value(token + 3 + 8, 8),
|
||||
s->dummy);
|
||||
s->width_temp = decode_value(token + 3, 8);
|
||||
s->height_temp = decode_value(token + 3 + 8, 8);
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
|
||||
// d696i0002347
|
||||
if (len == 12 && strncmp("pen", token, 3) == 0) {
|
||||
DBG(10, "%s: page end\n", __func__);
|
||||
s->eof = 1;
|
||||
if (s->isflatbedScan)
|
||||
{
|
||||
s->scanning = 0;
|
||||
}
|
||||
|
||||
DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n",
|
||||
__func__,
|
||||
decode_value(token + 3, 4),
|
||||
decode_value(token + 3 + 4, 8),
|
||||
s->dummy);
|
||||
|
||||
s->width_temp = decode_value(token + 3, 4);
|
||||
s->height_temp = decode_value(token + 3 + 4, 8);
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
|
||||
// d696d2347
|
||||
if (len == 8 && strncmp("pen", token, 3) == 0) {
|
||||
DBG(10, "%s: page end\n", __func__);
|
||||
s->eof = 1;
|
||||
if (s->isflatbedScan)
|
||||
{
|
||||
s->scanning = 0;
|
||||
}
|
||||
DBG(10, "%s: pen width: %d, height: %d, dummy: %d\n",
|
||||
__func__,
|
||||
decode_value(token + 3, 4),
|
||||
decode_value(token + 3 + 4, 4),
|
||||
s->dummy);
|
||||
|
||||
s->width_temp = decode_value(token + 3, 4);
|
||||
s->height_temp = decode_value(token + 3 + 4, 4);
|
||||
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
|
||||
|
||||
/* typIMGA or typIMGB */
|
||||
if (len == 4 && strncmp("typ", token, 3) == 0) {
|
||||
|
||||
|
@ -807,6 +1008,7 @@ static SANE_Status img_cb(void *userdata, char *token, int len)
|
|||
char *cause = token + 3 + 4; /* OPN, PJ, PE, ERR, LTF, LOCK, DFED, DTCL, AUT, PERM */
|
||||
|
||||
s->scanning = 0;
|
||||
s->scanEnd = 1;
|
||||
|
||||
DBG(1, "%s: error on option %3.3s, cause %4.4s\n",
|
||||
__func__, option, cause);
|
||||
|
@ -831,6 +1033,8 @@ static SANE_Status img_cb(void *userdata, char *token, int len)
|
|||
}
|
||||
|
||||
if (len == 4 && strncmp("lftd000", token, 3 + 4) == 0) {
|
||||
DBG(1, "%s:lft ok\n", __func__);
|
||||
s->scanEnd = 1;
|
||||
s->scanning = 0;
|
||||
}
|
||||
|
||||
|
@ -846,6 +1050,8 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
|
|||
unsigned int more;
|
||||
ssize_t read;
|
||||
|
||||
DBG(15, "esci2_img start\n");
|
||||
|
||||
*length = 0;
|
||||
|
||||
if (s->canceling)
|
||||
|
@ -856,6 +1062,7 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
|
|||
if (status != SANE_STATUS_GOOD) {
|
||||
return status;
|
||||
}
|
||||
DBG(15, "request img OK\n");
|
||||
|
||||
/* receive DataHeaderBlock */
|
||||
memset(s->buf, 0x00, 64);
|
||||
|
@ -863,6 +1070,7 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
|
|||
if (status != SANE_STATUS_GOOD) {
|
||||
return status;
|
||||
}
|
||||
DBG(15, "receive img OK\n");
|
||||
|
||||
/* check if we need to read any image data */
|
||||
more = 0;
|
||||
|
@ -873,6 +1081,17 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
|
|||
/* this handles eof and errors */
|
||||
parse_status = esci2_parse_block((char *)s->buf + 12, 64 - 12, s, &img_cb);
|
||||
|
||||
if (s->backside)
|
||||
{
|
||||
s->width_back = s->width_temp;
|
||||
s->height_back = s->height_temp;
|
||||
}else{
|
||||
s->width_front = s->width_temp;
|
||||
s->height_front = s->height_temp;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* no more data? return using the status of the esci2_parse_block
|
||||
* call, which might hold other error conditions.
|
||||
*/
|
||||
|
@ -884,7 +1103,6 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
|
|||
if (more > s->bsz) {
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/* ALWAYS read image data */
|
||||
if (s->hw->connection == SANE_EPSONDS_NET) {
|
||||
epsonds_net_request_read(s, more);
|
||||
|
|
|
@ -20,7 +20,7 @@ SANE_Status esci2_can(epsonds_scanner *s);
|
|||
SANE_Status esci2_capa(epsonds_scanner *s);
|
||||
SANE_Status esci2_resa(epsonds_scanner *s);
|
||||
SANE_Status esci2_stat(epsonds_scanner *s);
|
||||
SANE_Status esci2_para(epsonds_scanner *s, char *parameters);
|
||||
SANE_Status esci2_para(epsonds_scanner *s, char *parameters, int len);
|
||||
SANE_Status esci2_mech(epsonds_scanner *s, char *parameters);
|
||||
SANE_Status esci2_trdt(epsonds_scanner *s);
|
||||
SANE_Status esci2_img(struct epsonds_scanner *s, SANE_Int *length) ;
|
||||
|
|
|
@ -20,19 +20,39 @@
|
|||
#include "epsonds.h"
|
||||
#include "epsonds-jpeg.h"
|
||||
#include "epsonds-ops.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
#define min(A,B) (((A)<(B)) ? (A) : (B))
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub;
|
||||
jmp_buf setjmp_buffer;
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr * my_error_ptr;
|
||||
|
||||
|
||||
METHODDEF(void) my_error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
(*cinfo->err->format_message) (cinfo, buffer);
|
||||
|
||||
DBG(10,"Jpeg decode error [%s]", buffer);
|
||||
}
|
||||
|
||||
LOCAL(struct jpeg_error_mgr *) jpeg_custom_error (struct my_error_mgr * err)
|
||||
{
|
||||
|
||||
struct jpeg_error_mgr* pRet = jpeg_std_error(&(err->pub));
|
||||
err->pub.error_exit = my_error_exit;
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct jpeg_source_mgr pub;
|
||||
|
||||
epsonds_scanner *s;
|
||||
JOCTET *buffer;
|
||||
|
||||
SANE_Byte *linebuffer;
|
||||
SANE_Int linebuffer_size;
|
||||
SANE_Int linebuffer_index;
|
||||
int length;
|
||||
}
|
||||
epsonds_src_mgr;
|
||||
|
||||
|
@ -50,22 +70,11 @@ METHODDEF(boolean)
|
|||
jpeg_fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
epsonds_src_mgr *src = (epsonds_src_mgr *)cinfo->src;
|
||||
int avail, size;
|
||||
|
||||
/* read from the scanner or the ring buffer */
|
||||
|
||||
avail = eds_ring_avail(src->s->current);
|
||||
if (avail == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* read from scanner if no data? */
|
||||
size = min(1024, avail);
|
||||
|
||||
eds_ring_read(src->s->current, src->buffer, size);
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = size;
|
||||
src->pub.bytes_in_buffer = src->length;
|
||||
DBG(18, "reading from ring buffer, %d left\n", src->length);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -87,27 +96,25 @@ jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
|||
}
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
eds_jpeg_start(epsonds_scanner *s)
|
||||
|
||||
void eds_decode_jpeg(epsonds_scanner*s, SANE_Byte *data, SANE_Int size, ring_buffer* ringBuffer, SANE_Int isBackSide, SANE_Int needToConvertBW)
|
||||
{
|
||||
struct jpeg_decompress_struct jpeg_cinfo;
|
||||
struct my_error_mgr jpeg_err;
|
||||
|
||||
{
|
||||
epsonds_src_mgr *src;
|
||||
|
||||
s->jpeg_cinfo.err = jpeg_std_error(&s->jpeg_err);
|
||||
jpeg_cinfo.err = jpeg_custom_error(&jpeg_err);
|
||||
|
||||
jpeg_create_decompress(&s->jpeg_cinfo);
|
||||
jpeg_create_decompress(&jpeg_cinfo);
|
||||
|
||||
s->jpeg_cinfo.src = (struct jpeg_source_mgr *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo,
|
||||
jpeg_cinfo.src = (struct jpeg_source_mgr *)(*jpeg_cinfo.mem->alloc_small)((j_common_ptr)&jpeg_cinfo,
|
||||
JPOOL_PERMANENT, sizeof(epsonds_src_mgr));
|
||||
|
||||
memset(s->jpeg_cinfo.src, 0x00, sizeof(epsonds_src_mgr));
|
||||
|
||||
src = (epsonds_src_mgr *)s->jpeg_cinfo.src;
|
||||
src->s = s;
|
||||
|
||||
src->buffer = (JOCTET *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo,
|
||||
JPOOL_PERMANENT,
|
||||
1024 * sizeof(JOCTET));
|
||||
|
||||
memset(jpeg_cinfo.src, 0x00, sizeof(epsonds_src_mgr));
|
||||
;
|
||||
src = (epsonds_src_mgr *)jpeg_cinfo.src;
|
||||
src->pub.init_source = jpeg_init_source;
|
||||
src->pub.fill_input_buffer = jpeg_fill_input_buffer;
|
||||
src->pub.skip_input_data = jpeg_skip_input_data;
|
||||
|
@ -115,112 +122,114 @@ eds_jpeg_start(epsonds_scanner *s)
|
|||
src->pub.term_source = jpeg_term_source;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
src->pub.next_input_byte = NULL;
|
||||
src->buffer = (JOCTET*)data;
|
||||
src->length = size;
|
||||
}
|
||||
{
|
||||
if (jpeg_read_header(&jpeg_cinfo, TRUE)) {
|
||||
|
||||
s->jpeg_header_seen = 0;
|
||||
if (jpeg_start_decompress(&jpeg_cinfo)) {
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
eds_jpeg_read_header(epsonds_scanner *s)
|
||||
{
|
||||
epsonds_src_mgr *src = (epsonds_src_mgr *)s->jpeg_cinfo.src;
|
||||
|
||||
if (jpeg_read_header(&s->jpeg_cinfo, TRUE)) {
|
||||
|
||||
s->jdst = sanei_jpeg_jinit_write_ppm(&s->jpeg_cinfo);
|
||||
|
||||
if (jpeg_start_decompress(&s->jpeg_cinfo)) {
|
||||
|
||||
int size;
|
||||
|
||||
DBG(3, "%s: w: %d, h: %d, components: %d\n",
|
||||
DBG(10,"%s: w: %d, h: %d, components: %d\n",
|
||||
__func__,
|
||||
s->jpeg_cinfo.output_width, s->jpeg_cinfo.output_height,
|
||||
s->jpeg_cinfo.output_components);
|
||||
|
||||
size = s->jpeg_cinfo.output_width * s->jpeg_cinfo.output_components * 1;
|
||||
|
||||
src->linebuffer = (*s->jpeg_cinfo.mem->alloc_large)((j_common_ptr)&s->jpeg_cinfo,
|
||||
JPOOL_PERMANENT, size);
|
||||
|
||||
src->linebuffer_size = 0;
|
||||
src->linebuffer_index = 0;
|
||||
|
||||
s->jpeg_header_seen = 1;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
} else {
|
||||
DBG(0, "%s: decompression failed\n", __func__);
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
jpeg_cinfo.output_width, jpeg_cinfo.output_height,
|
||||
jpeg_cinfo.output_components);
|
||||
}
|
||||
} else {
|
||||
DBG(0, "%s: cannot read JPEG header\n", __func__);
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eds_jpeg_finish(epsonds_scanner *s)
|
||||
{
|
||||
jpeg_destroy_decompress(&s->jpeg_cinfo);
|
||||
}
|
||||
|
||||
void
|
||||
eds_jpeg_read(SANE_Handle handle, SANE_Byte *data,
|
||||
SANE_Int max_length, SANE_Int *length)
|
||||
{
|
||||
epsonds_scanner *s = handle;
|
||||
|
||||
struct jpeg_decompress_struct cinfo = s->jpeg_cinfo;
|
||||
epsonds_src_mgr *src = (epsonds_src_mgr *)s->jpeg_cinfo.src;
|
||||
|
||||
int l;
|
||||
|
||||
*length = 0;
|
||||
|
||||
/* copy from line buffer if available */
|
||||
if (src->linebuffer_size && src->linebuffer_index < src->linebuffer_size) {
|
||||
|
||||
*length = src->linebuffer_size - src->linebuffer_index;
|
||||
|
||||
if (*length > max_length)
|
||||
*length = max_length;
|
||||
|
||||
memcpy(data, src->linebuffer + src->linebuffer_index, *length);
|
||||
src->linebuffer_index += *length;
|
||||
|
||||
return;
|
||||
}
|
||||
{
|
||||
int sum = 0;
|
||||
int bufSize = jpeg_cinfo.output_width * jpeg_cinfo.output_components;
|
||||
|
||||
if (cinfo.output_scanline >= cinfo.output_height) {
|
||||
*length = 0;
|
||||
return;
|
||||
}
|
||||
int monoBufSize = (jpeg_cinfo.output_width + 7)/8;
|
||||
|
||||
/* scanlines of decompressed data will be in s->jdst->buffer
|
||||
* only one line at time is supported
|
||||
*/
|
||||
|
||||
l = jpeg_read_scanlines(&cinfo, s->jdst->buffer, 1);
|
||||
JSAMPARRAY scanlines = (jpeg_cinfo.mem->alloc_sarray)((j_common_ptr)&jpeg_cinfo, JPOOL_IMAGE, bufSize, 1);
|
||||
while (jpeg_cinfo.output_scanline < jpeg_cinfo.output_height) {
|
||||
int l = jpeg_read_scanlines(&jpeg_cinfo, scanlines, 1);
|
||||
if (l == 0) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
sum += l;
|
||||
|
||||
if (needToConvertBW)
|
||||
{
|
||||
SANE_Byte* bytes = scanlines[0];
|
||||
|
||||
SANE_Int imgPos = 0;
|
||||
|
||||
for (int i = 0; i < monoBufSize; i++)
|
||||
{
|
||||
SANE_Byte outByte = 0;
|
||||
|
||||
for(SANE_Int bitIndex = 0; bitIndex < 8 && imgPos < bufSize; bitIndex++) {
|
||||
//DBG(10,"bytes[imgPos] = %d\n", bytes[imgPos]);
|
||||
|
||||
if(bytes[imgPos] >= 110) {
|
||||
SANE_Byte bit = 7 - (bitIndex % 8);
|
||||
outByte |= (1<< bit);
|
||||
}
|
||||
imgPos += 1;
|
||||
}
|
||||
//DBG(10,"outByte = %d\n", outByte);
|
||||
eds_ring_write(ringBuffer, &outByte, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eds_ring_write(ringBuffer, scanlines[0], bufSize);
|
||||
}
|
||||
|
||||
/* from s->jdst->buffer to linebuffer
|
||||
* linebuffer holds width * bytesperpixel
|
||||
*/
|
||||
// decode until valida data
|
||||
if (isBackSide)
|
||||
{
|
||||
if (sum >= s->height_back)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}else
|
||||
{
|
||||
if (sum >= s->height_front)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DBG(10,"decodded lines = %d\n", sum);
|
||||
|
||||
(*s->jdst->put_pixel_rows)(&cinfo, s->jdst, 1, (char *)src->linebuffer);
|
||||
// abandon unncessary data
|
||||
if ((JDIMENSION)sum < jpeg_cinfo.output_height)
|
||||
{
|
||||
// unncessary data
|
||||
while(1)
|
||||
{
|
||||
int l = jpeg_read_scanlines(&jpeg_cinfo, scanlines, 1);
|
||||
if (l == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*length = cinfo.output_width * cinfo.output_components * 1;
|
||||
src->linebuffer_size = *length;
|
||||
src->linebuffer_index = 0;
|
||||
// if not auto crop mode padding to lines
|
||||
if (s->val[OPT_ADF_CRP].w == 0)
|
||||
{
|
||||
unsigned char* padding = malloc(s->params.bytes_per_line);
|
||||
memset(padding, 255, s->params.bytes_per_line);
|
||||
DBG(10,"padding data lines = %d to %d pa \n", sum, s->params.lines);
|
||||
|
||||
if (*length > max_length)
|
||||
*length = max_length;
|
||||
while(sum < s->params.lines)
|
||||
{
|
||||
eds_ring_write(ringBuffer, padding, bufSize);
|
||||
sum++;
|
||||
}
|
||||
|
||||
memcpy(data, src->linebuffer + src->linebuffer_index, *length);
|
||||
src->linebuffer_index += *length;
|
||||
free(padding);
|
||||
padding = NULL;
|
||||
}
|
||||
}
|
||||
{
|
||||
jpeg_finish_decompress(&jpeg_cinfo);
|
||||
jpeg_destroy_decompress(&jpeg_cinfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10,8 +10,4 @@
|
|||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
SANE_Status eds_jpeg_start(epsonds_scanner *s);
|
||||
void eds_jpeg_finish(epsonds_scanner *s);
|
||||
SANE_Status eds_jpeg_read_header(epsonds_scanner *s);
|
||||
void eds_jpeg_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length);
|
||||
void eds_decode_jpeg(epsonds_scanner*s, SANE_Byte *data, SANE_Int size, ring_buffer* ringBuffer, SANE_Int isBackSide, SANE_Int needToConvertBW);
|
||||
|
|
|
@ -32,10 +32,19 @@
|
|||
|
||||
#include "sane/sanei_debug.h"
|
||||
|
||||
|
||||
static ssize_t
|
||||
epsonds_net_read_raw(epsonds_scanner *s, unsigned char *buf, ssize_t wanted,
|
||||
SANE_Status *status)
|
||||
{
|
||||
DBG(15, "%s: wanted: %ld\n", __func__, wanted);
|
||||
|
||||
if (wanted == 0)
|
||||
{
|
||||
*status = SANE_STATUS_GOOD;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ready;
|
||||
ssize_t read = -1;
|
||||
fd_set readable;
|
||||
|
@ -284,3 +293,228 @@ epsonds_net_unlock(struct epsonds_scanner *s)
|
|||
/* epsonds_net_read(s, buf, 1, &status); */
|
||||
return status;
|
||||
}
|
||||
#if WITH_AVAHI
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <avahi-client/lookup.h>
|
||||
#include <avahi-common/error.h>
|
||||
#include <avahi-common/simple-watch.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
|
||||
static AvahiSimplePoll *simple_poll = NULL;
|
||||
|
||||
static struct timeval borowseEndTime;
|
||||
|
||||
static int resolvedCount = 0;
|
||||
static int browsedCount = 0;
|
||||
static int waitResolver = 0;
|
||||
|
||||
typedef struct {
|
||||
AvahiClient* client;
|
||||
Device_Found_CallBack callBack;
|
||||
}EDSAvahiUserData;
|
||||
|
||||
static int my_avahi_simple_poll_loop(AvahiSimplePoll *s) {
|
||||
struct timeval currentTime;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int r = avahi_simple_poll_iterate(s, 1);
|
||||
if (r != 0)
|
||||
{
|
||||
if (r >= 0 || errno != EINTR)
|
||||
{
|
||||
DBG(10, "my_avahi_simple_poll_loop end\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (waitResolver) {
|
||||
gettimeofday(¤tTime, NULL);
|
||||
|
||||
if ((currentTime.tv_sec - borowseEndTime.tv_sec) >= 3)
|
||||
{
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
DBG(10, "resolve timeout\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
epsonds_resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interface,
|
||||
AVAHI_GCC_UNUSED AvahiProtocol protocol,
|
||||
AvahiResolverEvent event, const char *name,
|
||||
const char *type,
|
||||
const char *domain,
|
||||
const char *host_name,
|
||||
const AvahiAddress *address, uint16_t port, AvahiStringList *txt,
|
||||
AvahiLookupResultFlags flags,
|
||||
void *userdata)
|
||||
{
|
||||
// unused parameter
|
||||
(void)r;
|
||||
(void)type;
|
||||
(void)domain;
|
||||
(void)host_name;
|
||||
(void)port;
|
||||
(void)flags;
|
||||
EDSAvahiUserData* data = userdata;
|
||||
char ipAddr[AVAHI_ADDRESS_STR_MAX];
|
||||
|
||||
DBG(10, "epsonds_searchDevices resolve_callback\n");
|
||||
|
||||
|
||||
resolvedCount++;
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_RESOLVER_FAILURE:
|
||||
break;
|
||||
case AVAHI_RESOLVER_FOUND:
|
||||
avahi_address_snprint(ipAddr, sizeof(ipAddr), address);
|
||||
DBG(10, "epsonds_searchDevices name = %s \n", name);
|
||||
if (strlen(name) > 7)
|
||||
{
|
||||
if (strncmp(name, "EPSON", 5) == 0)
|
||||
{
|
||||
while(txt != NULL)
|
||||
{
|
||||
char* text = (char*)avahi_string_list_get_text(txt);
|
||||
DBG(10, "avahi string = %s\n", text);
|
||||
|
||||
if (strlen(text) > 4 && strncmp(text, "mdl=", 4) == 0)
|
||||
{
|
||||
if (data->callBack)
|
||||
{
|
||||
data->callBack(&text[4], ipAddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
txt = avahi_string_list_get_next(txt);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface,
|
||||
AvahiProtocol protocol, AvahiBrowserEvent event,
|
||||
const char *name, const char *type,
|
||||
const char *domain,
|
||||
AvahiLookupResultFlags flags,
|
||||
void* userdata)
|
||||
{
|
||||
DBG(10, "browse_callback event = %d\n", event);
|
||||
|
||||
//unused parameter
|
||||
(void)b;
|
||||
(void)flags;
|
||||
|
||||
EDSAvahiUserData *data = userdata;
|
||||
switch (event) {
|
||||
case AVAHI_BROWSER_FAILURE:
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
return;
|
||||
case AVAHI_BROWSER_NEW:
|
||||
DBG(10, "browse_callback name = %s\n", name);
|
||||
browsedCount++;
|
||||
if (!(avahi_service_resolver_new(data->client, interface, protocol, name,
|
||||
type, domain,
|
||||
AVAHI_PROTO_UNSPEC, 0,
|
||||
epsonds_resolve_callback, data)))
|
||||
{
|
||||
DBG(10, "avahi_service_resolver_new fails\n");
|
||||
break;
|
||||
}
|
||||
case AVAHI_BROWSER_REMOVE:
|
||||
break;
|
||||
case AVAHI_BROWSER_ALL_FOR_NOW:
|
||||
DBG(10, "AVAHI_BROWSER_ALL_FOR_NOW\n");
|
||||
gettimeofday(&borowseEndTime, NULL);
|
||||
|
||||
if (browsedCount > resolvedCount)
|
||||
{
|
||||
DBG(10, "WAIT RESOLVER\n");
|
||||
waitResolver = 1;
|
||||
}else{
|
||||
DBG(10, "QUIT POLL\n");
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
}
|
||||
break;
|
||||
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
||||
DBG(10, "AVAHI_BROWSER_CACHE_EXHAUSTED\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
client_callback(AvahiClient *c, AvahiClientState state,
|
||||
AVAHI_GCC_UNUSED void *userdata)
|
||||
{
|
||||
assert(c);
|
||||
if (state == AVAHI_CLIENT_FAILURE)
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
}
|
||||
|
||||
SANE_Status epsonds_searchDevices(Device_Found_CallBack deviceFoundCallBack)
|
||||
{
|
||||
int result = SANE_STATUS_GOOD;
|
||||
|
||||
AvahiClient *client = NULL;
|
||||
AvahiServiceBrowser *sb = NULL;
|
||||
|
||||
EDSAvahiUserData data;
|
||||
|
||||
resolvedCount = 0;
|
||||
browsedCount = 0;
|
||||
waitResolver = 0;
|
||||
|
||||
|
||||
int error = 0;
|
||||
DBG(10, "epsonds_searchDevices\n");
|
||||
|
||||
if (!(simple_poll = avahi_simple_poll_new())) {
|
||||
DBG(10, "avahi_simple_poll_new failed\n");
|
||||
result = SANE_STATUS_INVAL;
|
||||
goto fail;
|
||||
}
|
||||
client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0,
|
||||
client_callback, NULL, &error);
|
||||
if (!client) {
|
||||
DBG(10, "avahi_client_new failed %s\n", avahi_strerror(error));
|
||||
result = SANE_STATUS_INVAL;
|
||||
goto fail;
|
||||
}
|
||||
data.client = client;
|
||||
data.callBack = deviceFoundCallBack;
|
||||
|
||||
if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
|
||||
AVAHI_PROTO_UNSPEC, "_scanner._tcp",
|
||||
NULL, 0, browse_callback, &data))) {
|
||||
DBG(10, "avahi_service_browser_new failed: %s\n",
|
||||
avahi_strerror(avahi_client_errno(client)));
|
||||
result = SANE_STATUS_INVAL;
|
||||
goto fail;
|
||||
}
|
||||
my_avahi_simple_poll_loop(simple_poll);
|
||||
fail:
|
||||
if (sb)
|
||||
avahi_service_browser_free(sb);
|
||||
if (client)
|
||||
avahi_client_free(client);
|
||||
if (simple_poll)
|
||||
avahi_simple_poll_free(simple_poll);
|
||||
|
||||
DBG(10, "epsonds_searchDevices fin\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <sys/types.h>
|
||||
#include "../include/sane/sane.h"
|
||||
|
||||
typedef void (*Device_Found_CallBack) (const char* name, const char* ip);
|
||||
|
||||
extern ssize_t epsonds_net_read(struct epsonds_scanner *s, unsigned char *buf, ssize_t buf_size,
|
||||
SANE_Status *status);
|
||||
extern size_t epsonds_net_write(struct epsonds_scanner *s, unsigned int cmd, const unsigned char *buf,
|
||||
|
@ -13,4 +15,8 @@ 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);
|
||||
|
||||
#if WITH_AVAHI
|
||||
extern SANE_Status epsonds_searchDevices(Device_Found_CallBack deviceFoundCallBack);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,10 +28,9 @@
|
|||
extern struct mode_param mode_params[];
|
||||
|
||||
/* Define the different scan sources */
|
||||
|
||||
#define FBF_STR SANE_I18N("Flatbed")
|
||||
#define TPU_STR SANE_I18N("Transparency Unit")
|
||||
#define ADF_STR SANE_I18N("Automatic Document Feeder")
|
||||
#define STRING_FLATBED SANE_I18N("Flatbed")
|
||||
#define STRING_ADFFRONT SANE_I18N("ADF Front")
|
||||
#define STRING_ADFDUPLEX SANE_I18N("ADF Duplex")
|
||||
|
||||
extern SANE_String_Const source_list[];
|
||||
|
||||
|
@ -53,10 +52,13 @@ eds_dev_post_init(struct epsonds_device *dev)
|
|||
DBG(10, "%s\n", __func__);
|
||||
|
||||
if (dev->has_fb)
|
||||
*source_list_add++ = FBF_STR;
|
||||
*source_list_add++ = STRING_FLATBED;
|
||||
|
||||
if (dev->has_adf)
|
||||
*source_list_add++ = ADF_STR;
|
||||
*source_list_add++ = STRING_ADFFRONT;
|
||||
|
||||
if (dev->adf_is_duplex)
|
||||
*source_list_add++ = STRING_ADFDUPLEX;
|
||||
|
||||
if (source_list[0] == 0
|
||||
|| (dev->res_list[0] == 0 && dev->dpi_range.min == 0)
|
||||
|
@ -209,8 +211,6 @@ eds_init_parameters(epsonds_scanner *s)
|
|||
|
||||
memset(&s->params, 0, sizeof(SANE_Parameters));
|
||||
|
||||
s->dummy = 0;
|
||||
|
||||
/* setup depth according to our mode table */
|
||||
if (mode_params[s->val[OPT_MODE].w].depth == 1)
|
||||
s->params.depth = 1;
|
||||
|
@ -314,6 +314,7 @@ eds_init_parameters(epsonds_scanner *s)
|
|||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
#define min(A,B) (((A)<(B)) ? (A) : (B))
|
||||
|
||||
void
|
||||
eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_length,
|
||||
|
@ -322,17 +323,13 @@ eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_lengt
|
|||
int lines, available;
|
||||
int hw_line_size = (s->params.bytes_per_line + s->dummy);
|
||||
|
||||
/* trim max_length to a multiple of hw_line_size */
|
||||
max_length -= (max_length % hw_line_size);
|
||||
|
||||
/* check available data */
|
||||
available = eds_ring_avail(s->current);
|
||||
if (max_length > available)
|
||||
max_length = available;
|
||||
|
||||
lines = max_length / hw_line_size;
|
||||
lines = min(max_length / s->params.bytes_per_line, available / hw_line_size);
|
||||
|
||||
DBG(18, "copying %d lines (%d, %d)\n", lines, s->params.bytes_per_line, s->dummy);
|
||||
DBG(18, "copying %d lines (%d, %d, %d)\n", lines, s->params.bytes_per_line, s->dummy, s->params.depth);
|
||||
|
||||
/* need more data? */
|
||||
if (lines == 0) {
|
||||
|
@ -490,3 +487,12 @@ void eds_ring_flush(ring_buffer *ring)
|
|||
{
|
||||
eds_ring_skip(ring, ring->fill);
|
||||
}
|
||||
|
||||
void eds_ring_destory(ring_buffer *ring)
|
||||
{
|
||||
if (ring->ring)
|
||||
{
|
||||
free(ring->ring);
|
||||
ring->ring = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,3 +38,4 @@ extern SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size);
|
|||
extern SANE_Int eds_ring_skip(ring_buffer *ring, SANE_Int size);
|
||||
extern SANE_Int eds_ring_avail(ring_buffer *ring);
|
||||
extern void eds_ring_flush(ring_buffer *ring) ;
|
||||
extern void eds_ring_destory(ring_buffer *ring) ;
|
||||
|
|
|
@ -12,22 +12,3 @@
|
|||
*/
|
||||
|
||||
#include "epsonds-usb.h"
|
||||
|
||||
SANE_Word epsonds_usb_product_ids[] = {
|
||||
0x0145, /* DS-5500, DS-6500, DS-7500 */
|
||||
0x0146, /* DS-50000, DS-60000, DS-70000 */
|
||||
0x014c, /* DS-510 */
|
||||
0x014d, /* DS-560 */
|
||||
0x0150, /* DS-40 */
|
||||
0x0152, /* DS-760, DS-860 */
|
||||
0x0154, /* DS-520 */
|
||||
0x08bc, /* PX-M7050 Series, WF-8510/8590 Series */
|
||||
0x08cc, /* PX-M7050FX Series, WF-R8590 Series */
|
||||
0 /* last entry - this is used for devices that are specified
|
||||
in the config file as "usb <vendor> <product>" */
|
||||
};
|
||||
|
||||
int epsonds_get_number_of_ids(void)
|
||||
{
|
||||
return sizeof (epsonds_usb_product_ids) / sizeof (SANE_Word);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,4 @@
|
|||
|
||||
#define SANE_EPSONDS_VENDOR_ID (0x4b8)
|
||||
|
||||
extern SANE_Word epsonds_usb_product_ids[];
|
||||
extern int epsonds_get_number_of_ids(void);
|
||||
|
||||
#endif
|
||||
|
|
2682
backend/epsonds.c
2682
backend/epsonds.c
Plik diff jest za duży
Load Diff
|
@ -10,7 +10,8 @@ usb
|
|||
# e.g.:
|
||||
# usb 0x4b8 0x14c
|
||||
|
||||
# Network (not yet supported!)
|
||||
#
|
||||
# Network
|
||||
#
|
||||
# net 192.168.1.123
|
||||
#net autodiscovery
|
||||
net autodiscovery
|
||||
|
|
|
@ -66,9 +66,14 @@
|
|||
#define TPU_STR SANE_I18N("Transparency Unit")
|
||||
#define ADF_STR SANE_I18N("Automatic Document Feeder")
|
||||
|
||||
#define STRING_FLATBED SANE_I18N("Flatbed")
|
||||
#define STRING_ADFFRONT SANE_I18N("ADF Front")
|
||||
#define STRING_ADFDUPLEX SANE_I18N("ADF Duplex")
|
||||
|
||||
enum {
|
||||
OPT_NUM_OPTS = 0,
|
||||
OPT_MODE_GROUP,
|
||||
OPT_STANDARD_GROUP,
|
||||
OPT_SOURCE,
|
||||
OPT_MODE,
|
||||
OPT_DEPTH,
|
||||
OPT_RESOLUTION,
|
||||
|
@ -78,11 +83,10 @@ enum {
|
|||
OPT_BR_X,
|
||||
OPT_BR_Y,
|
||||
OPT_EQU_GROUP,
|
||||
OPT_SOURCE,
|
||||
OPT_EJECT,
|
||||
OPT_LOAD,
|
||||
OPT_ADF_MODE,
|
||||
OPT_ADF_SKEW,
|
||||
OPT_ADF_CRP,
|
||||
NUM_OPTIONS
|
||||
};
|
||||
|
||||
|
@ -119,6 +123,8 @@ struct epsonds_device
|
|||
|
||||
SANE_Bool has_raw; /* supports RAW format */
|
||||
|
||||
SANE_Bool has_mono; /*supprt M001*/
|
||||
|
||||
SANE_Bool has_fb; /* flatbed */
|
||||
SANE_Range fbf_x_range; /* x range */
|
||||
SANE_Range fbf_y_range; /* y range */
|
||||
|
@ -136,9 +142,13 @@ struct epsonds_device
|
|||
SANE_Byte adf_alignment; /* left, center, right */
|
||||
SANE_Byte adf_has_dfd; /* supports double feed detection */
|
||||
|
||||
SANE_Byte adf_has_crp; /* supports crp */
|
||||
|
||||
SANE_Bool has_tpu; /* tpu */
|
||||
SANE_Range tpu_x_range; /* transparency unit x range */
|
||||
SANE_Range tpu_y_range; /* transparency unit y range */
|
||||
|
||||
SANE_Int lut_id;
|
||||
};
|
||||
|
||||
typedef struct epsonds_device epsonds_device;
|
||||
|
@ -171,6 +181,10 @@ struct epsonds_scanner
|
|||
|
||||
SANE_Int left, top, pages, dummy;
|
||||
|
||||
SANE_Int width_front, height_front;
|
||||
SANE_Int width_back , height_back;
|
||||
SANE_Int width_temp, height_temp;
|
||||
|
||||
/* jpeg stuff */
|
||||
|
||||
djpeg_dest_ptr jdst;
|
||||
|
@ -181,7 +195,18 @@ struct epsonds_scanner
|
|||
/* network buffers */
|
||||
unsigned char *netbuf, *netptr;
|
||||
size_t netlen;
|
||||
};
|
||||
|
||||
SANE_Byte *frontJpegBuf, *backJpegBuf;
|
||||
SANE_Int frontJpegBufLen, backJpegBufLen;
|
||||
SANE_Int acquirePage;
|
||||
|
||||
SANE_Int isflatbedScan;
|
||||
SANE_Int isDuplexScan;
|
||||
|
||||
SANE_Int needToConvertBW;
|
||||
|
||||
SANE_Int scanEnd;
|
||||
};
|
||||
|
||||
typedef struct epsonds_scanner epsonds_scanner;
|
||||
|
||||
|
|
|
@ -93,3 +93,253 @@
|
|||
:interface "USB"
|
||||
:usbid "0x04b8" "0x08cc"
|
||||
:status :untested
|
||||
|
||||
:model "DS-410"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0165"
|
||||
:status :complete
|
||||
|
||||
:model "ES-50"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x016c"
|
||||
:status :complete
|
||||
|
||||
:model "DS-70"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0160"
|
||||
:status :complete
|
||||
|
||||
:model "ES-55R"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x016d"
|
||||
:status :complete
|
||||
|
||||
:model "RR-60"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x018c"
|
||||
:status :complete
|
||||
|
||||
:model "ES-60W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x016e"
|
||||
:status :complete
|
||||
|
||||
:model "DS-80W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0166"
|
||||
:status :complete
|
||||
|
||||
:model "ES-65WR"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x016f"
|
||||
:status :complete
|
||||
|
||||
:model "RR-70W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x018b"
|
||||
:status :complete
|
||||
|
||||
:model "ES-60WW"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x016e"
|
||||
:status :complete
|
||||
|
||||
:model "ES-60WB"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x016e"
|
||||
:status :complete
|
||||
|
||||
:model "DS-1630"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x015c"
|
||||
:status :complete
|
||||
|
||||
:model "DS-1610"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x015d"
|
||||
:status :complete
|
||||
|
||||
:model "DS-1660W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x015e"
|
||||
:status :complete
|
||||
|
||||
:model "DS-310"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0159"
|
||||
:status :complete
|
||||
|
||||
:model "ES-200"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0159"
|
||||
:status :complete
|
||||
|
||||
:model "DS-320"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0162"
|
||||
:status :complete
|
||||
|
||||
:model "DS-360W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x015a"
|
||||
:status :complete
|
||||
|
||||
:model "ES-300W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x015a"
|
||||
:status :complete
|
||||
|
||||
:model "ES-300WR"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0177"
|
||||
:status :complete
|
||||
|
||||
:model "ES-400II"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0181"
|
||||
:status :complete
|
||||
|
||||
:model "DS-535II"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0183"
|
||||
:status :complete
|
||||
|
||||
:model "DS-531"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0184"
|
||||
:status :complete
|
||||
|
||||
:model "DS-530II"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0182"
|
||||
:status :complete
|
||||
|
||||
:model "ES-500WII"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0185"
|
||||
:status :complete
|
||||
|
||||
:model "DS-571W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0188"
|
||||
:status :complete
|
||||
|
||||
:model "DS-575WII"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0187"
|
||||
:status :complete
|
||||
|
||||
:model "DS-570WII"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0186"
|
||||
:status :complete
|
||||
|
||||
:model "ES-580W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x017f"
|
||||
:status :complete
|
||||
|
||||
:model "RR-600W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0180"
|
||||
:status :complete
|
||||
|
||||
:model "DS-535"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0167"
|
||||
:status :complete
|
||||
|
||||
:model "DS-535H"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x017a"
|
||||
:status :complete
|
||||
|
||||
:model "ES-400"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0156"
|
||||
:status :complete
|
||||
|
||||
:model "DS-530"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0155"
|
||||
:status :complete
|
||||
|
||||
:model "FF-680W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x016b"
|
||||
:status :complete
|
||||
|
||||
:model "DS-570W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0157"
|
||||
:status :complete
|
||||
|
||||
:model "ES-500W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0157"
|
||||
:status :complete
|
||||
|
||||
:model "DS-575W"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0169"
|
||||
:status :complete
|
||||
|
||||
:model "ES-500WR"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x0176"
|
||||
:status :complete
|
||||
|
||||
:model "EW-052A Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x114e"
|
||||
:status :complete
|
||||
|
||||
:model "XP-2100 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x114e"
|
||||
:status :complete
|
||||
|
||||
:model "ET-2700 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x1135"
|
||||
:status :complete
|
||||
|
||||
:model "L4150 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x1135"
|
||||
:status :complete
|
||||
|
||||
:model "ET-M2140 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x114a"
|
||||
:status :complete
|
||||
|
||||
:model "M2140 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x114a"
|
||||
:status :complete
|
||||
|
||||
:model "ET-M3140 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x114f"
|
||||
:status :complete
|
||||
|
||||
:model "M3140 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x114f"
|
||||
:status :complete
|
||||
|
||||
:model "L3150 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x1143"
|
||||
:status :complete
|
||||
|
||||
:model "ET-2710 Series"
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x1143"
|
||||
:status :complete
|
||||
|
||||
:model ""
|
||||
:interface "USB"
|
||||
:usbid "0x04b8" "0x00"
|
||||
:status :complete
|
||||
|
|
Ładowanie…
Reference in New Issue