epsonds: Merge to master

merge-requests/423/merge
Ralph Little 2021-07-03 15:55:25 -07:00
rodzic 911be8af68
commit 1e88e1504e
15 zmienionych plików z 3354 dodań i 489 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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,11 +465,40 @@ 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) {
/* RESOi0000600 */
@ -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, &para_cb);
return esci2_cmd(s, "PARAx0000000", 12, parameters, len, NULL, &para_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);

Wyświetl plik

@ -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) ;

Wyświetl plik

@ -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,140 +96,140 @@ 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)
{
epsonds_src_mgr *src;
struct jpeg_decompress_struct jpeg_cinfo;
struct my_error_mgr jpeg_err;
s->jpeg_cinfo.err = jpeg_std_error(&s->jpeg_err);
{
epsonds_src_mgr *src;
jpeg_create_decompress(&s->jpeg_cinfo);
jpeg_cinfo.err = jpeg_custom_error(&jpeg_err);
s->jpeg_cinfo.src = (struct jpeg_source_mgr *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo,
JPOOL_PERMANENT, sizeof(epsonds_src_mgr));
jpeg_create_decompress(&jpeg_cinfo);
memset(s->jpeg_cinfo.src, 0x00, sizeof(epsonds_src_mgr));
jpeg_cinfo.src = (struct jpeg_source_mgr *)(*jpeg_cinfo.mem->alloc_small)((j_common_ptr)&jpeg_cinfo,
JPOOL_PERMANENT, sizeof(epsonds_src_mgr));
src = (epsonds_src_mgr *)s->jpeg_cinfo.src;
src->s = s;
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;
src->pub.resync_to_restart = jpeg_resync_to_restart;
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)) {
src->buffer = (JOCTET *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo,
JPOOL_PERMANENT,
1024 * sizeof(JOCTET));
if (jpeg_start_decompress(&jpeg_cinfo)) {
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;
src->pub.resync_to_restart = jpeg_resync_to_restart;
src->pub.term_source = jpeg_term_source;
src->pub.bytes_in_buffer = 0;
src->pub.next_input_byte = NULL;
s->jpeg_header_seen = 0;
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;
}
if (cinfo.output_scanline >= cinfo.output_height) {
*length = 0;
return;
}
/* 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);
if (l == 0) {
return;
}
/* from s->jdst->buffer to linebuffer
* linebuffer holds width * bytesperpixel
*/
(*s->jdst->put_pixel_rows)(&cinfo, s->jdst, 1, (char *)src->linebuffer);
*length = cinfo.output_width * cinfo.output_components * 1;
src->linebuffer_size = *length;
src->linebuffer_index = 0;
if (*length > max_length)
*length = max_length;
memcpy(data, src->linebuffer + src->linebuffer_index, *length);
src->linebuffer_index += *length;
}
}
{
int sum = 0;
int bufSize = jpeg_cinfo.output_width * jpeg_cinfo.output_components;
int monoBufSize = (jpeg_cinfo.output_width + 7)/8;
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) {
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);
}
// 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);
// 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;
}
}
}
// 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);
while(sum < s->params.lines)
{
eds_ring_write(ringBuffer, padding, bufSize);
sum++;
}
free(padding);
padding = NULL;
}
}
{
jpeg_finish_decompress(&jpeg_cinfo);
jpeg_destroy_decompress(&jpeg_cinfo);
}
return;
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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(&currentTime, 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

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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) ;

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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

Plik diff jest za duży Load Diff

Wyświetl plik

@ -10,7 +10,8 @@ usb
# e.g.:
# usb 0x4b8 0x14c
# Network (not yet supported!)
#
# Network
#
# net 192.168.1.123
#net autodiscovery
net autodiscovery

Wyświetl plik

@ -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;

Wyświetl plik

@ -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