blob: 2c666bdec19e2bb8f45062aa07bd87f5985d7662 [file] [log] [blame]
commit 1e88e1504ef77f09d49da95d393a0af09d20f7fa
Author: Ralph Little <skelband@gmail.com>
Date: Sat Jul 3 15:55:25 2021 -0700
epsonds: Merge to master
diff --git a/backend/Makefile.am b/backend/Makefile.am
index 48a1393a5..ca282e4c6 100644
--- a/backend/Makefile.am
+++ b/backend/Makefile.am
@@ -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
diff --git a/backend/epsonds-cmd.c b/backend/epsonds-cmd.c
index 5141e0765..6f0ec6487 100644
--- a/backend/epsonds-cmd.c
+++ b/backend/epsonds-cmd.c
@@ -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);
diff --git a/backend/epsonds-cmd.h b/backend/epsonds-cmd.h
index 973609a03..2bd19dbb3 100644
--- a/backend/epsonds-cmd.h
+++ b/backend/epsonds-cmd.h
@@ -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) ;
diff --git a/backend/epsonds-jpeg.c b/backend/epsonds-jpeg.c
index 244f442ec..99ca53af2 100644
--- a/backend/epsonds-jpeg.c
+++ b/backend/epsonds-jpeg.c
@@ -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;
}
diff --git a/backend/epsonds-jpeg.h b/backend/epsonds-jpeg.h
index a804dec9b..42f542d33 100644
--- a/backend/epsonds-jpeg.h
+++ b/backend/epsonds-jpeg.h
@@ -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);
diff --git a/backend/epsonds-net.c b/backend/epsonds-net.c
index 3c8be2931..4f4c1e267 100644
--- a/backend/epsonds-net.c
+++ b/backend/epsonds-net.c
@@ -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
diff --git a/backend/epsonds-net.h b/backend/epsonds-net.h
index 107301bdc..2431c3594 100644
--- a/backend/epsonds-net.h
+++ b/backend/epsonds-net.h
@@ -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
diff --git a/backend/epsonds-ops.c b/backend/epsonds-ops.c
index 8b9d11586..56194c428 100644
--- a/backend/epsonds-ops.c
+++ b/backend/epsonds-ops.c
@@ -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;
+ }
+}
diff --git a/backend/epsonds-ops.h b/backend/epsonds-ops.h
index fe503d60d..108d5444b 100644
--- a/backend/epsonds-ops.h
+++ b/backend/epsonds-ops.h
@@ -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) ;
diff --git a/backend/epsonds-usb.c b/backend/epsonds-usb.c
index c7e514cb7..dacfd5fa1 100644
--- a/backend/epsonds-usb.c
+++ b/backend/epsonds-usb.c
@@ -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);
-}
diff --git a/backend/epsonds-usb.h b/backend/epsonds-usb.h
index 96c77b5b6..9baab701e 100644
--- a/backend/epsonds-usb.h
+++ b/backend/epsonds-usb.h
@@ -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
diff --git a/backend/epsonds.c b/backend/epsonds.c
index 1a7f953d0..06721c3d0 100644
--- a/backend/epsonds.c
+++ b/backend/epsonds.c
@@ -50,6 +50,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
+#include <math.h>
#include "sane/saneopts.h"
#include "sane/sanei_config.h"
@@ -64,7 +65,8 @@
#include "epsonds-jpeg.h"
#include "epsonds-net.h"
-
+static SANE_Status
+setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info);
/*
* Definition of the mode_param struct, that is used to
* specify the valid parameters for the different scan modes.
@@ -72,6 +74,1231 @@
* The depth variable gets updated when the bit depth is modified.
*/
+
+static unsigned char LUT[][256] =
+{
+ {// 0
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
+ 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+ 0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
+ 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
+ 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
+ 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
+ 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
+ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
+ 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
+ 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
+ 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
+ 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+ },
+ { // 1
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D,
+ 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20,
+ 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30,
+ 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E,
+ 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B,
+ 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58,
+ 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64,
+ 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70,
+ 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,
+ 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86,
+ 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91,
+ 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C,
+ 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6,
+ 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,
+ 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,
+ 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4,
+ 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD,
+ 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0,
+ 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,
+ 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3,
+ 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC,
+ 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ },
+ { // 2
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x16,0x19,0x1B,
+ 0x1D,0x1F,0x21,0x23,0x25,0x27,0x28,0x2A,
+ 0x2C,0x2E,0x30,0x32,0x33,0x35,0x37,0x39,
+ 0x3A,0x3C,0x3E,0x40,0x41,0x43,0x45,0x46,
+ 0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53,
+ 0x55,0x57,0x58,0x5A,0x5B,0x5D,0x5F,0x60,
+ 0x62,0x63,0x65,0x66,0x68,0x69,0x6B,0x6C,
+ 0x6E,0x6F,0x71,0x72,0x74,0x75,0x77,0x78,
+ 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,
+ 0x86,0x87,0x88,0x8A,0x8B,0x8D,0x8E,0x90,
+ 0x91,0x92,0x94,0x95,0x97,0x98,0x99,0x9B,
+ 0x9C,0x9E,0x9F,0xA0,0xA2,0xA3,0xA5,0xA7,
+ 0xA9,0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2,
+ 0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD,
+ 0xBE,0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8,
+ 0xC9,0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2,
+ 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD,
+ 0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,
+ 0xE8,0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1,
+ 0xF2,0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB,
+ 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ { // 3
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x07,
+ 0x08,0x0A,0x0C,0x0E,0x10,0x12,0x14,0x16,
+ 0x18,0x1A,0x1C,0x1E,0x20,0x22,0x24,0x26,
+ 0x28,0x2A,0x2B,0x2D,0x2F,0x31,0x33,0x34,
+ 0x36,0x38,0x39,0x3B,0x3D,0x3E,0x40,0x42,
+ 0x43,0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4F,
+ 0x50,0x52,0x53,0x55,0x56,0x58,0x59,0x5B,
+ 0x5D,0x5E,0x60,0x61,0x63,0x64,0x66,0x67,
+ 0x69,0x6A,0x6B,0x6D,0x6E,0x70,0x71,0x73,
+ 0x74,0x76,0x77,0x79,0x7A,0x7B,0x7D,0x7E,
+ 0x80,0x81,0x83,0x84,0x85,0x87,0x88,0x8A,
+ 0x8B,0x8C,0x8E,0x8F,0x90,0x92,0x93,0x95,
+ 0x96,0x97,0x99,0x9A,0x9B,0x9D,0x9E,0x9F,
+ 0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,
+ 0xAB,0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,
+ 0xB6,0xB7,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,
+ 0xC0,0xC2,0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,
+ 0xCB,0xCC,0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,
+ 0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,0xDF,
+ 0xE0,0xE1,0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,
+ 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3,
+ 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ { //4
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,
+ 0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10,
+ 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20,
+ 0x22,0x24,0x26,0x28,0x2A,0x2B,0x2D,0x2F,
+ 0x31,0x33,0x34,0x36,0x38,0x39,0x3B,0x3D,
+ 0x3E,0x40,0x42,0x43,0x45,0x47,0x48,0x4A,
+ 0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55,0x56,
+ 0x58,0x59,0x5B,0x5D,0x5E,0x60,0x61,0x63,
+ 0x64,0x66,0x67,0x69,0x6A,0x6B,0x6D,0x6E,
+ 0x70,0x71,0x73,0x74,0x76,0x77,0x79,0x7A,
+ 0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,0x85,
+ 0x87,0x88,0x8A,0x8B,0x8C,0x8E,0x8F,0x90,
+ 0x92,0x93,0x95,0x96,0x97,0x99,0x9A,0x9B,
+ 0x9D,0x9E,0x9F,0xA1,0xA2,0xA3,0xA5,0xA6,
+ 0xA7,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB1,
+ 0xB2,0xB3,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,
+ 0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC6,
+ 0xC7,0xC8,0xC9,0xCB,0xCC,0xCD,0xCF,0xD0,
+ 0xD1,0xD2,0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,
+ 0xDB,0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,0xE5,
+ 0xE6,0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,
+ 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9,
+ 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ { // 5
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x02,0x03,0x04,0x05,0x07,0x08,0x0A,
+ 0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,
+ 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A,
+ 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38,
+ 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45,
+ 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,
+ 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E,
+ 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A,
+ 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76,
+ 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81,
+ 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C,
+ 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97,
+ 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA2,
+ 0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD,
+ 0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7,
+ 0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,
+ 0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC,
+ 0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,
+ 0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0,
+ 0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB,
+ 0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5,
+ 0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ { // 6
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,
+ 0x10,0x12,0x14,0x16,0x18,0x18,0x1A,0x1C,
+ 0x1E,0x20,0x22,0x24,0x26,0x27,0x29,0x2B,
+ 0x2C,0x2E,0x30,0x31,0x33,0x35,0x36,0x38,
+ 0x39,0x3B,0x3C,0x3E,0x40,0x41,0x43,0x44,
+ 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50,
+ 0x51,0x52,0x54,0x55,0x56,0x58,0x59,0x5B,
+ 0x5C,0x5D,0x5F,0x60,0x61,0x63,0x64,0x65,
+ 0x67,0x68,0x69,0x6A,0x6C,0x6D,0x6E,0x70,
+ 0x71,0x72,0x73,0x75,0x76,0x77,0x78,0x7A,
+ 0x7B,0x7C,0x7D,0x7E,0x80,0x81,0x82,0x83,
+ 0x85,0x86,0x87,0x88,0x89,0x8A,0x8C,0x8D,
+ 0x8E,0x8F,0x90,0x92,0x93,0x94,0x95,0x96,
+ 0x97,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ 0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,
+ 0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,
+ 0xB2,0xB3,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,
+ 0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC4,
+ 0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,
+ 0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,
+ 0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,
+ 0xDE,0xDF,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,
+ 0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,
+ 0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,
+ 0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ { // 7
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C,
+ 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A,
+ 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37,
+ 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44,
+ 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50,
+ 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C,
+ 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67,
+ 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72,
+ 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D,
+ 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88,
+ 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92,
+ 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C,
+ 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6,
+ 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0,
+ 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA,
+ 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,
+ 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE,
+ 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1,
+ 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA,
+ 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,
+ 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ }
+};
+
+static unsigned char LUT_R[][256] =
+{
+ { // 0
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
+ 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+ 0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
+ 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
+ 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
+ 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
+ 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
+ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
+ 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
+ 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
+ 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
+ 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+ },
+ { // 1
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D,
+ 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20,
+ 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30,
+ 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E,
+ 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B,
+ 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58,
+ 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64,
+ 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70,
+ 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,
+ 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86,
+ 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91,
+ 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C,
+ 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6,
+ 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,
+ 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,
+ 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4,
+ 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD,
+ 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0,
+ 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,
+ 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3,
+ 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC,
+ 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ },
+ { // 2
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,
+ 0x10,0x12,0x14,0x16,0x19,0x1B,0x1D,0x1F,
+ 0x21,0x23,0x25,0x27,0x28,0x2A,0x2C,0x2E,
+ 0x30,0x32,0x33,0x35,0x37,0x39,0x3A,0x3C,
+ 0x3E,0x40,0x41,0x43,0x45,0x46,0x48,0x4A,
+ 0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,
+ 0x58,0x5A,0x5B,0x5D,0x5F,0x60,0x62,0x63,
+ 0x65,0x66,0x68,0x69,0x6B,0x6C,0x6E,0x6F,
+ 0x71,0x72,0x74,0x75,0x77,0x78,0x7A,0x7B,
+ 0x7D,0x7E,0x80,0x81,0x83,0x84,0x86,0x87,
+ 0x88,0x8A,0x8B,0x8D,0x8E,0x90,0x91,0x92,
+ 0x94,0x95,0x97,0x98,0x99,0x9B,0x9C,0x9E,
+ 0x9F,0xA0,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,
+ 0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2,0xB4,
+ 0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD,0xBE,
+ 0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8,0xC9,
+ 0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2,0xD4,
+ 0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD,0xDE,
+ 0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,
+ 0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1,0xF2,
+ 0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB,0xFC,
+ 0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x02,0x03,0x04,0x05,0x07,0x08,0x0A,
+ 0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,
+ 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A,
+ 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38,
+ 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45,
+ 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,
+ 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E,
+ 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A,
+ 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76,
+ 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81,
+ 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C,
+ 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97,
+ 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA2,
+ 0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD,
+ 0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7,
+ 0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,
+ 0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC,
+ 0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,
+ 0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0,
+ 0xE1,0xE3,0xE4,0xE5,0xE5,0xE6,0xE8,0xE9,
+ 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3,
+ 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,
+ 0x07,0x08,0x0A,0x0C,0x0E,0x10,0x12,0x14,
+ 0x16,0x18,0x1A,0x1C,0x1E,0x20,0x22,0x24,
+ 0x26,0x28,0x2A,0x2B,0x2D,0x2F,0x31,0x33,
+ 0x34,0x36,0x38,0x39,0x3B,0x3D,0x3E,0x40,
+ 0x42,0x43,0x45,0x47,0x48,0x4A,0x4B,0x4D,
+ 0x4F,0x50,0x52,0x53,0x55,0x56,0x58,0x59,
+ 0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64,0x66,
+ 0x67,0x69,0x6A,0x6B,0x6D,0x6E,0x70,0x71,
+ 0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,0x7D,
+ 0x7E,0x80,0x81,0x83,0x84,0x85,0x87,0x88,
+ 0x8A,0x8B,0x8C,0x8E,0x8F,0x90,0x92,0x93,
+ 0x95,0x96,0x97,0x99,0x9A,0x9B,0x9D,0x9E,
+ 0x9F,0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,
+ 0xAA,0xAB,0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,
+ 0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBD,0xBE,
+ 0xBF,0xC0,0xC2,0xC3,0xC4,0xC6,0xC7,0xC8,
+ 0xC9,0xCB,0xCC,0xCD,0xCF,0xD0,0xD1,0xD2,
+ 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,
+ 0xDE,0xDF,0xE0,0xE1,0xE3,0xE4,0xE5,0xE6,
+ 0xE8,0xE9,0xEA,0xEB,0xEB,0xED,0xEE,0xEF,
+ 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9,
+ 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,
+ 0x10,0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,
+ 0x20,0x22,0x24,0x26,0x28,0x2A,0x2B,0x2D,
+ 0x2F,0x31,0x33,0x34,0x36,0x38,0x39,0x3B,
+ 0x3D,0x3E,0x40,0x42,0x43,0x45,0x47,0x48,
+ 0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55,
+ 0x56,0x58,0x59,0x5B,0x5D,0x5E,0x60,0x61,
+ 0x63,0x64,0x66,0x67,0x69,0x6A,0x6B,0x6D,
+ 0x6E,0x70,0x71,0x73,0x74,0x76,0x77,0x79,
+ 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,
+ 0x85,0x87,0x88,0x8A,0x8B,0x8C,0x8E,0x8F,
+ 0x90,0x92,0x93,0x95,0x96,0x97,0x99,0x9A,
+ 0x9B,0x9D,0x9E,0x9F,0xA1,0xA2,0xA3,0xA5,
+ 0xA6,0xA7,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,
+ 0xB1,0xB2,0xB3,0xB5,0xB6,0xB7,0xB9,0xBA,
+ 0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,
+ 0xC6,0xC7,0xC8,0xC9,0xCB,0xCC,0xCD,0xCF,
+ 0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,0xD7,0xD9,
+ 0xDA,0xDB,0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,
+ 0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB,0xED,
+ 0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,
+ 0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x05,0x06,0x08,0x0A,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x19,0x1B,0x1D,
+ 0x1F,0x20,0x22,0x24,0x26,0x28,0x2A,0x2B,
+ 0x2D,0x2F,0x31,0x32,0x34,0x35,0x37,0x39,
+ 0x3A,0x3C,0x3D,0x3F,0x41,0x42,0x44,0x45,
+ 0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x4F,0x51,
+ 0x52,0x54,0x55,0x57,0x58,0x59,0x5B,0x5C,
+ 0x5E,0x5F,0x60,0x62,0x63,0x64,0x66,0x67,
+ 0x68,0x6A,0x6B,0x6C,0x6E,0x6F,0x70,0x72,
+ 0x73,0x74,0x75,0x77,0x78,0x79,0x7B,0x7C,
+ 0x7D,0x7E,0x80,0x81,0x82,0x83,0x85,0x86,
+ 0x87,0x88,0x89,0x8B,0x8C,0x8D,0x8E,0x90,
+ 0x91,0x92,0x93,0x94,0x96,0x97,0x98,0x99,
+ 0x9A,0x9B,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2,
+ 0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAB,0xAC,
+ 0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB4,0xB5,
+ 0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBD,0xBE,
+ 0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,
+ 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD6,0xD7,0xD8,
+ 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,
+ 0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xEA,
+ 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,
+ 0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,
+ 0xFB,0xFC,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C,
+ 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A,
+ 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37,
+ 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44,
+ 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50,
+ 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C,
+ 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67,
+ 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72,
+ 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D,
+ 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88,
+ 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92,
+ 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C,
+ 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6,
+ 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0,
+ 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA,
+ 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,
+ 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE,
+ 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1,
+ 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA,
+ 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,
+ 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ }
+};
+
+static unsigned char LUT_G[][256] =
+{
+ {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
+ 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+ 0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
+ 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
+ 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
+ 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
+ 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
+ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
+ 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
+ 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
+ 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
+ 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D,
+ 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20,
+ 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30,
+ 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E,
+ 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B,
+ 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58,
+ 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64,
+ 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70,
+ 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,
+ 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86,
+ 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91,
+ 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C,
+ 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6,
+ 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,
+ 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,
+ 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4,
+ 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD,
+ 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0,
+ 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,
+ 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3,
+ 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC,
+ 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x16,0x19,0x1B,
+ 0x1D,0x1F,0x21,0x23,0x25,0x27,0x28,0x2A,
+ 0x2C,0x2E,0x30,0x32,0x33,0x35,0x37,0x39,
+ 0x3A,0x3C,0x3E,0x40,0x41,0x43,0x45,0x46,
+ 0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53,
+ 0x55,0x57,0x58,0x5A,0x5B,0x5D,0x5F,0x60,
+ 0x62,0x63,0x65,0x66,0x68,0x69,0x6B,0x6C,
+ 0x6E,0x6F,0x71,0x72,0x74,0x75,0x77,0x78,
+ 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,
+ 0x86,0x87,0x88,0x8A,0x8B,0x8D,0x8E,0x90,
+ 0x91,0x92,0x94,0x95,0x97,0x98,0x99,0x9B,
+ 0x9C,0x9E,0x9F,0xA0,0xA2,0xA3,0xA5,0xA7,
+ 0xA9,0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2,
+ 0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD,
+ 0xBE,0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8,
+ 0xC9,0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2,
+ 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD,
+ 0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,
+ 0xE8,0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1,
+ 0xF2,0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB,
+ 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x07,
+ 0x08,0x0A,0x0C,0x0E,0x10,0x12,0x14,0x16,
+ 0x18,0x1A,0x1C,0x1E,0x20,0x22,0x24,0x26,
+ 0x28,0x2A,0x2B,0x2D,0x2F,0x31,0x33,0x34,
+ 0x36,0x38,0x39,0x3B,0x3D,0x3E,0x40,0x42,
+ 0x43,0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4F,
+ 0x50,0x52,0x53,0x55,0x56,0x58,0x59,0x5B,
+ 0x5D,0x5E,0x60,0x61,0x63,0x64,0x66,0x67,
+ 0x69,0x6A,0x6B,0x6D,0x6E,0x70,0x71,0x73,
+ 0x74,0x76,0x77,0x79,0x7A,0x7B,0x7D,0x7E,
+ 0x80,0x81,0x83,0x84,0x85,0x87,0x88,0x8A,
+ 0x8B,0x8C,0x8E,0x8F,0x90,0x92,0x93,0x95,
+ 0x96,0x97,0x99,0x9A,0x9B,0x9D,0x9E,0x9F,
+ 0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,
+ 0xAB,0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,
+ 0xB6,0xB7,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,
+ 0xC0,0xC2,0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,
+ 0xCB,0xCC,0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,
+ 0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,0xDF,
+ 0xE0,0xE1,0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,
+ 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3,
+ 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,
+ 0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10,
+ 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20,
+ 0x22,0x24,0x26,0x28,0x2A,0x2B,0x2D,0x2F,
+ 0x31,0x33,0x34,0x36,0x38,0x39,0x3B,0x3D,
+ 0x3E,0x40,0x42,0x43,0x45,0x47,0x48,0x4A,
+ 0x4B,0x4D,0x4F,0x50,0x52,0x53,0x55,0x56,
+ 0x58,0x59,0x5B,0x5D,0x5E,0x60,0x61,0x63,
+ 0x64,0x66,0x67,0x69,0x6A,0x6B,0x6D,0x6E,
+ 0x70,0x71,0x73,0x74,0x76,0x77,0x79,0x7A,
+ 0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,0x85,
+ 0x87,0x88,0x8A,0x8B,0x8C,0x8E,0x8F,0x90,
+ 0x92,0x93,0x95,0x96,0x97,0x99,0x9A,0x9B,
+ 0x9D,0x9E,0x9F,0xA1,0xA2,0xA3,0xA5,0xA6,
+ 0xA7,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB1,
+ 0xB2,0xB3,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,
+ 0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC6,
+ 0xC7,0xC8,0xC9,0xCB,0xCC,0xCD,0xCF,0xD0,
+ 0xD1,0xD2,0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,
+ 0xDB,0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,0xE5,
+ 0xE6,0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,
+ 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9,
+ 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x02,0x03,0x04,0x05,0x07,0x08,0x0A,
+ 0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,
+ 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A,
+ 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38,
+ 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45,
+ 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,
+ 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E,
+ 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A,
+ 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76,
+ 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81,
+ 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C,
+ 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97,
+ 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA2,
+ 0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD,
+ 0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7,
+ 0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,
+ 0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC,
+ 0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,
+ 0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0,
+ 0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB,
+ 0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5,
+ 0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,
+ 0x10,0x12,0x14,0x16,0x18,0x18,0x1A,0x1C,
+ 0x1E,0x20,0x22,0x24,0x26,0x27,0x29,0x2B,
+ 0x2C,0x2E,0x30,0x31,0x33,0x35,0x36,0x38,
+ 0x39,0x3B,0x3C,0x3E,0x40,0x41,0x43,0x44,
+ 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50,
+ 0x51,0x52,0x54,0x55,0x56,0x58,0x59,0x5B,
+ 0x5C,0x5D,0x5F,0x60,0x61,0x63,0x64,0x65,
+ 0x67,0x68,0x69,0x6A,0x6C,0x6D,0x6E,0x70,
+ 0x71,0x72,0x73,0x75,0x76,0x77,0x78,0x7A,
+ 0x7B,0x7C,0x7D,0x7E,0x80,0x81,0x82,0x83,
+ 0x85,0x86,0x87,0x88,0x89,0x8A,0x8C,0x8D,
+ 0x8E,0x8F,0x90,0x92,0x93,0x94,0x95,0x96,
+ 0x97,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ 0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,
+ 0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,
+ 0xB2,0xB3,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,
+ 0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC4,
+ 0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,
+ 0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,
+ 0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,
+ 0xDE,0xDF,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,
+ 0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,
+ 0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,
+ 0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ { // 7
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C,
+ 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A,
+ 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37,
+ 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44,
+ 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50,
+ 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C,
+ 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67,
+ 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72,
+ 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D,
+ 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88,
+ 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92,
+ 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C,
+ 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6,
+ 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0,
+ 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA,
+ 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,
+ 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE,
+ 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1,
+ 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA,
+ 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,
+ 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ }
+};
+
+static unsigned char LUT_B[][256] =
+{
+ {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
+ 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+ 0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
+ 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
+ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
+ 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
+ 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
+ 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
+ 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
+ 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
+ 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+ 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
+ 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
+ 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x06,0x07,0x09,0x0B,0x0D,
+ 0x10,0x12,0x14,0x17,0x19,0x1B,0x1E,0x20,
+ 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30,
+ 0x32,0x33,0x35,0x37,0x39,0x3B,0x3C,0x3E,
+ 0x40,0x41,0x43,0x45,0x46,0x48,0x4A,0x4B,
+ 0x4D,0x4F,0x50,0x52,0x53,0x55,0x57,0x58,
+ 0x5A,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64,
+ 0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6F,0x70,
+ 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,
+ 0x7D,0x7E,0x7F,0x81,0x82,0x84,0x85,0x86,
+ 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x90,0x91,
+ 0x92,0x94,0x95,0x96,0x98,0x99,0x9A,0x9C,
+ 0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6,
+ 0xA7,0xA8,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,
+ 0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,
+ 0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4,
+ 0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCC,0xCD,
+ 0xCF,0xD0,0xD1,0xD2,0xD3,0xD5,0xD6,0xD7,
+ 0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE0,
+ 0xE1,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,
+ 0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF3,
+ 0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFB,0xFC,
+ 0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x16,0x19,0x1B,
+ 0x1D,0x1F,0x21,0x23,0x25,0x27,0x28,0x2A,
+ 0x2C,0x2E,0x30,0x32,0x33,0x35,0x37,0x39,
+ 0x3A,0x3C,0x3E,0x40,0x41,0x43,0x45,0x46,
+ 0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,0x53,
+ 0x55,0x57,0x58,0x5A,0x5B,0x5D,0x5F,0x60,
+ 0x62,0x63,0x65,0x66,0x68,0x69,0x6B,0x6C,
+ 0x6E,0x6F,0x71,0x72,0x74,0x75,0x77,0x78,
+ 0x7A,0x7B,0x7D,0x7E,0x80,0x81,0x83,0x84,
+ 0x86,0x87,0x88,0x8A,0x8B,0x8D,0x8E,0x90,
+ 0x91,0x92,0x94,0x95,0x97,0x98,0x99,0x9B,
+ 0x9C,0x9E,0x9F,0xA0,0xA2,0xA3,0xA5,0xA7,
+ 0xA9,0xAA,0xAB,0xAD,0xAE,0xB0,0xB1,0xB2,
+ 0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,0xBC,0xBD,
+ 0xBE,0xC0,0xC1,0xC2,0xC4,0xC5,0xC6,0xC8,
+ 0xC9,0xCA,0xCC,0xCD,0xCE,0xD0,0xD1,0xD2,
+ 0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,0xDD,
+ 0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,
+ 0xE8,0xE9,0xEB,0xEC,0xED,0xEF,0xF0,0xF1,
+ 0xF2,0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB,
+ 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x07,0x08,
+ 0x0A,0x0C,0x0E,0x10,0x12,0x14,0x16,0x18,
+ 0x1A,0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,
+ 0x2A,0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,
+ 0x38,0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,
+ 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,
+ 0x52,0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,
+ 0x5E,0x60,0x61,0x63,0x64,0x66,0x67,0x69,
+ 0x6A,0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,
+ 0x76,0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,
+ 0x81,0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,
+ 0x8C,0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,
+ 0x97,0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,
+ 0xA2,0xA3,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,
+ 0xAD,0xAE,0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,
+ 0xB7,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,
+ 0xC2,0xC3,0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,
+ 0xCC,0xCD,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,
+ 0xD6,0xD7,0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,
+ 0xE0,0xE1,0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,
+ 0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3,
+ 0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
+ 0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10,0x12,
+ 0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20,0x22,
+ 0x24,0x26,0x28,0x2A,0x2B,0x2D,0x2F,0x31,
+ 0x33,0x34,0x36,0x38,0x39,0x3B,0x3D,0x3E,
+ 0x40,0x42,0x43,0x45,0x47,0x48,0x4A,0x4B,
+ 0x4D,0x4F,0x50,0x52,0x53,0x55,0x56,0x58,
+ 0x59,0x5B,0x5D,0x5E,0x60,0x61,0x63,0x64,
+ 0x66,0x67,0x69,0x6A,0x6B,0x6D,0x6E,0x70,
+ 0x71,0x73,0x74,0x76,0x77,0x79,0x7A,0x7B,
+ 0x7D,0x7E,0x80,0x81,0x83,0x84,0x85,0x87,
+ 0x88,0x8A,0x8B,0x8C,0x8E,0x8F,0x90,0x92,
+ 0x93,0x95,0x96,0x97,0x99,0x9A,0x9B,0x9D,
+ 0x9E,0x9F,0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,
+ 0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB1,0xB2,
+ 0xB3,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBD,
+ 0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC6,0xC7,
+ 0xC8,0xC9,0xCB,0xCC,0xCD,0xCF,0xD0,0xD1,
+ 0xD2,0xD4,0xD5,0xD6,0xD7,0xD9,0xDA,0xDB,
+ 0xDC,0xDE,0xDF,0xE0,0xE1,0xE3,0xE4,0xE5,
+ 0xE6,0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,
+ 0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9,
+ 0xFA,0xFB,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x02,0x03,0x04,0x05,0x07,0x08,0x0A,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x16,0x18,0x1A,
+ 0x1C,0x1E,0x20,0x22,0x24,0x26,0x28,0x2A,
+ 0x2B,0x2D,0x2F,0x31,0x33,0x34,0x36,0x38,
+ 0x39,0x3B,0x3D,0x3E,0x40,0x42,0x43,0x45,
+ 0x47,0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x52,
+ 0x53,0x55,0x56,0x58,0x59,0x5B,0x5D,0x5E,
+ 0x60,0x61,0x63,0x64,0x66,0x67,0x69,0x6A,
+ 0x6B,0x6D,0x6E,0x70,0x71,0x73,0x74,0x76,
+ 0x77,0x79,0x7A,0x7B,0x7D,0x7E,0x80,0x81,
+ 0x83,0x84,0x85,0x87,0x88,0x8A,0x8B,0x8C,
+ 0x8E,0x8F,0x90,0x92,0x93,0x95,0x96,0x97,
+ 0x99,0x9A,0x9B,0x9D,0x9E,0x9F,0xA1,0xA3,
+ 0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAD,0xAE,
+ 0xAF,0xB1,0xB2,0xB3,0xB5,0xB6,0xB7,0xB9,
+ 0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,
+ 0xC4,0xC6,0xC7,0xC8,0xC9,0xCB,0xCC,0xCD,
+ 0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,0xD7,
+ 0xD9,0xDA,0xDB,0xDC,0xDE,0xDF,0xE0,0xE1,
+ 0xE3,0xE4,0xE5,0xE6,0xE8,0xE9,0xEA,0xEB,
+ 0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5,
+ 0xF6,0xF8,0xF9,0xFA,0xFB,0xFD,0xFE,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,
+ 0x04,0x05,0x07,0x08,0x0A,0x0C,0x0E,0x10,
+ 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20,
+ 0x22,0x24,0x26,0x27,0x29,0x2B,0x2C,0x2E,
+ 0x30,0x31,0x33,0x35,0x36,0x38,0x39,0x3B,
+ 0x3C,0x3E,0x40,0x41,0x43,0x44,0x45,0x47,
+ 0x48,0x4B,0x4D,0x4E,0x50,0x51,0x52,0x54,
+ 0x55,0x56,0x58,0x59,0x5B,0x5C,0x5D,0x5F,
+ 0x60,0x61,0x63,0x64,0x65,0x67,0x68,0x69,
+ 0x6A,0x6C,0x6D,0x6E,0x70,0x71,0x72,0x73,
+ 0x75,0x76,0x77,0x78,0x7A,0x7B,0x7C,0x7D,
+ 0x7E,0x80,0x81,0x82,0x83,0x85,0x86,0x87,
+ 0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x8F,0x90,
+ 0x92,0x93,0x94,0x95,0x96,0x96,0x97,0x99,
+ 0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA1,0xA2,
+ 0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xAA,0xAB,
+ 0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,
+ 0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,
+ 0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC5,
+ 0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,
+ 0xCE,0xCF,0xD0,0xD1,0xD2,0xD4,0xD5,0xD6,
+ 0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,
+ 0xDF,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,
+ 0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,
+ 0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,
+ 0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ },
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,
+ 0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0C,
+ 0x0E,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C,
+ 0x1E,0x20,0x21,0x23,0x25,0x27,0x28,0x2A,
+ 0x2C,0x2D,0x2F,0x31,0x32,0x34,0x36,0x37,
+ 0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44,
+ 0x45,0x47,0x48,0x4A,0x4B,0x4D,0x4E,0x50,
+ 0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C,
+ 0x5D,0x5F,0x60,0x61,0x63,0x64,0x66,0x67,
+ 0x68,0x6A,0x6B,0x6D,0x6E,0x6F,0x71,0x72,
+ 0x73,0x75,0x76,0x78,0x79,0x7A,0x7C,0x7D,
+ 0x7E,0x80,0x81,0x82,0x84,0x85,0x86,0x88,
+ 0x89,0x8A,0x8B,0x8D,0x8E,0x8F,0x91,0x92,
+ 0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C,
+ 0x9E,0x9F,0xA0,0xA1,0xA3,0xA4,0xA5,0xA6,
+ 0xA8,0xA9,0xAA,0xAB,0xAD,0xAE,0xAF,0xB0,
+ 0xB2,0xB3,0xB4,0xB5,0xB7,0xB8,0xB9,0xBA,
+ 0xBC,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,
+ 0xC5,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE,
+ 0xCF,0xD0,0xD1,0xD3,0xD4,0xD5,0xD6,0xD7,
+ 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xE0,0xE1,
+ 0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEA,
+ 0xEB,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,
+ 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFC,0xFD,
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ }
+};
+//// profile array ////
+
+typedef struct
+{
+ int productID; // USB PID
+ char productName[50]; // ESCI/2 procduct name
+ char deviceID[50]; // device ID (same as bonjour mdl name)
+ int lutID; // look up table no
+}epsonds_profile_map;
+
+const epsonds_profile_map epsonds_models_predefined[] = {
+ {0x0145, "DS-5500","DS-5500", 7},
+ {0x0145, "DS-6500","DS-6500", 7},
+ {0x0145, "DS-7500","DS-7500", 7},
+ {0x0146, "DS-50000","DS-50000", 7},
+ {0x0146, "DS-60000","DS-60000", 7},
+ {0x0146, "DS-70000","DS-70000", 7},
+ {0x014C, "DS-510","DS-510", 7},
+ {0x0150, "DS-560","DS-560", 7},
+ {0x0152, "DS-40","DS-40", 7},
+ {0x014D, "DS-760","DS-760", 7},
+ {0x014D, "DS-860","DS-860", 7},
+ {0x0154, "DS-520","DS-520", 7},
+ {0x08BC, "PID 08BC","PX-M7050 Series", 7},
+ {0x08BC, "PID 08BC","WF-8510 Series", 7},
+ {0x08BC, "PID 08BC","WF-8590 Series", 7},
+ {0x08CC, "PID 08CC","PX-M7050FX Series", 7},
+ {0x08CC, "PID 08CC","WF-R8590 Series", 7},
+ {0x0165, "DS-410","DS-410", 7},
+ {0x016C, "ES-50","ES-50", 6},
+ {0x0160, "DS-70","DS-70", 6},
+ {0x016D, "ES-55R","ES-55R", 6},
+ {0x018C, "RR-60","RR-60", 6},
+ {0x016E, "ES-60W","ES-60W", 6},
+ {0x0166, "DS-80W","DS-80W", 6},
+ {0x016F, "ES-65WR","ES-65WR", 6},
+ {0x018B, "RR-70W","RR-70W", 6},
+ {0x016E, "ES-60WW","ES-60WW", 6},
+ {0x016E, "ES-60WB","ES-60WB", 6},
+ {0x015C, "DS-1630","DS-1630", 4},
+ {0x015D, "DS-1610","DS-1610", 4},
+ {0x015E, "DS-1660W","DS-1660W", 4},
+ {0x0159, "DS-310","DS-310", 5},
+ {0x0159, "ES-200","ES-200", 5},
+ {0x0162, "DS-320","DS-320", 5},
+ {0x015A, "DS-360W","DS-360W", 5},
+ {0x015A, "ES-300W","ES-300W", 5},
+ {0x0177, "ES-300WR","ES-300WR", 5},
+ {0x0181, "ES-400II","ES-400II", 2},
+ {0x0183, "DS-535II","DS-535II", 2},
+ {0x0184, "DS-531","DS-531", 2},
+ {0x0182, "DS-530II","DS-530II", 2},
+ {0x0185, "ES-500WII","ES-500WII", 2},
+ {0x0188, "DS-571W","DS-571W", 2},
+ {0x0187, "DS-575WII","DS-575WII", 2},
+ {0x0186, "DS-570WII","DS-570WII", 2},
+ {0x017F, "ES-580W","ES-580W", 2},
+ {0x0180, "RR-600W","RR-600W", 2},
+ {0x0167, "DS-535","DS-535", 2},
+ {0x017A, "DS-535H","DS-535H", 2},
+ {0x0156, "ES-400","ES-400", 2},
+ {0x0155, "DS-530","DS-530", 2},
+ {0x016B, "FF-680W","FF-680W", 2},
+ {0x0157, "DS-570W","DS-570W", 2},
+ {0x0157, "ES-500W","ES-500W", 2},
+ {0x0169, "DS-575W","DS-575W", 2},
+ {0x0176, "ES-500WR","ES-500WR", 2},
+ {0x114E, "PID 114E","EW-052A Series", 7},
+ {0x114E, "PID 114E","XP-2100 Series", 7},
+ {0x1135, "PID 1135","ET-2700 Series", 7},
+ {0x1135, "PID 1135","L4150 Series", 7},
+ {0x114A, "PID 114A","ET-M2140 Series", 7},
+ {0x114A, "PID 114A","M2140 Series", 7},
+ {0x114F, "PID 114F","ET-M3140 Series", 7},
+ {0x114F, "PID 114F","M3140 Series", 7},
+ {0x1143, "PID 1143","L3150 Series", 7},
+ {0x1143, "PID 1143","ET-2710 Series", 7},
+ {0x00, "","", 0x00 }
+};
+
+typedef struct
+{
+ epsonds_profile_map *array;
+ int used;
+ int size;
+}epsonds_profile_map_array;
+
+
+static epsonds_profile_map_array stProfileMapArray;
+
+static void insert_profile_map(epsonds_profile_map_array *a, epsonds_profile_map element);
+
+static void init_profile_maps(epsonds_profile_map_array *a, size_t initialSize) {
+ a->array = malloc(initialSize * sizeof(epsonds_profile_map));
+ a->used = 0;
+ a->size = initialSize;
+
+ for (int i = 0; epsonds_models_predefined[i].productID != 0; i++) {
+
+ //DBG(6, "epsonds_models_predefined[i].productID = %x\n", epsonds_models_predefined[i].productID );
+
+ insert_profile_map(a, epsonds_models_predefined[i]);
+ }
+}
+
+static void insert_profile_map(epsonds_profile_map_array *a, epsonds_profile_map element) {
+ if (a->used == a->size) {
+ a->size *= 2;
+ a->array = realloc(a->array, a->size * sizeof(epsonds_profile_map));
+ }
+ a->array[a->used++] = element;
+}
+
+static void free_profile_maps(epsonds_profile_map_array *a) {
+ free(a->array);
+ a->array = NULL;
+ a->used = a->size = 0;
+}
+/////////////////////////
+
+
struct mode_param mode_params[] = {
{0, 0x00, 0x30, 1},
{0, 0x00, 0x30, 8},
@@ -86,16 +1313,12 @@ static SANE_String_Const mode_list[] = {
NULL
};
-static const SANE_String_Const adf_mode_list[] = {
- SANE_I18N("Simplex"),
- SANE_I18N("Duplex"),
- NULL
-};
/* Define the different scan sources */
-#define FBF_STR SANE_I18N("Flatbed")
-#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")
/* order will be fixed: fb, adf, tpu */
SANE_String_Const source_list[] = {
@@ -129,6 +1352,9 @@ 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 SANE_Status acquire_jpeg_data(epsonds_scanner* s);
+static SANE_Status acquire_and_decode_jpeg_data(epsonds_scanner* s);
+static SANE_Status acquire_raw_data(epsonds_scanner* s);
static void
print_params(const SANE_Parameters params)
@@ -146,6 +1372,11 @@ close_scanner(epsonds_scanner *s)
{
DBG(7, "%s: fd = %d\n", __func__, s->fd);
+ if (s->scanning)
+ {
+ sane_cancel(s);
+ }
+
if (s->fd == -1)
goto free;
@@ -171,49 +1402,6 @@ 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)
{
@@ -230,7 +1418,7 @@ open_scanner(epsonds_scanner *s)
unsigned char buf[5];
/* device name has the form net:ipaddr */
- status = sanei_tcp_open(&s->hw->sane.name[4], 1865, &s->fd);
+ status = sanei_tcp_open(&s->hw->name[4], 1865, &s->fd);
if (status == SANE_STATUS_GOOD) {
ssize_t read;
@@ -272,12 +1460,10 @@ open_scanner(epsonds_scanner *s)
}
} else if (s->hw->connection == SANE_EPSONDS_USB) {
-
status = sanei_usb_open(s->hw->sane.name, &s->fd);
if (status == SANE_STATUS_GOOD) {
sanei_usb_set_timeout(USB_TIMEOUT);
- sanei_usb_clear_halt(s->fd);
}
} else {
@@ -307,7 +1493,6 @@ static struct epsonds_scanner *
scanner_create(struct epsonds_device *dev, SANE_Status *status)
{
struct epsonds_scanner *s;
-
s = malloc(sizeof(struct epsonds_scanner));
if (s == NULL) {
*status = SANE_STATUS_NO_MEM;
@@ -428,7 +1613,32 @@ device_detect(const char *name, int type, SANE_Status *status)
DBG(1, "scanner model: %s\n", dev->model);
- /* add this scanner to the device list */
+
+ s->hw->lut_id = 0;
+
+ for (int i = 0; i < stProfileMapArray.used; i++) {
+
+ epsonds_profile_map* map = &stProfileMapArray.array[i];
+
+
+ if (strcmp(map->productName, dev->model) == 0) {
+
+ {//Convert to user friendly model name
+ free(s->hw->model);
+
+ char* deviceName = (char*)malloc(strlen(map->deviceID) + 1);
+ memset(deviceName, 0, strlen(map->deviceID) + 1);
+ strncpy(deviceName, map->deviceID, strlen(map->deviceID));
+ s->hw->model = deviceName;
+ s->hw->sane.model = s->hw->model;
+ }
+ {// set lutid
+ s->hw->lut_id = map->lutID;
+ }
+ break;
+ }
+ }
+ DBG(1, "scanner lut_id: %d\n", s->hw->lut_id);
num_devices++;
dev->next = first_dev;
@@ -479,6 +1689,67 @@ attach_one_net(const char *dev)
return attach(name, SANE_EPSONDS_NET);
}
+static void found_net_device(const char* device_name, const char* ip)
+{
+ DBG(7, "Found %s: ip = %s\n", device_name, ip);
+
+ int foundSupportedDevice = 0;
+
+ // search models
+ for (int i = 0; i < stProfileMapArray.used; i++) {
+ if (strcmp(stProfileMapArray.array[i].deviceID, device_name) == 0) {
+ foundSupportedDevice = 1;
+ break;
+ }
+ }
+
+
+ if (foundSupportedDevice)
+ {
+ char name[39 + 4];
+
+ strcpy(name, "net:");
+ strncat(name, ip, 39);
+
+ int foundCache = 0;
+ // search cache and prents duplicated model
+ for (epsonds_device* dev = first_dev; dev; dev = dev->next) {
+ if (strcmp(dev->sane.name, name) == 0) {
+ foundCache = 1;
+ }
+ }
+ if (foundCache == 0)
+ {
+ attach(name, SANE_EPSONDS_NET);
+ }
+ }
+}
+
+static void
+splitProfileName(const char* input, int* outProductID, char *outProductName, char* outDeviceID, int* outLutID)
+{
+ char target[1024];
+ strncpy(target, input, 1023);
+
+ strtok(target, ":");//profile
+
+ //productID
+ char* pid = strtok(NULL, ",");
+ sscanf(pid, "%x", (unsigned int*)outProductID);
+
+ //productName
+ char* productName = strtok(NULL, ",");
+ strncpy(outProductName, productName, 49);
+
+ //deviceID
+ char* deviceID = strtok(NULL, ",");
+ strncpy(outDeviceID, deviceID, 49);
+
+ //lutID
+ char* lutID = strtok(NULL, ",");
+ sscanf(lutID, "%d", outLutID);
+}
+
static SANE_Status
attach_one_config(SANEI_Config __sane_unused__ *config, const char *line,
@@ -489,8 +1760,17 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line,
int len = strlen(line);
DBG(7, "%s: len = %d, line = %s\n", __func__, len, line);
+ if (strncmp(line, "profile", 7) == 0 ) {
+ DBG(7, " found profile device profile\n");
- if (sscanf(line, "usb %i %i", &vendor, &product) == 2) {
+ epsonds_profile_map profle_map;
+
+ splitProfileName(line, &profle_map.productID, profle_map.productName, profle_map.deviceID, &profle_map.lutID);
+
+ DBG(7, "Found profile : %x %s %s %d\n", profle_map.productID, profle_map.productName, profle_map.deviceID, profle_map.lutID);
+
+ insert_profile_map(&stProfileMapArray, profle_map);
+ }else if (sscanf(line, "usb %i %i", &vendor, &product) == 2) {
DBG(7, " user configured device\n");
@@ -501,15 +1781,11 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line,
} else if (strncmp(line, "usb", 3) == 0 && len == 3) {
- int i, numIds;
-
DBG(7, " probing usb devices\n");
- numIds = epsonds_get_number_of_ids();
-
- for (i = 0; i < numIds; i++) {
- sanei_usb_find_devices(SANE_EPSONDS_VENDOR_ID,
- epsonds_usb_product_ids[i], attach_one_usb);
+ for (int i = 0; i < stProfileMapArray.used; i++) {
+ int usbPid = stProfileMapArray.array[i].productID;
+ sanei_usb_find_devices(SANE_EPSONDS_VENDOR_ID, usbPid, attach_one_usb);
}
} else if (strncmp(line, "net", 3) == 0) {
@@ -520,11 +1796,17 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line,
sanei_config_skip_whitespace(line + 3);
if (strncmp(name, "autodiscovery", 13) == 0)
- e2_network_discovery();
+ {
+ #if WITH_AVAHI
+ epsonds_searchDevices(found_net_device);
+ #else
+ // currently does not support
+ //e2_network_discovery();
+ #endif
+ }
else
attach_one_net(name);
}
-
} else {
DBG(0, "unable to parse config line: %s\n", line);
}
@@ -564,6 +1846,9 @@ SANE_Status
sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
{
DBG_INIT();
+
+ init_profile_maps(&stProfileMapArray, 100);
+
DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__);
DBG(1, "epsonds backend, version %i.%i.%i\n",
@@ -582,6 +1867,7 @@ void
sane_exit(void)
{
DBG(5, "** %s\n", __func__);
+ free_profile_maps(&stProfileMapArray);
free_devices();
}
@@ -591,7 +1877,8 @@ sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)
int i;
epsonds_device *dev;
- DBG(5, "** %s\n", __func__);
+ DBG(5, "** %s local_only = %d \n", __func__, local_only);
+
probe_devices(local_only);
@@ -612,12 +1899,14 @@ sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)
*device_list = devlist;
+
return SANE_STATUS_GOOD;
}
static SANE_Status
init_options(epsonds_scanner *s)
{
+ DBG(5, "init_options\n");
int i;
for (i = 0; i < NUM_OPTIONS; i++) {
@@ -632,11 +1921,11 @@ init_options(epsonds_scanner *s)
s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
/* "Scan Mode" group: */
-
- s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode");
- s->opt[OPT_MODE_GROUP].desc = "";
- s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
- s->opt[OPT_MODE_GROUP].cap = 0;
+ s->opt[OPT_STANDARD_GROUP].name = SANE_NAME_STANDARD;
+ s->opt[OPT_STANDARD_GROUP].title = SANE_TITLE_STANDARD;
+ s->opt[OPT_STANDARD_GROUP].desc = SANE_DESC_STANDARD;
+ s->opt[OPT_STANDARD_GROUP].type = SANE_TYPE_GROUP;
+ s->opt[OPT_STANDARD_GROUP].cap = 0;
/* scan mode */
s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
@@ -761,18 +2050,6 @@ init_options(epsonds_scanner *s)
if (!s->hw->adf_has_load)
s->opt[OPT_LOAD].cap |= SANE_CAP_INACTIVE;
- s->opt[OPT_ADF_MODE].name = "adf-mode";
- s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode");
- s->opt[OPT_ADF_MODE].desc =
- SANE_I18N("Selects the ADF mode (simplex/duplex)");
- s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING;
- s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list);
- s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
- s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list;
- s->val[OPT_ADF_MODE].w = 0; /* simplex */
-
- if (!s->hw->adf_is_duplex)
- s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_ADF_SKEW].name = "adf-skew";
s->opt[OPT_ADF_SKEW].title = SANE_I18N("ADF Skew Correction");
@@ -781,8 +2058,26 @@ init_options(epsonds_scanner *s)
s->opt[OPT_ADF_SKEW].type = SANE_TYPE_BOOL;
s->val[OPT_ADF_SKEW].w = 0;
+
+ s->opt[OPT_ADF_CRP].name = "adf-crp";
+ s->opt[OPT_ADF_CRP].title = SANE_I18N("ADF CRP Correction");
+ s->opt[OPT_ADF_CRP].desc =
+ SANE_I18N("Enables ADF auto cropping"); //
+ s->opt[OPT_ADF_CRP].type = SANE_TYPE_BOOL;
+ s->val[OPT_ADF_CRP].w = 0;
+
+
if (!s->hw->adf_has_skew)
+ {
+ s->val[OPT_ADF_SKEW].w = 0;
s->opt[OPT_ADF_SKEW].cap |= SANE_CAP_INACTIVE;
+ }
+
+ if(!s->hw->adf_has_crp)
+ {
+ s->val[OPT_ADF_CRP].w = 0;
+ s->opt[OPT_ADF_CRP].cap |= SANE_CAP_INACTIVE;
+ }
return SANE_STATUS_GOOD;
}
@@ -793,6 +2088,8 @@ sane_open(SANE_String_Const name, SANE_Handle *handle)
SANE_Status status;
epsonds_scanner *s = NULL;
+
+
DBG(7, "** %s: name = '%s'\n", __func__, name);
/* probe if empty device name provided */
@@ -848,6 +2145,8 @@ sane_open(SANE_String_Const name, SANE_Handle *handle)
status = eds_lock(s);
}
+ setvalue((SANE_Handle)s, OPT_MODE, (void*)SANE_VALUE_SCAN_MODE_COLOR, NULL);
+
return status;
}
@@ -881,24 +2180,6 @@ search_string_list(const SANE_String_Const *list, SANE_String value)
return ((*list == NULL) ? NULL : list);
}
-static void
-activateOption(epsonds_scanner *s, SANE_Int option, SANE_Bool *change)
-{
- if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
- s->opt[option].cap &= ~SANE_CAP_INACTIVE;
- *change = SANE_TRUE;
- }
-}
-
-static void
-deactivateOption(epsonds_scanner *s, SANE_Int option, SANE_Bool *change)
-{
- if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
- s->opt[option].cap |= SANE_CAP_INACTIVE;
- *change = SANE_TRUE;
- }
-}
-
/*
* Handles setting the source (flatbed, transparency adapter (TPU),
* or auto document feeder (ADF)).
@@ -911,7 +2192,6 @@ static void
change_source(epsonds_scanner *s, SANE_Int optindex, char *value)
{
int force_max = SANE_FALSE;
- SANE_Bool dummy;
DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex,
value);
@@ -928,26 +2208,17 @@ change_source(epsonds_scanner *s, SANE_Int optindex, char *value)
force_max = SANE_TRUE;
}
- if (strcmp(ADF_STR, value) == 0) {
-
+ if (strcmp(STRING_ADFFRONT, value) == 0 || strcmp(STRING_ADFDUPLEX, value) == 0) {
s->hw->x_range = &s->hw->adf_x_range;
s->hw->y_range = &s->hw->adf_y_range;
s->hw->alignment = s->hw->adf_alignment;
- if (s->hw->adf_is_duplex) {
- activateOption(s, OPT_ADF_MODE, &dummy);
- } else {
- deactivateOption(s, OPT_ADF_MODE, &dummy);
- s->val[OPT_ADF_MODE].w = 0;
- }
} else if (strcmp(TPU_STR, value) == 0) {
s->hw->x_range = &s->hw->tpu_x_range;
s->hw->y_range = &s->hw->tpu_y_range;
- deactivateOption(s, OPT_ADF_MODE, &dummy);
-
} else {
/* neither ADF nor TPU active, assume FB */
@@ -995,7 +2266,6 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value)
break;
case OPT_MODE:
- case OPT_ADF_MODE:
case OPT_SOURCE:
strcpy((char *) value, sopt->constraint.string_list[sval->w]);
break;
@@ -1045,12 +2315,9 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
switch (option) {
- case OPT_ADF_MODE: /* simple lists */
- sval->w = optindex;
- break;
-
case OPT_ADF_SKEW:
case OPT_RESOLUTION:
+ case OPT_ADF_CRP:
sval->w = *((SANE_Word *) value);
reload = SANE_TRUE;
break;
@@ -1064,9 +2331,29 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
// fall through
case OPT_TL_X:
case OPT_TL_Y:
+
sval->w = *((SANE_Word *) value);
if (NULL != info)
*info |= SANE_INFO_RELOAD_PARAMS;
+
+ if (option == OPT_BR_X)
+ {
+ DBG(17, "OPT_BR_X = %d\n", sval->w);
+ }
+ if (option == OPT_BR_Y)
+ {
+ DBG(17, "OPT_BR_Y = %d\n", sval->w);
+ }
+ if (option == OPT_TL_X)
+ {
+ DBG(17, "OPT_TL_X = %d\n", sval->w);
+ }
+ if (option == OPT_TL_Y)
+ {
+ DBG(17, "OPT_TL_Y = %d\n", sval->w);
+ }
+ // adf crop set to off
+ s->val[OPT_ADF_CRP].w = 0;
break;
case OPT_SOURCE:
@@ -1076,6 +2363,8 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
case OPT_MODE:
{
+ DBG(17, " OPT_MODE = index %d\n", optindex);
+
/* use JPEG mode if RAW is not available when bpp > 1 */
if (optindex > 0 && !s->hw->has_raw) {
s->mode_jpeg = 1;
@@ -1152,6 +2441,183 @@ sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action,
return SANE_STATUS_INVAL;
}
+
+static void setBit (SANE_Byte* bytes, SANE_Int bitIndex, SANE_Bool isTrue)
+{
+ SANE_Int octet = bitIndex / 8;
+ SANE_Byte bit = 7 - (bitIndex % 8);
+
+ if (isTrue) {
+ bytes[octet] |= (1 << bit);
+ } else {
+ bytes[octet] &= ~(1 << bit);
+ }
+}
+
+static SANE_Bool getBit (SANE_Byte* bytes, SANE_Int bitIndex)
+{
+ SANE_Int octet = bitIndex / 8;
+ SANE_Byte mask = 1 << (7 - (bitIndex % 8));
+
+ if( bytes[octet] & mask ){
+ return SANE_TRUE;
+ }
+
+ return SANE_FALSE;
+}
+
+static void swapPixel1(SANE_Int x1,
+ SANE_Int y1,
+ SANE_Int x2,
+ SANE_Int y2,
+ SANE_Byte* bytes,
+ SANE_Byte bitsPerSample,
+ SANE_Int samplesPerPixel,
+ SANE_Int bytesPerRow)
+{
+ SANE_Int pixelBits = bitsPerSample * samplesPerPixel;
+ SANE_Int widthBits = bytesPerRow * 8;
+
+ SANE_Byte temp = getBit(bytes, widthBits * y1 + x1 * pixelBits);
+ {
+ SANE_Byte right = getBit(bytes, widthBits * y2 + x2 * pixelBits);
+ setBit(bytes, widthBits * y1 + x1 * pixelBits, right);
+ }
+ setBit(bytes, widthBits * y2 + x2 * pixelBits, temp);
+}
+
+static void swapPixel8(SANE_Int x1,
+ SANE_Int y1,
+ SANE_Int x2,
+ SANE_Int y2,
+ SANE_Byte* bytes,
+ SANE_Byte bitsPerSample,
+ SANE_Int samplesPerPixel,
+ SANE_Int bytesPerRow)
+{
+ SANE_Int pixelBytes = samplesPerPixel * bitsPerSample / 8;
+
+ for (SANE_Byte i = 0; i < pixelBytes; i++) {
+ SANE_Byte temp = bytes[y1 * bytesPerRow + (pixelBytes * x1 + i)];
+ bytes[y1 * bytesPerRow + (pixelBytes * x1 + i)] = bytes[y2 * bytesPerRow + (pixelBytes * x2 + i)];
+ bytes[y2 * bytesPerRow + (pixelBytes * x2 + i)] = temp;
+ }
+}
+
+
+
+static void swapPixel(SANE_Int x1,
+ SANE_Int y1,
+ SANE_Int x2,
+ SANE_Int y2,
+ SANE_Byte* bytes,
+ SANE_Byte bitsPerSample,
+ SANE_Int samplesPerPixel,
+ SANE_Int bytesPerRow)
+{
+ if (bitsPerSample == 1) {
+ swapPixel1(x1, y1, x2, y2, bytes, bitsPerSample, samplesPerPixel, bytesPerRow);
+ }else if(bitsPerSample == 8 || bitsPerSample == 16){
+ swapPixel8(x1, y1, x2, y2, bytes, bitsPerSample, samplesPerPixel, bytesPerRow);
+ }
+}
+
+
+void
+upside_down_backside_image(epsonds_scanner *s)
+{
+ // get all data from ring_buffer
+ if (eds_ring_avail(&s->back) &&
+ (strcmp(s->hw->sane.model, (char*)"DS-1630") == 0
+ || strcmp(s->hw->sane.model, (char*)"DS-1610") == 0
+ || strcmp(s->hw->sane.model, (char*)"DS-1660W") == 0))
+ {
+ SANE_Int bytesPerLine = s->params.bytes_per_line;
+ SANE_Int imageSize = bytesPerLine * s->height_back;
+
+ SANE_Byte* workBuffer = malloc(imageSize);
+ // if there is not enough memory, do nothing.
+ if (workBuffer)
+ {
+ eds_ring_read(&s->back, workBuffer, imageSize);
+ SANE_Int samplesPerPxel = 3;
+ if (s->params.format == SANE_FRAME_RGB)
+ {
+ samplesPerPxel = 3;
+ }
+ else if (s->params.format == SANE_FRAME_GRAY)
+ {
+ samplesPerPxel = 1;
+ }
+
+ SANE_Int half = (s->height_back / 2) - 1;
+ if (half < 0) {
+ half = 0;
+ }
+
+ if((s->height_back % 2) == 1) {
+ SANE_Int ymid = ( (s->height_back - 1 ) / 2 );
+ for(SANE_Int x = 0;x < (s->width_back / 2); x++) {
+ swapPixel(x, ymid, s->width_back - x - 1, ymid, workBuffer, s->params.depth, samplesPerPxel, s->params.bytes_per_line);
+ }
+ }
+
+ if (s->height_back != 1) {
+ for(SANE_Int x = 0; x < s->width_back; x++) {
+ for(SANE_Int y = 0;y <= half; y++) {
+ swapPixel(x, y, s->width_back - x - 1, s->height_back - y -1, workBuffer, s->params.depth, samplesPerPxel, s->params.bytes_per_line);
+ }
+ }
+ }
+
+ eds_ring_write(&s->back, workBuffer, imageSize);
+ free(workBuffer);
+ workBuffer = NULL;
+
+ }
+ }
+
+}
+
+
+SANE_Status
+get_next_image(epsonds_scanner *s)
+{
+ SANE_Status status = SANE_STATUS_GOOD;
+
+ if (s->acquirePage == 0 && s->current == &s->front)
+ {
+ DBG(20, "** %s: get_next_image\n", __func__);
+
+
+ /*page info will be updatted by pen*/
+ s->width_back = 0;
+ s->width_front = 0;
+ s->height_back = 0;
+ s->height_front = 0;
+
+ if (s->mode_jpeg)
+ {
+ status = acquire_and_decode_jpeg_data(s);
+ }else{
+ status = acquire_raw_data(s);
+ }
+ if (status != SANE_STATUS_GOOD)
+ {
+ eds_ring_flush(&s->front);
+ eds_ring_flush(&s->back);
+ eds_ring_destory(&s->front);
+ eds_ring_destory(&s->back);
+ }
+ DBG(20," ringFront = %d ringBack = %d\n", eds_ring_avail(&s->front), eds_ring_avail(&s->back));
+
+ s->acquirePage = 1;
+ }
+
+ return status;
+}
+
+
SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
{
@@ -1173,25 +2639,186 @@ sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
eds_init_parameters(s);
}
+
+ SANE_Status status = SANE_STATUS_GOOD;
+
+ status = get_next_image(s);
+
+ // if size auto, update page size value
+ if(s->val[OPT_ADF_CRP].w)
+ {
+ // frontside
+ if (s->current == &s->front)
+ {
+ DBG(20, "front side \n");
+ if (s->width_front != 0 && s->height_front != 0)
+ {
+ if (s->params.format == SANE_FRAME_RGB)
+ {
+ s->params.bytes_per_line = s->width_front * 3;
+ s->params.pixels_per_line = s->width_front;
+ }
+
+ if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 8)
+ {
+ s->params.bytes_per_line = s->width_front;
+ s->params.pixels_per_line = s->width_front;
+ }
+
+ if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 1)
+ {
+ s->params.bytes_per_line = (s->width_front + 7)/8;
+ s->params.pixels_per_line = s->width_front;
+ }
+ s->params.lines = s->height_front;
+ }
+ }
+ // backside
+ if (s->current == &s->back)
+ {
+ DBG(20, "back side \n");
+ if (s->width_back != 0 && s->height_back != 0)
+ {
+ if (s->params.format == SANE_FRAME_RGB)
+ {
+ s->params.bytes_per_line = s->width_back * 3;
+ s->params.pixels_per_line = s->width_back;
+ }
+
+ if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 8)
+ {
+ s->params.bytes_per_line = s->width_back;
+ s->params.pixels_per_line = s->width_back;
+ }
+
+ if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 1)
+ {
+ s->params.bytes_per_line = (s->width_back + 7)/8;
+ s->params.pixels_per_line = s->width_back;
+ }
+ s->params.lines = s->height_back;
+ }
+ }
+ }
if (params != NULL)
*params = s->params;
print_params(s->params);
- return SANE_STATUS_GOOD;
+ DBG(20, "s->params.line = %d s->params.bytes_per_line = %d s->params.pixels_per_line = %d \n", s->params.lines, s->params.bytes_per_line , s->params.pixels_per_line );
+ return status;
}
+
+
+typedef float ColorMatrix[3][3];
+
+#define CCT_TABLE_SIZE 9
+static int get_roundup_index(double frac[], int n)
+{
+ int i, index = -1;
+ double max_val = 0.0;
+
+ for (i=0; i<n; i++) {
+ if (frac[i]<0) continue;
+ if (max_val<frac[i]) {
+ index = i;
+ max_val = frac[i];
+ }
+ }
+ return index;
+}
+
+static int get_rounddown_index(double frac[], int n)
+{
+ int i, index = -1;
+ double min_val = 1.0;
+
+ for (i=0; i<n; i++) {
+ if (frac[i]>0) continue;
+ if (min_val>frac[i]) {
+ index = i;
+ min_val = frac[i];
+ }
+ }
+ return index;
+}
+
+
+void ESCIRoundColorCorrectionMatrix(int mult, double org_cct[], int rnd_cct[])
+{
+ int i, j, index;
+ double mult_cct[CCT_TABLE_SIZE], frac[CCT_TABLE_SIZE];
+ int sum[3];
+ int loop;
+
+ for (i=0; i<CCT_TABLE_SIZE; i++) {
+ mult_cct[i] = org_cct[i] * mult;
+ }
+
+ // round value multiplied by 'mult' off to integer.
+ for (i=0; i<CCT_TABLE_SIZE; i++) {
+ rnd_cct[i] = (int)floor(org_cct[i] * mult + 0.5);
+ }
+
+ loop=0;
+ do {
+ // If all element equal to 11, diagonal element is set to 10.
+ for (i=0; i<3; i++) {
+ if ( (rnd_cct[i*3]==11) &&
+ (rnd_cct[i*3]==rnd_cct[i*3+1]) &&
+ (rnd_cct[i*3]==rnd_cct[i*3+2]) ) {
+ rnd_cct[i*3+i] --;
+ mult_cct[i*3+i] = rnd_cct[i*3+i];
+ }
+ }
+ // calc. summation of each line.
+ for (i=0; i<3; i++) {
+ sum[i] = 0;
+ for (j=0; j<3; j++) {
+ sum[i] += rnd_cct[i*3+j];
+ }
+ }
+ // calc. values rounded up or down.
+ for (i=0; i<CCT_TABLE_SIZE; i++) {
+ frac[i] = mult_cct[i] - rnd_cct[i];
+ }
+
+ // if summation does not equal to 'mult', adjust rounded up or down value.
+ for (i=0; i<3; i++) {
+ if (sum[i]<mult) {
+ index = get_roundup_index(&frac[i*3], 3);
+ if (index!=-1) {
+ rnd_cct[i*3+index] ++;
+ mult_cct[i*3+index] = rnd_cct[i*3+index];
+ sum[i]++;
+ }
+ } else if (sum[i]>mult) {
+ index = get_rounddown_index(&frac[i*3], 3);
+ if (index!=-1) {
+ rnd_cct[i*3+index] --;
+ mult_cct[i*3+index] = rnd_cct[i*3+index];
+ sum[i]--;
+ }
+ }
+ }
+
+ } while ((++loop<2)&&((sum[0]!=mult)||(sum[1]!=mult)||(sum[2]!=mult)));
+}
+
+
+
/*
* This function is part of the SANE API and gets called from the front end to
* start the scan process.
*/
-
+#define CMD_BUF_SIZE 1000
SANE_Status
sane_start(SANE_Handle handle)
{
epsonds_scanner *s = (epsonds_scanner *)handle;
char buf[65]; /* add one more byte to correct buffer overflow issue */
- char cmd[100]; /* take care not to overflow */
+ char cmd[CMD_BUF_SIZE]; /* take care not to overflow */
SANE_Status status = 0;
s->pages++;
@@ -1203,26 +2830,28 @@ sane_start(SANE_Handle handle)
s->eof = 0;
s->canceling = 0;
+ s->acquirePage = 0;
if ((s->pages % 2) == 1) {
s->current = &s->front;
- eds_ring_flush(s->current);
} else if (eds_ring_avail(&s->back)) {
DBG(5, "back side\n");
s->current = &s->back;
}
- /* prepare the JPEG decompressor */
- if (s->mode_jpeg) {
- status = eds_jpeg_start(s);
- if (status != SANE_STATUS_GOOD) {
- goto end;
- } }
-
/* scan already in progress? (one pass adf) */
- if (s->scanning) {
+ if (s->scanning || eds_ring_avail(&s->back) > 0) {
DBG(5, " scan in progress, returning early\n");
- return SANE_STATUS_GOOD;
+ return get_next_image(s);
+ }
+ if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 || strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0) {
+ if (s->scanEnd)
+ {
+ s->scanEnd = 0;
+ return SANE_STATUS_NO_DOCS;
+ }
+ }else{
+ s->scanEnd = 0;
}
/* calc scanning parameters */
@@ -1239,13 +2868,7 @@ sane_start(SANE_Handle handle)
/* transfer buffer size, bsz */
/* XXX read value from scanner */
- s->bsz = (65536 * 4);
-
- /* ring buffer for front page */
- status = eds_ring_init(&s->front, s->bsz * 2);
- if (status != SANE_STATUS_GOOD) {
- return status;
- }
+ s->bsz = (1048576 * 4);
/* transfer buffer */
s->buf = realloc(s->buf, s->bsz);
@@ -1256,29 +2879,34 @@ sane_start(SANE_Handle handle)
/* set scanning parameters */
+ s->isDuplexScan = 0;
/* document source */
- if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) {
+ if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 || strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0) {
- sprintf(buf, "#ADF%s%s",
- s->val[OPT_ADF_MODE].w ? "DPLX" : "",
- s->val[OPT_ADF_SKEW].w ? "SKEW" : "");
-
- /* it seems that DFL only works in duplex mode, but it's
- * also required to be enabled or duplex will be rejected.
- */
-
- if (s->val[OPT_ADF_MODE].w) {
-
- if (s->hw->adf_has_dfd == 2) {
- strcat(buf, "DFL2");
- } else if (s->hw->adf_has_dfd == 1) {
- strcat(buf, "DFL1");
- }
+ SANE_Int status = esci2_stat(s);
+ if (status == SANE_STATUS_NO_DOCS)
+ {
+ return SANE_STATUS_NO_DOCS;
}
- } else if (strcmp(source_list[s->val[OPT_SOURCE].w], FBF_STR) == 0) {
+ SANE_Int duplexMode = (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0);
+
+ sprintf(buf, "#ADF%s%s%s",
+ duplexMode ? "DPLX" : "",
+ s->val[OPT_ADF_SKEW].w ? "SKEW" : "",
+ s->val[OPT_ADF_CRP].w ? "CRP " : ""
+ );
+
+ if (duplexMode)
+ {
+ s->isDuplexScan = 1;
+ }
+ s->isflatbedScan = 0;
+ }
+ else if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_FLATBED) == 0) {
strcpy(buf, "#FB ");
+ s->isflatbedScan = 1;
} else {
/* XXX */
@@ -1286,8 +2914,18 @@ sane_start(SANE_Handle handle)
strcpy(cmd, buf);
+ s->needToConvertBW = 0;
+
if (s->params.format == SANE_FRAME_GRAY) {
- sprintf(buf, "#COLM%03d", s->params.depth);
+ if (s->params.depth == 1 && s->hw->has_mono == 0)
+ {
+ sprintf(buf, "#COLM008");
+ s->needToConvertBW = 1;
+ s->mode_jpeg = 1;
+ }else
+ {
+ sprintf(buf, "#COLM%03d", s->params.depth);
+ }
} else if (s->params.format == SANE_FRAME_RGB) {
sprintf(buf, "#COLC%03d", s->params.depth * 3);
}
@@ -1303,9 +2941,29 @@ sane_start(SANE_Handle handle)
strcat(cmd, "#FMTJPG #JPGd090");
}
+ /* set GMM */
+ if (s->params.depth == 1)
+ {
+ sprintf(buf, "#GMMUG10");
+ } else
+ {
+ sprintf(buf, "#GMMUG18");
+ }
+ strcat(cmd, buf);
+
/* resolution (RSMi not always supported) */
- if (s->val[OPT_RESOLUTION].w > 999) {
+ if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 && s->val[OPT_RESOLUTION].w > 600) {
+ DBG(0, "Automatic Document Feeder supported resolution of 600dpi or less. \n");
+ } else if (s->val[OPT_RESOLUTION].w > 999) {
+ sprintf(buf, "#RSMi%07d#RSSi%07d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w);
+ } else {
+ sprintf(buf, "#RSMd%03d#RSSd%03d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w);
+ }
+
+ if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0 && s->val[OPT_RESOLUTION].w > 600) {
+ DBG(0, "Automatic Document Feeder supported resolution of 600dpi or less. \n");
+ } else if (s->val[OPT_RESOLUTION].w > 999) {
sprintf(buf, "#RSMi%07d#RSSi%07d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w);
} else {
sprintf(buf, "#RSMd%03d#RSSd%03d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w);
@@ -1313,13 +2971,321 @@ sane_start(SANE_Handle handle)
strcat(cmd, buf);
+ if (strcmp(s->hw->sane.model, (char*)"DS-70") == 0 || strcmp(s->hw->sane.model, (char*)"ES-65WR") == 0 || strcmp(s->hw->sane.model, (char*)"ES-60W") == 0
+ || strcmp(s->hw->sane.model, (char*)"DS-80W") == 0 || strcmp(s->hw->sane.model, (char*)"ES-55R") == 0 || strcmp(s->hw->sane.model, (char*)"ES-50") == 0){
+ sprintf(buf, "#BSZi0262144");
+ strcat(cmd, buf);
+ }
+ else {
+ sprintf(buf, "#BSZi1048576");
+ strcat(cmd, buf);
+ }
+
+
/* scanning area */
+
sprintf(buf, "#ACQi%07di%07di%07di%07d",
s->left, s->top, s->params.pixels_per_line, s->params.lines);
+
+ if (strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFFRONT) == 0 || strcmp(source_list[s->val[OPT_SOURCE].w], STRING_ADFDUPLEX) == 0) {
+ status = esci2_stat(s);
+ if (status != SANE_STATUS_GOOD) {
+ goto end;
+ }
+ }
+
strcat(cmd, buf);
- status = esci2_para(s, cmd);
+
+ int pos = 0;
+
+ {
+ for (int i = 0; i < CMD_BUF_SIZE; i++)
+ {
+ // find end of string
+ if(cmd[i] == 0)
+ {
+ pos = i;
+ break;
+ }
+ }
+
+
+ if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 8) {
+ DBG(10, "SANE_FRAME_GRAY\n");
+ cmd[pos++] = '#';
+ cmd[pos++] = 'G';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'T';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'O';
+ cmd[pos++] = 'N';
+ cmd[pos++] = 'O';
+ cmd[pos++] = 'h';
+ cmd[pos++] = '1';
+ cmd[pos++] = '0';
+ cmd[pos++] = '0';
+
+ for(int count = 0; count < 256; count++) {
+ cmd[pos++] = LUT[s->hw->lut_id][count];
+ }
+ }
+ if (s->params.format == SANE_FRAME_GRAY && s->params.depth == 1) {
+ DBG(10, "SANE_FRAME_GRAY\n");
+ cmd[pos++] = '#';
+ cmd[pos++] = 'G';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'T';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'O';
+ cmd[pos++] = 'N';
+ cmd[pos++] = 'O';
+ cmd[pos++] = 'h';
+ cmd[pos++] = '1';
+ cmd[pos++] = '0';
+ cmd[pos++] = '0';
+
+ for(int count = 0; count < 256; count++) {
+ cmd[pos++] = LUT[0][count];
+ }
+ }
+ else if (s->params.format == SANE_FRAME_RGB) {
+ DBG(10, "SANE_FRAME_RGB\n");
+ cmd[pos++] = '#';
+ cmd[pos++] = 'G';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'T';
+ cmd[pos++] = 'R';
+ cmd[pos++] = 'E';
+ cmd[pos++] = 'D';
+ cmd[pos++] = ' ';
+ cmd[pos++] = 'h';
+ cmd[pos++] = '1';
+ cmd[pos++] = '0';
+ cmd[pos++] = '0';
+
+ for(int count = 0; count < 256; count++) {
+ cmd[pos++] = LUT_R[s->hw->lut_id][count];
+ }
+
+ cmd[pos++] = '#';
+ cmd[pos++] = 'G';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'T';
+ cmd[pos++] = 'G';
+ cmd[pos++] = 'R';
+ cmd[pos++] = 'N';
+ cmd[pos++] = ' ';
+ cmd[pos++] = 'h';
+ cmd[pos++] = '1';
+ cmd[pos++] = '0';
+ cmd[pos++] = '0';
+
+ for(int count = 0; count < 256; count++) {
+ cmd[pos++] = LUT_G[s->hw->lut_id][count];
+ }
+
+ cmd[pos++] = '#';
+ cmd[pos++] = 'G';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'T';
+ cmd[pos++] = 'B';
+ cmd[pos++] = 'L';
+ cmd[pos++] = 'U';
+ cmd[pos++] = ' ';
+ cmd[pos++] = 'h';
+ cmd[pos++] = '1';
+ cmd[pos++] = '0';
+ cmd[pos++] = '0';
+
+ for(int count = 0; count < 256; count++) {
+ cmd[pos++] = LUT_B[s->hw->lut_id][count];
+ }
+ }
+ cmd[pos] = 0;
+
+ }
+ {// Set Color Matrix
+ if (s->params.format == SANE_FRAME_RGB && s->hw->lut_id != 0 )/*Color Matrix Target devide and color Scan*/
+ {
+ ColorMatrix matrix;
+
+ // DS-530
+
+ if (s->hw->lut_id == 2)
+ {
+ // R
+ matrix[0][0] = 1.0229;
+ matrix[0][1] = 0.0009;
+ matrix[0][2] = -0.0238;
+
+ // G
+ matrix[1][0] = 0.0031;
+ matrix[1][1] = 1.0287;
+ matrix[1][2] = -0.0318;
+
+ //B
+ matrix[2][0] = 0.0044;
+ matrix[2][1] = -0.1150;
+ matrix[2][2] = 1.1106;
+ }
+
+ // DS-1660W Flatbed
+
+ if (s->hw->lut_id == 4)
+ {
+ // R
+ matrix[0][0] = 1.0229;
+ matrix[0][1] = 0.0009;
+ matrix[0][2] = -0.0238;
+
+ // G
+ matrix[1][0] = 0.0031;
+ matrix[1][1] = 1.0287;
+ matrix[1][2] = -0.0318;
+
+ //B
+ matrix[2][0] = 0.0044;
+ matrix[2][1] = -0.1150;
+ matrix[2][2] = 1.1106;
+ }
+
+
+ // DS-320
+
+ if (s->hw->lut_id == 5)
+ {
+ // R
+ matrix[0][0] = 1.0250;
+ matrix[0][1] = 0.0004;
+ matrix[0][2] = -0.0254;
+
+ // G
+ matrix[1][0] = 0.0003;
+ matrix[1][1] = 1.0022;
+ matrix[1][2] = -0.0025;
+
+ //B
+ matrix[2][0] = 0.0049;
+ matrix[2][1] = -0.0949;
+ matrix[2][2] = 1.0900;
+ }
+
+
+ // ES-50
+
+ if (s->hw->lut_id == 6)
+ {
+ // R
+ matrix[0][0] = 1.0383;
+ matrix[0][1] = -0.0021;
+ matrix[0][2] = -0.0362;
+
+ // G
+ matrix[1][0] = 0.0046;
+ matrix[1][1] = 1.0576;
+ matrix[1][2] = -0.0622;
+
+ //B
+ matrix[2][0] = 0.0235;
+ matrix[2][1] = -0.2396;
+ matrix[2][2] = 1.2161;
+ }
+
+
+ // R
+ matrix[0][0] = 0.9864;
+ matrix[0][1] = 0.0248;
+ matrix[0][2] = -0.0112;
+
+ // G
+ matrix[1][0] = 0.0021;
+ matrix[1][1] = 1.0100;
+ matrix[1][2] = -0.0112;
+
+ //B
+ matrix[2][0] = 0.0139;
+ matrix[2][1] = -0.1249;
+ matrix[2][2] = 1.1110;
+
+
+ // Set Matrix value
+ {
+ cmd[pos++] = '#';
+ cmd[pos++] = 'C';
+ cmd[pos++] = 'M';
+ cmd[pos++] = 'X';
+ cmd[pos++] = 'U';
+ cmd[pos++] = 'M';
+ cmd[pos++] = '0';
+ cmd[pos++] = '8';
+ cmd[pos++] = 'h';
+ cmd[pos++] = '0';
+ cmd[pos++] = '0';
+ cmd[pos++] = '9';
+ }
+
+
+ // Matrix to be sent to scanner must be following d1-d9 order:
+ //
+ // G R B
+ // G [d1 d4 d7]
+ // R [d2 d5 d8]
+ // B [d3 d6 d9]
+ //
+ // So, we will convert it with index table.
+ char index[9] = {4, 1, 7, 3, 0, 6, 5, 2, 8};
+
+ double flatten[9] = {0};
+ for (int row = 0; row < 3; row++) {
+ for (int col = 0; col < 3; col++) {
+ flatten[row * 3 + col] = matrix[row][col];
+ }
+ }
+
+ int rounded[9] = {0};
+ ESCIRoundColorCorrectionMatrix(32, flatten, rounded);
+
+
+ char ordered[9] = {0};
+ for (int row = 0; row < 3; row++) {
+ for (int col = 0; col < 3; col++) {
+ int val = rounded[row * 3 + col];
+ unsigned char oct = (unsigned char)abs(val);
+ oct |= ((val < 0) ? (1 << 7) : 0);
+ ordered[(signed char)index[row * 3 + col]] = oct;
+ }
+ }
+ {
+ cmd[pos++] = ordered[0];
+ cmd[pos++] = ordered[1];
+ cmd[pos++] = ordered[2];
+ cmd[pos++] = ordered[3];
+ cmd[pos++] = ordered[4];
+ cmd[pos++] = ordered[5];
+ cmd[pos++] = ordered[6];
+ cmd[pos++] = ordered[7];
+ cmd[pos++] = ordered[8];
+ cmd[pos++] = 0; //padding
+ cmd[pos++] = 0; //padding
+ cmd[pos++] = 0; //padding
+
+
+ DBG(1, "color matrix\n");
+ for (int i = 0; i < 9; i++)
+ {
+ DBG(1, "%d\n", ordered[i]);
+ }
+
+ }
+ cmd[pos] = 0;
+ }
+
+ }
+
+
+ status = esci2_para(s, cmd, pos);
if (status != SANE_STATUS_GOOD) {
goto end;
}
@@ -1336,7 +3302,8 @@ sane_start(SANE_Handle handle)
/* first page is page 1 */
s->pages = 1;
s->scanning = 1;
-
+ s->dummy = 0;
+ s->scanEnd = 0;
end:
if (status != SANE_STATUS_GOOD) {
DBG(1, "%s: start failed: %s\n", __func__, sane_strstatus(status));
@@ -1345,140 +3312,305 @@ end:
return status;
}
-/* this moves data from our buffers to SANE */
-
-SANE_Status
-sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
- SANE_Int *length)
+static SANE_Status acquire_jpeg_data(epsonds_scanner* s)
{
- SANE_Int read = 0, tries = 3;
- SANE_Int available;
- SANE_Status status = 0;
- epsonds_scanner *s = (epsonds_scanner *)handle;
- *length = read = 0;
+ SANE_Int read = 0;
- DBG(20, "** %s: backside = %d\n", __func__, s->backside);
-
- /* sane_read called before sane_start? */
- if (s->current == NULL) {
- DBG(0, "%s: buffer is NULL", __func__);
- return SANE_STATUS_INVAL;
+ SANE_Int jpegBufSize = s->params.bytes_per_line * s->params.lines;
+ if (s->needToConvertBW)
+ {
+ jpegBufSize = s->params.pixels_per_line * s->params.lines;
}
+
+ s->frontJpegBuf = malloc(jpegBufSize);
+ s->backJpegBuf = malloc(jpegBufSize);
+ s->frontJpegBufLen = 0;
+ s->backJpegBufLen = 0;
+
+ // load all images, decode and fill buffer
+ SANE_Int status = SANE_STATUS_GOOD;
+
+ int eofFront = 0;
+ int eofBack = 0;
+
+
+ status = eds_ring_init(&s->front, (s->params.bytes_per_line) * s->params.lines);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ status = eds_ring_init(&s->back, (s->params.bytes_per_line) * s->params.lines);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ while (1)
+ {
+ status = esci2_img(s, &read);
+ DBG(20, "acquire_jpeg_data read: %d, eof: %d, backside: %d, status: %d\n", read, s->eof, s->backside, status);
+ if (read)
+ {
+ if (s->backside)
+ {
+ SANE_Byte* backBuffer = s->backJpegBuf + s->backJpegBufLen;
+ memcpy(backBuffer, s->buf, read);
+ s->backJpegBufLen += read;
+ }else{
+ SANE_Byte* frontBuffer = s->frontJpegBuf + s->frontJpegBufLen ;
+ memcpy(frontBuffer, s->buf, read);
+ s->frontJpegBufLen += read;
+ }
+ }
+ if (status == SANE_STATUS_GOOD)
+ {
+
+ DBG(20, "continue acquire image\n");
+ continue;
+ }
+ else if (status == SANE_STATUS_EOF)
+ {
+ if (s->backside)
+ {
+ DBG(20, "eofBack\n");
+ eofBack = 1;
+ }else{
+ DBG(20, "eofFront\n");
+ eofFront = 1;
+ }
+ }else if (status == SANE_STATUS_CANCELLED)
+ {
+ // cancel cleanup
+ esci2_can(s);
+
+ free(s->frontJpegBuf);
+ free(s->backJpegBuf);
+ s->frontJpegBuf = NULL;
+ s->backJpegBuf = NULL;
+ return status;
+ }else{
+ // error occurs cleanup
+ free(s->frontJpegBuf);
+ free(s->backJpegBuf);
+ s->frontJpegBuf = NULL;
+ s->backJpegBuf = NULL;
+ return status;
+ }
+
+
+ if (s->isDuplexScan)
+ {
+ DBG(20, "eofFront = %d eofBack = %d\n", eofFront, eofBack);
+ // acquire finish
+ if (eofFront && eofBack)
+ {
+ DBG(20, "eofFront && eofBack end\n");
+ break;
+ }
+ }else{
+ if (eofFront)
+ {
+ DBG(20, "eofFront end\n");
+ break;
+ }
+ }
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+acquire_raw_data(epsonds_scanner* s)
+{
+ SANE_Int read = 0;
+
+ // load all images, decode and fill buffer
+ SANE_Int status = SANE_STATUS_GOOD;
+
+ int eofFront = 0;
+ int eofBack = 0;
+ int firstWrite = 1;
+
+ while (1)
+ {
+ DBG(20, "acquire_raw_data loop start\n");
+ status = esci2_img(s, &read);
+ DBG(20, "acquire_raw_data read: %d, eof: %d, backside: %d, status: %d\n", read, s->eof, s->backside, status);
+
+ if (read)
+ {
+ if (firstWrite)
+ {
+ status = eds_ring_init(&s->front, (s->params.bytes_per_line + s->dummy) * s->params.lines);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+
+ status = eds_ring_init(&s->back, (s->params.bytes_per_line + s->dummy) * s->params.lines);
+ if (status != SANE_STATUS_GOOD) {
+ return status;
+ }
+ firstWrite = 0;
+ }
+
+ DBG(20, "eds_ring_write start\n");
+ status = eds_ring_write(s->backside ? &s->back : &s->front, s->buf, read);
+ DBG(20, "eds_ring_write end\n");
+ }
+ DBG(20, "acquire_raw_data3\n");
+
+ if (status == SANE_STATUS_GOOD)
+ {
+ DBG(20, "contiune acquire image\n");
+ continue;
+ }
+ else if (status == SANE_STATUS_EOF)
+ {
+ if (s->backside)
+ {
+ eofBack = 1;
+ }else{
+ eofFront = 1;
+ }
+ }
+ else if (status == SANE_STATUS_CANCELLED)
+ {
+ esci2_can(s);
+ return status;
+ }else{
+ // error occurs cleanup
+ return status;
+ }
+
+ if (s->isDuplexScan)
+ {
+ // acquire finish
+ if (eofFront && eofBack)
+ {
+ break;
+ }
+ }else{
+ if (eofFront)
+ {
+ break;
+ }
+ }
+ }
+
+
+ int needBytes = (s->params.bytes_per_line + s->dummy) * s->params.lines;
+ {
+ int available = eds_ring_avail(&s->front);
+ if (available < needBytes)
+ {
+ int required = needBytes - available;
+ unsigned char* padding = (unsigned char*)malloc(required);
+ memset(padding, 255, required);
+ eds_ring_write(&s->front, padding, required);
+ free(padding);
+
+ }
+
+ }
+ {
+ int available = eds_ring_avail(&s->back);
+ if (available > 0 && available < needBytes)
+ {
+ int required = needBytes - available;
+ unsigned char* padding = (unsigned char*)malloc(required);
+ memset(padding, 255, required);
+ eds_ring_write(&s->back, padding, required);
+ free(padding);
+ }
+
+ }
+
+ if (s->isDuplexScan)
+ {
+ upside_down_backside_image(s);
+ }
+
+ DBG(20, "acquire_raw_data finish");
+ return SANE_STATUS_GOOD;
+
+}
+
+static SANE_Status
+acquire_and_decode_jpeg_data(epsonds_scanner* s)
+{
+ SANE_Int status = acquire_jpeg_data(s);
+ if (status == SANE_STATUS_GOOD)
+ {
+ DBG(20, "** %s: sane status = %d needToConvertBW = %d \n", __func__, status, s->needToConvertBW);
+
+ // process front page
+ if (s->frontJpegBufLen > 0)
+ {
+ eds_decode_jpeg(s, s->frontJpegBuf, s->frontJpegBufLen, &s->front,0, s->needToConvertBW);
+ free(s->frontJpegBuf);
+ s->frontJpegBuf = NULL;
+ }
+ // process back page
+ if (s->backJpegBufLen > 0)
+ {
+ eds_decode_jpeg(s, s->backJpegBuf, s->backJpegBufLen, &s->back, 1, s->needToConvertBW);
+ free(s->backJpegBuf);
+ s->backJpegBuf = NULL;
+ }
+
+ if (s->isDuplexScan)
+ {
+ upside_down_backside_image(s);
+ }
+ }else{
+ DBG(20, "** %s: sane finish status = %d\n", __func__, status);
+ return status;
+ }
+ return status;
+}
+
+int sumLength = 0;
+/* this moves data from our buffers to SANE */
+SANE_Status
+sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length)
+{
+ epsonds_scanner *s = (epsonds_scanner *)handle;
+ SANE_Int read = 0;
+
+ if (s->canceling)
+ {
+ esci2_can(s);
+ *length = 0;
+ return SANE_STATUS_CANCELLED;
+ }
+
+ int available = eds_ring_avail(s->current);
/* anything in the buffer? pass it to the frontend */
- available = eds_ring_avail(s->current);
- if (available) {
+ if (available > 0) {
DBG(18, "reading from ring buffer, %d left\n", available);
- if (s->mode_jpeg && !s->jpeg_header_seen) {
-
- status = eds_jpeg_read_header(s);
- if (status != SANE_STATUS_GOOD && --tries) {
- goto read_again;
- }
- }
-
- if (s->mode_jpeg) {
- eds_jpeg_read(handle, data, max_length, &read);
- } else {
- eds_copy_image_from_ring(s, data, max_length, &read);
- }
+ eds_copy_image_from_ring(s, data, max_length, &read);
+ // data is empty fin
if (read == 0) {
- goto read_again;
+ *length = 0;
+ eds_ring_flush(s->current);
+ eds_ring_destory(s->current);
+ DBG(18, "returns EOF 2\n");
+ return SANE_STATUS_EOF;
}
-
*length = read;
return SANE_STATUS_GOOD;
-
-
- } else if (s->current == &s->back) {
-
- /* finished reading the back page, next
- * command should give us the EOF
- */
- DBG(18, "back side ring buffer empty\n");
+ }else{
+ *length = 0;
+ eds_ring_flush(s->current);
+ eds_ring_destory(s->current);
+ DBG(18, "returns EOF 1\n");
+ return SANE_STATUS_EOF;
}
-
- /* read until data or error */
-
-read_again:
-
- status = esci2_img(s, &read);
- if (status != SANE_STATUS_GOOD) {
- DBG(20, "read: %d, eof: %d, backside: %d, status: %d\n", read, s->eof, s->backside, status);
- }
-
- /* just got a back side page, alloc ring buffer if necessary
- * we didn't before because dummy was not known
- */
- if (s->backside) {
-
- int required = s->params.lines * (s->params.bytes_per_line + s->dummy);
-
- if (s->back.size < required) {
-
- DBG(20, "allocating buffer for the back side\n");
-
- status = eds_ring_init(&s->back, required);
- if (status != SANE_STATUS_GOOD) {
- return status;
- }
- }
- }
-
- /* abort scanning when appropriate */
- if (status == SANE_STATUS_CANCELLED) {
- esci2_can(s);
- return status;
- }
-
- if (s->eof && s->backside) {
- DBG(18, "back side scan finished\n");
- }
-
- /* read again if no error and no data */
- if (read == 0 && status == SANE_STATUS_GOOD) {
- goto read_again;
- }
-
- /* got something, write to ring */
- if (read) {
-
- DBG(20, " %d bytes read, %d lines, eof: %d, canceling: %d, status: %d, backside: %d\n",
- read, read / (s->params.bytes_per_line + s->dummy),
- s->canceling, s->eof, status, s->backside);
-
- /* move data to the appropriate ring */
- status = eds_ring_write(s->backside ? &s->back : &s->front, s->buf, read);
-
- if (0 && s->mode_jpeg && !s->jpeg_header_seen
- && status == SANE_STATUS_GOOD) {
-
- status = eds_jpeg_read_header(s);
- if (status != SANE_STATUS_GOOD && --tries) {
- goto read_again;
- }
- }
- }
-
- /* continue reading if appropriate */
- if (status == SANE_STATUS_GOOD)
- return status;
-
- /* cleanup */
- DBG(5, "** %s: cleaning up\n", __func__);
-
- if (s->mode_jpeg) {
- eds_jpeg_finish(s);
- }
-
- eds_ring_flush(s->current);
-
- return status;
}
/*
diff --git a/backend/epsonds.conf.in b/backend/epsonds.conf.in
index 1967a00fd..e2880fa21 100644
--- a/backend/epsonds.conf.in
+++ b/backend/epsonds.conf.in
@@ -10,7 +10,8 @@ usb
# e.g.:
# usb 0x4b8 0x14c
-# Network (not yet supported!)
+#
+# Network
#
# net 192.168.1.123
-#net autodiscovery
+net autodiscovery
diff --git a/backend/epsonds.h b/backend/epsonds.h
index 04cb7244d..7f1b6509b 100644
--- a/backend/epsonds.h
+++ b/backend/epsonds.h
@@ -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;
diff --git a/doc/descriptions/epsonds.desc b/doc/descriptions/epsonds.desc
index 37d0e7635..2e79a118f 100644
--- a/doc/descriptions/epsonds.desc
+++ b/doc/descriptions/epsonds.desc
@@ -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