diff options
Diffstat (limited to 'backend')
63 files changed, 1873 insertions, 480 deletions
diff --git a/backend/Makefile.am b/backend/Makefile.am index 86b1d1f..4bf4e6f 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -1619,7 +1619,7 @@ libsane_rts8891_la_LIBADD = $(COMMON_LIBS) \ sane_strstatus.lo \ ../sanei/sanei_scsi.lo \ ../sanei/sanei_usb.lo \ - $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) $(RESMGR_LIBS) + $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) $(RESMGR_LIBS) EXTRA_DIST += rts8891.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += rts8891_devices.c rts8891_low.c rts8891_low.h diff --git a/backend/avision.c b/backend/avision.c index a681ed2..3189e41 100644 --- a/backend/avision.c +++ b/backend/avision.c @@ -1321,6 +1321,15 @@ static Avision_HWEntry Avision_Device_List [] = /* status="complete" */ { NULL, NULL, + 0x262c, 0x2001, + "Xerox", "Book Scanner 4167", + AV_NON_INTERLACED_DUPLEX_300, + { 0, {0, 0}, {{0, 0}, {0, 0}} } + }, + /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge! (rebadged Avision FB6080E)" */ + /* status="complete" */ + + { NULL, NULL, 0x04a7, 0x049C, "Xerox", "DocuMate150", AV_INT_BUTTON | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK, diff --git a/backend/bh.h b/backend/bh.h index c96dc79..1a4c7f1 100644 --- a/backend/bh.h +++ b/backend/bh.h @@ -544,9 +544,8 @@ static SANE_String_Const paper_list[] = 0 }; -static /* inline */ int _is_host_little_endian(void); static /* inline */ int -_is_host_little_endian() +_is_host_little_endian(void) { SANE_Int val = 255; unsigned char *firstbyte = (unsigned char *) &val; diff --git a/backend/canon_dr-cmd.h b/backend/canon_dr-cmd.h index 0ef883f..7812232 100644 --- a/backend/canon_dr-cmd.h +++ b/backend/canon_dr-cmd.h @@ -247,6 +247,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) #define get_R_PANEL_count_only(in) getbitfield(in+1, 1, 1) #define get_R_PANEL_bypass_mode(in) getbitfield(in+1, 1, 2) #define get_R_PANEL_enable_led(in) getbitfield(in+2, 1, 0) +#define get_R_PANEL_function_number(in) getbitfield(in+3, 0xf, 0) #define get_R_PANEL_counter(in) getnbyte(in + 0x04, 4) /*sensors*/ diff --git a/backend/canon_dr.c b/backend/canon_dr.c index 359005a..9607e3c 100644 --- a/backend/canon_dr.c +++ b/backend/canon_dr.c @@ -464,6 +464,7 @@ #define STRING_IMPRINTER_ADDON_BoI SANE_I18N("Black-on-Image") #define STRING_IMPRINTER_ADDON_WoB SANE_I18N("White-on-Black") + /* Also set via config file. */ static int global_buffer_size; static int global_buffer_size_default = 2 * 1024 * 1024; @@ -1564,6 +1565,7 @@ init_model (struct scanner *s) s->fcal_dest = FCAL_DEST_SW; s->sw_lut = 1; s->invert_tly = 1; + s->has_function_number = 1; /*only in Y direction, so we trash them in X*/ s->std_res_x[DPI_100]=0; @@ -3214,6 +3216,22 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } + if(option==OPT_FUNCTION_NUMBER){ + opt->name = "function-number"; + opt->title = "Function number"; + opt->desc = "Function number set on panel"; + opt->type = SANE_TYPE_INT; + opt->unit = SANE_UNIT_NONE; + opt->constraint_type = SANE_CONSTRAINT_RANGE; + opt->constraint.range = &s->counter_range; + s->counter_range.min=1; + s->counter_range.max=9; + s->counter_range.quant=1; + opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if(!s->can_read_panel || !s->has_function_number) + opt->cap = SANE_CAP_INACTIVE; + } + if(option==OPT_ADF_LOADED){ opt->name = "adf-loaded"; opt->title = "ADF Loaded"; @@ -3654,6 +3672,11 @@ sane_control_option (SANE_Handle handle, SANE_Int option, *val_p = s->total_counter; return ret; + case OPT_FUNCTION_NUMBER: + ret = read_panel(s, OPT_FUNCTION_NUMBER); + *val_p = s->panel_function_number; + return ret; + case OPT_ADF_LOADED: ret = read_sensors(s,OPT_ADF_LOADED); *val_p = s->sensor_adf_loaded; @@ -4674,6 +4697,7 @@ read_panel(struct scanner *s,SANE_Int option) s->panel_bypass_mode = get_R_PANEL_bypass_mode(in); s->panel_enable_led = get_R_PANEL_enable_led(in); s->panel_counter = get_R_PANEL_counter(in); + s->panel_function_number = get_R_PANEL_function_number(in); ret = SANE_STATUS_GOOD; } diff --git a/backend/canon_dr.h b/backend/canon_dr.h index e84b5b7..d591e7a 100644 --- a/backend/canon_dr.h +++ b/backend/canon_dr.h @@ -78,6 +78,7 @@ enum scanner_Option OPT_COUNTER, OPT_ROLLERCOUNTER, OPT_TOTALCOUNTER, + OPT_FUNCTION_NUMBER, OPT_ADF_LOADED, OPT_CARD_LOADED, @@ -250,6 +251,7 @@ struct scanner int has_hwcrop; int has_pre_imprinter; int has_post_imprinter; + int has_function_number; int can_read_sensors; int can_read_panel; int can_write_panel; @@ -445,13 +447,14 @@ struct scanner int panel_bypass_mode; int panel_enable_led; int panel_counter; + int panel_function_number; int sensor_adf_loaded; int sensor_card_loaded; int roller_counter; int total_counter; /* values which are used to track the frontend's access to sensors */ - char panel_read[OPT_COUNTER - OPT_START + 1]; + char panel_read[OPT_FUNCTION_NUMBER - OPT_START + 1]; char sensors_read[OPT_CARD_LOADED - OPT_ADF_LOADED + 1]; }; diff --git a/backend/dell1600n_net.c b/backend/dell1600n_net.c index 9f2d48d..45b0d2c 100644 --- a/backend/dell1600n_net.c +++ b/backend/dell1600n_net.c @@ -907,7 +907,7 @@ sane_get_select_fd (SANE_Handle __sane_unused__ handle, /* Clears the contents of gKnownDevices and zeros it */ void -ClearKnownDevices () +ClearKnownDevices (void) { int i; diff --git a/backend/epson.c b/backend/epson.c index d2aba4c..d1cad9f 100644 --- a/backend/epson.c +++ b/backend/epson.c @@ -851,9 +851,9 @@ static EpsonHdrUnion command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, SANE_Status * status); static SANE_Status get_identity_information (SANE_Handle handle); static SANE_Status get_identity2_information (SANE_Handle handle); -static int send (Epson_Scanner * s, void *buf, size_t buf_size, +static int scanner_send (Epson_Scanner * s, void *buf, size_t buf_size, SANE_Status * status); -static ssize_t receive (Epson_Scanner * s, void *buf, ssize_t buf_size, +static ssize_t scanner_receive (Epson_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status); static SANE_Status color_shuffle (SANE_Handle handle, int *new_length); static SANE_Status request_focus_position (SANE_Handle handle, @@ -880,7 +880,7 @@ static void scan_finish (Epson_Scanner * s); */ static int -send (Epson_Scanner * s, void *buf, size_t buf_size, SANE_Status * status) +scanner_send (Epson_Scanner * s, void *buf, size_t buf_size, SANE_Status * status) { DBG (3, "send buf, size = %lu\n", (u_long) buf_size); @@ -933,7 +933,7 @@ send (Epson_Scanner * s, void *buf, size_t buf_size, SANE_Status * status) */ static ssize_t -receive (Epson_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status) +scanner_receive (Epson_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status) { ssize_t n = 0; @@ -1044,7 +1044,7 @@ expect_ack (Epson_Scanner * s) len = sizeof (result); - receive (s, result, len, &status); + scanner_receive (s, result, len, &status); if (SANE_STATUS_GOOD != status) return status; @@ -1072,12 +1072,12 @@ set_cmd (Epson_Scanner * s, u_char cmd, int val) params[0] = ESC; params[1] = cmd; - send (s, params, 2, &status); + scanner_send (s, params, 2, &status); if (SANE_STATUS_GOOD != (status = expect_ack (s))) return status; params[0] = val; - send (s, params, 1, &status); + scanner_send (s, params, 1, &status); status = expect_ack (s); return status; @@ -1151,7 +1151,7 @@ set_zoom (Epson_Scanner * s, int x_zoom, int y_zoom) cmd[0] = ESC; cmd[1] = s->hw->cmd->set_zoom; - send (s, cmd, 2, &status); + scanner_send (s, cmd, 2, &status); status = expect_ack (s); if (status != SANE_STATUS_GOOD) @@ -1160,7 +1160,7 @@ set_zoom (Epson_Scanner * s, int x_zoom, int y_zoom) params[0] = x_zoom; params[1] = y_zoom; - send (s, params, 2, &status); + scanner_send (s, params, 2, &status); status = expect_ack (s); return status; @@ -1179,7 +1179,7 @@ set_resolution (Epson_Scanner * s, int xres, int yres) params[0] = ESC; params[1] = s->hw->cmd->set_resolution; - send (s, params, 2, &status); + scanner_send (s, params, 2, &status); status = expect_ack (s); if (status != SANE_STATUS_GOOD) @@ -1190,7 +1190,7 @@ set_resolution (Epson_Scanner * s, int xres, int yres) params[2] = yres; params[3] = yres >> 8; - send (s, params, 4, &status); + scanner_send (s, params, 4, &status); status = expect_ack (s); return status; @@ -1224,7 +1224,7 @@ set_scan_area (Epson_Scanner * s, int x, int y, int width, int height) params[0] = ESC; params[1] = s->hw->cmd->set_scan_area; - send (s, params, 2, &status); + scanner_send (s, params, 2, &status); status = expect_ack (s); if (status != SANE_STATUS_GOOD) return status; @@ -1238,7 +1238,7 @@ set_scan_area (Epson_Scanner * s, int x, int y, int width, int height) params[6] = height; params[7] = height >> 8; - send (s, params, 8, &status); + scanner_send (s, params, 8, &status); status = expect_ack (s); return status; @@ -1267,7 +1267,7 @@ set_color_correction_coefficients (Epson_Scanner * s) params[0] = ESC; params[1] = cmd; - send (s, params, 2, &status); + scanner_send (s, params, 2, &status); if (SANE_STATUS_GOOD != (status = expect_ack (s))) return status; @@ -1285,7 +1285,7 @@ set_color_correction_coefficients (Epson_Scanner * s) cct[0], cct[1], cct[2], cct[3], cct[4], cct[5], cct[6], cct[7], cct[8]); - send (s, cct, length, &status); + scanner_send (s, cct, length, &status); status = expect_ack (s); DBG (1, "set_color_correction_coefficients: ending=%d.\n", status); @@ -1376,11 +1376,11 @@ set_gamma_table (Epson_Scanner * s) } } - send (s, params, 2, &status); + scanner_send (s, params, 2, &status); if (SANE_STATUS_GOOD != (status = expect_ack (s))) return status; - send (s, gamma, length, &status); + scanner_send (s, gamma, length, &status); if (SANE_STATUS_GOOD != (status = expect_ack (s))) return status; @@ -1621,7 +1621,7 @@ reset (Epson_Scanner * s) return status; } - send (s, param, 2, &status); + scanner_send (s, param, 2, &status); status = expect_ack (s); if (needToClose) @@ -1658,8 +1658,8 @@ close_scanner (Epson_Scanner * s) param[0] = ESC; param[1] = s->hw->cmd->request_status; param[2]='\0'; - send(s,param,2,&status); - receive(s,result,4,&status); + scanner_send(s,param,2,&status); + scanner_receive(s,result,4,&status); } @@ -1782,7 +1782,7 @@ feed (Epson_Scanner * s) params[0] = cmd; - send (s, params, 1, &status); + scanner_send (s, params, 1, &status); if (SANE_STATUS_GOOD != (status = expect_ack (s))) { @@ -1824,7 +1824,7 @@ eject (Epson_Scanner * s) params[0] = cmd; - send (s, params, 1, &status); + scanner_send (s, params, 1, &status); if (SANE_STATUS_GOOD != (status = expect_ack (s))) { @@ -1866,7 +1866,7 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, head = &(hdrunion->hdr); - send (s, cmd, cmd_size, status); + scanner_send (s, cmd, cmd_size, status); if (SANE_STATUS_GOOD != *status) { @@ -1874,7 +1874,7 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, it seems to fix the problem. It should not have any ill effects on other scanners. */ *status = SANE_STATUS_GOOD; - send (s, cmd, cmd_size, status); + scanner_send (s, cmd, cmd_size, status); if (SANE_STATUS_GOOD != *status) return (EpsonHdrUnion) 0; } @@ -1883,18 +1883,18 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, if (s->hw->connection == SANE_EPSON_SCSI) { - receive (s, buf, 4, status); + scanner_receive (s, buf, 4, status); buf += 4; } else if (s->hw->connection == SANE_EPSON_USB) { int bytes_read; - bytes_read = receive (s, buf, 4, status); + bytes_read = scanner_receive (s, buf, 4, status); buf += bytes_read; } else { - receive (s, buf, 1, status); + scanner_receive (s, buf, 1, status); buf += 1; } @@ -1923,7 +1923,7 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, } else { - receive (s, buf, 3, status); + scanner_receive (s, buf, 3, status); /* buf += 3; */ } @@ -1948,7 +1948,7 @@ command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, head = &(hdrunion->hdr); buf = head->buf; - receive (s, buf, count, status); + scanner_receive (s, buf, count, status); if (SANE_STATUS_GOOD != *status) return (EpsonHdrUnion) 0; @@ -4958,20 +4958,20 @@ sane_start (SANE_Handle handle) params[0] = ESC; params[1] = s->hw->cmd->request_extended_status; - send (s, params, 2, &status); /* send ESC f (request extended status) */ + scanner_send (s, params, 2, &status); /* send ESC f (request extended status) */ if (SANE_STATUS_GOOD == status) { len = 4; /* receive header */ - receive (s, result, len, &status); + scanner_receive (s, result, len, &status); if (SANE_STATUS_GOOD != status) return status; len = result[3] << 8 | result[2]; buf = alloca (len); - receive (s, buf, len, &status); /* receive actual status data */ + scanner_receive (s, buf, len, &status); /* receive actual status data */ if (buf[0] & 0x80) { @@ -4999,20 +4999,20 @@ sane_start (SANE_Handle handle) params[0] = ESC; params[1] = s->hw->cmd->request_condition; - send (s, params, 2, &status); /* send request condition */ + scanner_send (s, params, 2, &status); /* send request condition */ if (SANE_STATUS_GOOD != status) return status; len = 4; - receive (s, result, len, &status); + scanner_receive (s, result, len, &status); if (SANE_STATUS_GOOD != status) return status; len = result[3] << 8 | result[2]; buf = alloca (len); - receive (s, buf, len, &status); + scanner_receive (s, buf, len, &status); if (SANE_STATUS_GOOD != status) return status; @@ -5081,7 +5081,7 @@ sane_start (SANE_Handle handle) params[0] = ESC; params[1] = s->hw->cmd->start_scanning; - send (s, params, 2, &status); + scanner_send (s, params, 2, &status); if (SANE_STATUS_GOOD != status) { @@ -5120,7 +5120,7 @@ sane_auto_eject (Epson_Scanner * s) params[0] = cmd; - send (s, params, 1, &status); + scanner_send (s, params, 1, &status); if (SANE_STATUS_GOOD != (status = expect_ack (s))) { @@ -5142,7 +5142,7 @@ read_data_block (Epson_Scanner * s, EpsonDataRec * result) SANE_Status status; u_char param[3]; - receive (s, result, s->block ? 6 : 4, &status); + scanner_receive (s, result, s->block ? 6 : 4, &status); if (SANE_STATUS_GOOD != status) return status; @@ -5207,7 +5207,7 @@ read_data_block (Epson_Scanner * s, EpsonDataRec * result) param[0] = ESC; param[1] = s->hw->cmd->start_scanning; - send (s, param, 2, &status); + scanner_send (s, param, 2, &status); if (SANE_STATUS_GOOD != status) { @@ -5338,7 +5338,7 @@ START_READ: break; } - receive (s, s->buf + index * s->params.pixels_per_line, buf_len, + scanner_receive (s, s->buf + index * s->params.pixels_per_line, buf_len, &status); if (SANE_STATUS_GOOD != status) @@ -5347,7 +5347,7 @@ START_READ: * send the ACK signal to the scanner in order to make * it ready for the next data block. */ - send (s, S_ACK, 1, &status); + scanner_send (s, S_ACK, 1, &status); /* * ... and request the next data block @@ -5378,7 +5378,7 @@ START_READ: break; } - receive (s, s->buf + index * s->params.pixels_per_line, buf_len, + scanner_receive (s, s->buf + index * s->params.pixels_per_line, buf_len, &status); if (SANE_STATUS_GOOD != status) @@ -5388,7 +5388,7 @@ START_READ: return status; } - send (s, S_ACK, 1, &status); + scanner_send (s, S_ACK, 1, &status); /* * ... and the last data block @@ -5420,7 +5420,7 @@ START_READ: break; } - receive (s, s->buf + index * s->params.pixels_per_line, buf_len, + scanner_receive (s, s->buf + index * s->params.pixels_per_line, buf_len, &status); if (SANE_STATUS_GOOD != status) @@ -5442,7 +5442,7 @@ START_READ: reorder = SANE_TRUE; } - receive (s, s->buf, buf_len, &status); + scanner_receive (s, s->buf, buf_len, &status); if (SANE_STATUS_GOOD != status) { @@ -5460,7 +5460,7 @@ START_READ: { if (s->canceling) { - send (s, S_CAN, 1, &status); + scanner_send (s, S_CAN, 1, &status); expect_ack (s); *length = 0; @@ -5470,7 +5470,7 @@ START_READ: return SANE_STATUS_CANCELLED; } else - send (s, S_ACK, 1, &status); + scanner_send (s, S_ACK, 1, &status); } s->end = s->buf + buf_len; @@ -6132,21 +6132,21 @@ get_identity2_information (SANE_Handle handle) param[1] = s->hw->cmd->request_identity2; param[2] = '\0'; - send (s, param, 2, &status); + scanner_send (s, param, 2, &status); if (SANE_STATUS_GOOD != status) return status; len = 4; /* receive header */ - receive (s, result, len, &status); + scanner_receive (s, result, len, &status); if (SANE_STATUS_GOOD != status) return status; len = result[3] << 8 | result[2]; buf = alloca (len); - receive (s, buf, len, &status); /* receive actual status data */ + scanner_receive (s, buf, len, &status); /* receive actual status data */ /* the first two bytes of the buffer contain the optical resolution */ s->hw->optical_res = buf[1] << 8 | buf[0]; @@ -6234,21 +6234,21 @@ request_focus_position (SANE_Handle handle, u_char * position) param[1] = s->hw->cmd->request_focus_position; param[2] = '\0'; - send (s, param, 2, &status); + scanner_send (s, param, 2, &status); if (SANE_STATUS_GOOD != status) return status; len = 4; /* receive header */ - receive (s, result, len, &status); + scanner_receive (s, result, len, &status); if (SANE_STATUS_GOOD != status) return status; len = result[3] << 8 | result[2]; buf = alloca (len); - receive (s, buf, len, &status); /* receive actual status data */ + scanner_receive (s, buf, len, &status); /* receive actual status data */ *position = buf[1]; DBG (1, "Focus position = 0x%x\n", buf[1]); @@ -6287,7 +6287,7 @@ request_push_button_status (SANE_Handle handle, SANE_Bool * theButtonStatus) param[1] = s->hw->cmd->request_push_button_status; param[2] = '\0'; - send (s, param, 2, &status); + scanner_send (s, param, 2, &status); if (SANE_STATUS_GOOD != status) { @@ -6297,14 +6297,14 @@ request_push_button_status (SANE_Handle handle, SANE_Bool * theButtonStatus) len = 4; /* receive header */ - receive (s, result, len, &status); + scanner_receive (s, result, len, &status); if (SANE_STATUS_GOOD != status) return status; len = result[3] << 8 | result[2]; /* this should be 1 for scanners with one button */ buf = alloca (len); - receive (s, buf, len, &status); /* receive actual status data */ + scanner_receive (s, buf, len, &status); /* receive actual status data */ DBG (1, "Push button status = %d\n", buf[0] & 0x01); *theButtonStatus = ((buf[0] & 0x01) != 0); diff --git a/backend/epson2-ops.c b/backend/epson2-ops.c index faf0ffa..61930f6 100644 --- a/backend/epson2-ops.c +++ b/backend/epson2-ops.c @@ -1774,10 +1774,16 @@ e2_ext_read(struct Epson_Scanner *s) return status; } - if (e2_dev_model(dev, "GT-8200") || e2_dev_model(dev, "Perfection1650")) { - /* See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=597922#127 */ - s->buf[buf_len] &= 0xc0; - } + /* Some scanners wrongly set FSG_STATUS_CANCEL_REQ. Mask it out. + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=597922#127 + * https://gitlab.com/sane-project/backends/-/issues/716 + */ + if (e2_dev_model(dev, "GT-8200") || e2_dev_model(dev, "Perfection1650") || + e2_dev_model(dev, "GT-10000") || e2_dev_model(dev, "ES-6000") || + e2_dev_model(dev, "Perfection610") || e2_dev_model(dev, "GT-6600") || + e2_dev_model(dev, "Perfection1200") || e2_dev_model(dev, "GT-7600") || + e2_dev_model(dev, "Expression1600") || e2_dev_model(dev, "ES-2000")) + s->buf[buf_len] &= FSG_STATUS_FER | FSG_STATUS_NOT_READY; if (s->buf[buf_len] & FSG_STATUS_CANCEL_REQ) { DBG(0, "%s: cancel request received\n", __func__); diff --git a/backend/escl/escl.c b/backend/escl/escl.c index 77b753f..6bd3429 100644 --- a/backend/escl/escl.c +++ b/backend/escl/escl.c @@ -61,25 +61,6 @@ static const SANE_Device **devlist = NULL; static ESCL_Device *list_devices_primary = NULL; static int num_devices = 0; -#ifdef CURL_SSLVERSION_MAX_DEFAULT -static int proto_tls[] = { - CURL_SSLVERSION_MAX_DEFAULT, - #ifdef CURL_SSLVERSION_MAX_TLSv1_3 - CURL_SSLVERSION_MAX_TLSv1_3, - #endif - #ifdef CURL_SSLVERSION_MAX_TLSv1_2 - CURL_SSLVERSION_MAX_TLSv1_2, - #endif - #ifdef CURL_SSLVERSION_MAX_TLSv1_1 - CURL_SSLVERSION_MAX_TLSv1_1, - #endif - #ifdef CURL_SSLVERSION_MAX_TLSv1_0 - CURL_SSLVERSION_MAX_TLSv1_0, - #endif - -1 -}; -#endif - typedef struct Handled { struct Handled *next; @@ -120,17 +101,15 @@ escl_free_device(ESCL_Device *current) } -#ifdef CURL_SSLVERSION_MAX_DEFAULT static int -escl_tls_protocol_supported(char *url, int proto) +escl_tls_protocol_supported(char *url) { CURLcode res = CURLE_UNSUPPORTED_PROTOCOL; CURL *curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, url); - /* ask libcurl to use TLS version 1.0 or later */ - curl_easy_setopt(curl, CURLOPT_SSLVERSION, proto); + curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); @@ -145,33 +124,17 @@ escl_tls_protocol_supported(char *url, int proto) static int escl_is_tls(char * url, char *type) { - int tls_version = 0; if(!strcmp(type, "_uscans._tcp") || !strcmp(type, "https")) { - while(proto_tls[tls_version] != -1) - { - if (escl_tls_protocol_supported(url, proto_tls[tls_version]) == CURLE_OK) + if (escl_tls_protocol_supported(url) == CURLE_OK) { - DBG(10, "curl tls compatible (%d)\n", proto_tls[tls_version]); - break; + DBG(10, "curl tls compatible\n"); + return 1; } - tls_version++; - } - if (proto_tls[tls_version] < 1) - return 0; } - return proto_tls[tls_version]; -} -#else -static int -escl_is_tls(char * url, char *type) -{ - (void)url; - (void)type; return 0; } -#endif void escl_free_handler(escl_sane_t *handler) @@ -416,7 +379,7 @@ convertFromESCLDev(ESCL_Device *cdev) unix_path, cdev->https ? "s" : "", cdev->ip_address, cdev->port_nb); sdev->name = tmp; - DBG( 1, "Escl add device : %s\n", tmp); + DBG( 10, "Escl add device : %s\n", tmp); sdev->vendor = get_vendor(cdev->model_name); if (!sdev->vendor) @@ -523,7 +486,7 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line, line = sanei_config_get_string(line + 6, &name_str); DBG (10, "New Escl_Device URL [%s].\n", (name_str ? name_str : "VIDE")); if (!name_str || !*name_str) { - DBG (1, "Escl_Device URL missing.\n"); + DBG(10, "Escl_Device URL missing.\n"); return SANE_STATUS_INVAL; } if (*line) { @@ -1163,19 +1126,19 @@ escl_parse_name(SANE_String_Const name, ESCL_Device *device) device->type = strdup("http"); host = name + 7; } else { - DBG(1, "Unknown URL scheme in %s", name); + DBG(10, "Unknown URL scheme in %s", name); return SANE_STATUS_INVAL; } port_str = strchr(host, ':'); if (port_str == NULL) { - DBG(1, "Port missing from URL: %s", name); + DBG(10, "Port missing from URL: %s", name); return SANE_STATUS_INVAL; } port_str++; device->port_nb = atoi(port_str); if (device->port_nb < 1 || device->port_nb > 65535) { - DBG(1, "Invalid port number in URL: %s", name); + DBG(10, "Invalid port number in URL: %s", name); return SANE_STATUS_INVAL; } @@ -1201,7 +1164,7 @@ _get_hack(SANE_String_Const name, ESCL_Device *device) fp = sanei_config_open (ESCL_CONFIG_FILE); if (!fp) { - DBG (2, "_get_hack: couldn't access %s\n", ESCL_CONFIG_FILE); + DBG(4, "_get_hack: couldn't access %s\n", ESCL_CONFIG_FILE); DBG (3, "_get_hack: exit\n"); } @@ -1236,7 +1199,7 @@ _get_blacklist_pdf(void) fp = sanei_config_open (ESCL_CONFIG_FILE); if (!fp) { - DBG (2, "_get_blacklit: couldn't access %s\n", ESCL_CONFIG_FILE); + DBG(4, "_get_blacklit: couldn't access %s\n", ESCL_CONFIG_FILE); DBG (3, "_get_blacklist: exit\n"); } @@ -1345,7 +1308,7 @@ sane_cancel(SANE_Handle h) } handler->scanner->work = SANE_FALSE; handler->cancel = SANE_TRUE; - escl_scanner(handler->device, handler->scanner->scanJob, handler->result); + escl_scanner(handler->device, handler->scanner->scanJob, handler->result, SANE_TRUE); free(handler->result); handler->result = NULL; free(handler->scanner->scanJob); @@ -1558,7 +1521,7 @@ sane_start(SANE_Handle h) int bps = 0; if (handler->device == NULL) { - DBG(1, "Missing handler device.\n"); + DBG(10, "Missing handler device.\n"); return (SANE_STATUS_INVAL); } handler->cancel = SANE_FALSE; @@ -1566,6 +1529,7 @@ sane_start(SANE_Handle h) handler->decompress_scan_data = SANE_FALSE; handler->end_read = SANE_FALSE; if (handler->scanner->work == SANE_FALSE) { + escl_reset_all_jobs(handler->device); SANE_Status st = escl_status(handler->device, handler->scanner->source, NULL, @@ -1887,24 +1851,23 @@ escl_curl_url(CURL *handle, const ESCL_Device *device, SANE_String_Const path) (device->https ? "https" : "http"), device->ip_address, device->port_nb, path); - DBG( 1, "escl_curl_url: URL: %s\n", url ); + DBG( 10, "escl_curl_url: URL: %s\n", url ); curl_easy_setopt(handle, CURLOPT_URL, url); free(url); - DBG( 1, "Before use hack\n"); + DBG( 10, "Before use hack\n"); if (device->hack) { - DBG( 1, "Use hack\n"); + DBG( 10, "Use hack\n"); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, device->hack); } - DBG( 1, "After use hack\n"); + DBG( 10, "After use hack\n"); if (device->https) { - DBG( 1, "Ignoring safety certificates, use https\n"); + DBG( 10, "Ignoring safety certificates, use https\n"); + curl_easy_setopt(handle, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L); - if (device->tls > 0) - curl_easy_setopt(handle, CURLOPT_SSLVERSION, device->tls); } if (device->unix_socket != NULL) { - DBG( 1, "Using local socket %s\n", device->unix_socket ); + DBG( 10, "Using local socket %s\n", device->unix_socket ); curl_easy_setopt(handle, CURLOPT_UNIX_SOCKET_PATH, device->unix_socket); } diff --git a/backend/escl/escl.h b/backend/escl/escl.h index b59a3ff..2dce59b 100644 --- a/backend/escl/escl.h +++ b/backend/escl/escl.h @@ -248,7 +248,11 @@ SANE_Status escl_scan(capabilities_t *scanner, void escl_scanner(const ESCL_Device *device, char *scanJob, - char *result); + char *result, + SANE_Bool status); + +SANE_Status escl_reset_all_jobs(ESCL_Device *device); + typedef void CURL; diff --git a/backend/escl/escl_capabilities.c b/backend/escl/escl_capabilities.c index 950efaa..05b3fd2 100644 --- a/backend/escl/escl_capabilities.c +++ b/backend/escl/escl_capabilities.c @@ -48,7 +48,7 @@ header_callback(void *str, size_t size, size_t nmemb, void *userp) char *content = realloc(header->memory, header->size + realsize + 1); if (content == NULL) { - DBG( 1, "Not enough memory (realloc returned NULL)\n"); + DBG( 10, "Not enough memory (realloc returned NULL)\n"); return (0); } header->memory = content; @@ -201,10 +201,8 @@ find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner, int type) { const char *name = (const char *)node->name; if (strcmp(name, "ColorMode") == 0) { +#ifndef HAVE_POPPLER_GLIB const char *color = (SANE_String_Const)xmlNodeGetContent(node); -#if HAVE_POPPLER_GLIB - if (type == PLATEN || strcmp(color, "BlackAndWhite1")) -#else if (strcmp(color, "BlackAndWhite1")) #endif scanner->caps[type].ColorModes = char_to_array(scanner->caps[type].ColorModes, &scanner->caps[type].ColorModesSize, (SANE_String_Const)xmlNodeGetContent(node), 1); @@ -235,14 +233,14 @@ find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner, int type) } #endif #if(defined HAVE_TIFFIO_H) - else if(type == PLATEN && !strcmp(scanner->caps[type].DocumentFormats[i], "image/tiff")) + else if(!strcmp(scanner->caps[type].DocumentFormats[i], "image/tiff")) { have_tiff = SANE_TRUE; scanner->caps[type].have_tiff = i; } #endif #if HAVE_POPPLER_GLIB - else if(type == PLATEN && !strcmp(scanner->caps[type].DocumentFormats[i], "application/pdf")) + else if(!strcmp(scanner->caps[type].DocumentFormats[i], "application/pdf")) { have_pdf = SANE_TRUE; scanner->caps[type].have_pdf = i; @@ -568,9 +566,9 @@ escl_capabilities(ESCL_Device *device, char *blacklist, SANE_Status *status) curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 3L); CURLcode res = curl_easy_perform(curl_handle); if (res == CURLE_OK) - DBG( 1, "Create NewJob : the scanner header responded : [%s]\n", header->memory); + DBG( 10, "Create NewJob : the scanner header responded : [%s]\n", header->memory); if (res != CURLE_OK) { - DBG( 1, "The scanner didn't respond: %s\n", curl_easy_strerror(res)); + DBG( 10, "The scanner didn't respond: %s\n", curl_easy_strerror(res)); *status = SANE_STATUS_INVAL; goto clean_data; } diff --git a/backend/escl/escl_crop.c b/backend/escl/escl_crop.c index 59284ac..a7e0fa0 100644 --- a/backend/escl/escl_crop.c +++ b/backend/escl/escl_crop.c @@ -44,7 +44,7 @@ escl_crop_surface(capabilities_t *scanner, int real_h = 0; unsigned char *surface_crop = NULL; - DBG( 1, "Escl Image Crop\n"); + DBG( 10, "Escl Image Crop\n"); ratio = (double)w / (double)scanner->caps[scanner->source].width; scanner->caps[scanner->source].width = w; if (scanner->caps[scanner->source].pos_x < 0) @@ -62,18 +62,18 @@ escl_crop_surface(capabilities_t *scanner, y_off = (int)((double)scanner->caps[scanner->source].pos_y * ratio); real_h = scanner->caps[scanner->source].height - y_off; - DBG( 1, "Escl Image Crop [%dx%d|%dx%d]\n", scanner->caps[scanner->source].pos_x, scanner->caps[scanner->source].pos_y, + DBG( 10, "Escl Image Crop [%dx%d|%dx%d]\n", scanner->caps[scanner->source].pos_x, scanner->caps[scanner->source].pos_y, scanner->caps[scanner->source].width, scanner->caps[scanner->source].height); *width = real_w; *height = real_h; - DBG( 1, "Escl Image Crop [%dx%d]\n", *width, *height); + DBG( 10, "Escl Image Crop [%dx%d]\n", *width, *height); if (x_off > 0 || real_w < scanner->caps[scanner->source].width || y_off > 0 || real_h < scanner->caps[scanner->source].height) { surface_crop = (unsigned char *)malloc (sizeof (unsigned char) * real_w * real_h * bps); if(!surface_crop) { - DBG( 1, "Escl Crop : Surface_crop Memory allocation problem\n"); + DBG( 10, "Escl Crop : Surface_crop Memory allocation problem\n"); free(surface); surface = NULL; goto finish; diff --git a/backend/escl/escl_devices.c b/backend/escl/escl_devices.c index a2fdb80..05598ed 100644 --- a/backend/escl/escl_devices.c +++ b/backend/escl/escl_devices.c @@ -193,21 +193,21 @@ escl_devices(SANE_Status *status) *status = SANE_STATUS_GOOD; if (!(simple_poll = avahi_simple_poll_new())) { - DBG( 1, "Failed to create simple poll object.\n"); + DBG( 10, "Failed to create simple poll object.\n"); *status = SANE_STATUS_INVAL; goto fail; } client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error); if (!client) { - DBG( 1, "Failed to create client: %s\n", avahi_strerror(error)); + DBG( 10, "Failed to create client: %s\n", avahi_strerror(error)); *status = SANE_STATUS_INVAL; goto fail; } if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_uscan._tcp", NULL, 0, browse_callback, client))) { - DBG( 1, "Failed to create service browser: %s\n", + DBG( 10, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client))); *status = SANE_STATUS_INVAL; goto fail; @@ -216,7 +216,7 @@ escl_devices(SANE_Status *status) AVAHI_PROTO_UNSPEC, "_uscans._tcp", NULL, 0, browse_callback, client))) { - DBG( 1, "Failed to create service browser: %s\n", + DBG( 10, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client))); *status = SANE_STATUS_INVAL; goto fail; diff --git a/backend/escl/escl_jpeg.c b/backend/escl/escl_jpeg.c index 62c20c0..9008dae 100644 --- a/backend/escl/escl_jpeg.c +++ b/backend/escl/escl_jpeg.c @@ -179,7 +179,7 @@ get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps) if (surface != NULL) free(surface); fseek(scanner->tmp, start, SEEK_SET); - DBG( 1, "Escl Jpeg : Error reading jpeg\n"); + DBG( 10, "Escl Jpeg : Error reading jpeg\n"); if (scanner->tmp) { fclose(scanner->tmp); scanner->tmp = NULL; @@ -241,7 +241,7 @@ get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps) surface = malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components); if (surface == NULL) { jpeg_destroy_decompress(&cinfo); - DBG( 1, "Escl Jpeg : Memory allocation problem\n"); + DBG( 10, "Escl Jpeg : Memory allocation problem\n"); if (scanner->tmp) { fclose(scanner->tmp); scanner->tmp = NULL; diff --git a/backend/escl/escl_mupdf.c b/backend/escl/escl_mupdf.c index dd23482..f5b3b7e 100644 --- a/backend/escl/escl_mupdf.c +++ b/backend/escl/escl_mupdf.c @@ -137,7 +137,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); if (!ctx) { - DBG(1, "cannot create mupdf context\n"); + DBG(10, "cannot create mupdf context\n"); status = SANE_STATUS_INVAL; goto close_file; } @@ -147,7 +147,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) fz_register_document_handlers(ctx); fz_catch(ctx) { - DBG(1, "cannot register document handlers: %s\n", fz_caught_message(ctx)); + DBG(10, "cannot register document handlers: %s\n", fz_caught_message(ctx)); status = SANE_STATUS_INVAL; goto drop_context; } @@ -157,7 +157,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) stream = fz_open_file_ptr_escl(ctx, scanner->tmp); fz_catch(ctx) { - DBG(1, "cannot open stream: %s\n", fz_caught_message(ctx)); + DBG(10, "cannot open stream: %s\n", fz_caught_message(ctx)); status = SANE_STATUS_INVAL; goto drop_context; } @@ -167,7 +167,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) fz_seek(ctx, stream, 0, SEEK_SET); fz_catch(ctx) { - DBG(1, "cannot seek stream: %s\n", fz_caught_message(ctx)); + DBG(10, "cannot seek stream: %s\n", fz_caught_message(ctx)); status = SANE_STATUS_INVAL; goto drop_stream; } @@ -177,7 +177,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) doc = fz_open_document_with_stream(ctx, "filename.pdf", stream); fz_catch(ctx) { - DBG(1, "cannot open document: %s\n", fz_caught_message(ctx)); + DBG(10, "cannot open document: %s\n", fz_caught_message(ctx)); status = SANE_STATUS_INVAL; goto drop_stream; } @@ -187,14 +187,14 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) page_count = fz_count_pages(ctx, doc); fz_catch(ctx) { - DBG(1, "cannot count number of pages: %s\n", fz_caught_message(ctx)); + DBG(10, "cannot count number of pages: %s\n", fz_caught_message(ctx)); status = SANE_STATUS_INVAL; goto drop_document; } if (page_number < 0 || page_number >= page_count) { - DBG(1, "page number out of range: %d (page count %d)\n", page_number + 1, page_count); + DBG(10, "page number out of range: %d (page count %d)\n", page_number + 1, page_count); status = SANE_STATUS_INVAL; goto drop_document; } @@ -209,7 +209,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) pix = fz_new_pixmap_from_page_number(ctx, doc, 0, &ctm, fz_device_rgb(ctx), 0); fz_catch(ctx) { - DBG(1, "cannot render page: %s\n", fz_caught_message(ctx)); + DBG(10, "cannot render page: %s\n", fz_caught_message(ctx)); status = SANE_STATUS_INVAL; goto drop_document; } @@ -220,7 +220,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) // If necessary, trim the image. surface = escl_crop_surface(scanner, surface, pix->w, pix->h, pix->n, width, height); if (!surface) { - DBG( 1, "Escl Pdf : Surface Memory allocation problem\n"); + DBG( 10, "Escl Pdf : Surface Memory allocation problem\n"); status = SANE_STATUS_NO_MEM; goto drop_pix; } diff --git a/backend/escl/escl_newjob.c b/backend/escl/escl_newjob.c index cb48bd1..ed2f4b0 100644 --- a/backend/escl/escl_newjob.c +++ b/backend/escl/escl_newjob.c @@ -96,7 +96,7 @@ download_callback(void *str, size_t size, size_t nmemb, void *userp) char *content = realloc(download->memory, download->size + realsize + 1); if (content == NULL) { - DBG( 1, "Not enough memory (realloc returned NULL)\n"); + DBG( 10, "Not enough memory (realloc returned NULL)\n"); return (0); } download->memory = content; @@ -144,19 +144,19 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st *status = SANE_STATUS_GOOD; if (device == NULL || scanner == NULL) { *status = SANE_STATUS_NO_MEM; - DBG( 1, "Create NewJob : the name or the scan are invalid.\n"); + DBG( 10, "Create NewJob : the name or the scan are invalid.\n"); return (NULL); } upload = (struct downloading *)calloc(1, sizeof(struct downloading)); if (upload == NULL) { *status = SANE_STATUS_NO_MEM; - DBG( 1, "Create NewJob : memory allocation failure\n"); + DBG( 10, "Create NewJob : memory allocation failure\n"); return (NULL); } download = (struct downloading *)calloc(1, sizeof(struct downloading)); if (download == NULL) { free(upload); - DBG( 1, "Create NewJob : memory allocation failure\n"); + DBG( 10, "Create NewJob : memory allocation failure\n"); *status = SANE_STATUS_NO_MEM; return (NULL); } @@ -168,38 +168,21 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st int have_tiff = scanner->caps[scanner->source].have_tiff; int have_pdf = scanner->caps[scanner->source].have_pdf; - if ((scanner->source == PLATEN && have_pdf == -1) || - (scanner->source > PLATEN)) { - if (have_tiff != -1) { - scanner->caps[scanner->source].default_format = - strdup(scanner->caps[scanner->source].DocumentFormats[have_tiff]); - } - else if (have_png != -1) { - scanner->caps[scanner->source].default_format = - strdup(scanner->caps[scanner->source].DocumentFormats[have_png]); - } - else if (have_jpeg != -1) { - scanner->caps[scanner->source].default_format = - strdup(scanner->caps[scanner->source].DocumentFormats[have_jpeg]); - } + if (have_pdf != -1) { + scanner->caps[scanner->source].default_format = + strdup(scanner->caps[scanner->source].DocumentFormats[have_pdf]); } - else { - if (have_pdf != -1) { - scanner->caps[scanner->source].default_format = - strdup(scanner->caps[scanner->source].DocumentFormats[have_pdf]); - } - else if (have_tiff != -1) { - scanner->caps[scanner->source].default_format = - strdup(scanner->caps[scanner->source].DocumentFormats[have_tiff]); - } - else if (have_png != -1) { - scanner->caps[scanner->source].default_format = - strdup(scanner->caps[scanner->source].DocumentFormats[have_png]); - } - else if (have_jpeg != -1) { - scanner->caps[scanner->source].default_format = - strdup(scanner->caps[scanner->source].DocumentFormats[have_jpeg]); - } + else if (have_tiff != -1) { + scanner->caps[scanner->source].default_format = + strdup(scanner->caps[scanner->source].DocumentFormats[have_tiff]); + } + else if (have_png != -1) { + scanner->caps[scanner->source].default_format = + strdup(scanner->caps[scanner->source].DocumentFormats[have_png]); + } + else if (have_jpeg != -1) { + scanner->caps[scanner->source].default_format = + strdup(scanner->caps[scanner->source].DocumentFormats[have_jpeg]); } if (atof ((const char *)device->version) <= 2.0) { @@ -222,7 +205,7 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st " <scan:Duplex>%s</scan:Duplex>", scanner->source == ADFDUPLEX ? "true" : "false"); } - DBG( 1, "Create NewJob : %s\n", scanner->caps[scanner->source].default_format); + DBG( 10, "Create NewJob : %s\n", scanner->caps[scanner->source].default_format); if (scanner->caps[scanner->source].pos_x > scanner->caps[scanner->source].width) off_x = (scanner->caps[scanner->source].pos_x > scanner->caps[scanner->source].width) / 2; if (scanner->caps[scanner->source].pos_y > scanner->caps[scanner->source].height) @@ -295,7 +278,7 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st upload->memory = strdup(cap_data); upload->size = strlen(cap_data); wake_up_device: - DBG( 1, "Create NewJob : %s\n", cap_data); + DBG( 10, "Create NewJob : %s\n", cap_data); download->memory = malloc(1); download->size = 0; curl_handle = curl_easy_init(); @@ -310,12 +293,12 @@ wake_up_device: curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 3L); CURLcode res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { - DBG( 1, "Create NewJob : the scanner responded incorrectly: %s\n", curl_easy_strerror(res)); + DBG( 10, "Create NewJob : the scanner responded incorrectly: %s\n", curl_easy_strerror(res)); *status = SANE_STATUS_INVAL; } else { if (download->memory != NULL) { - char *tmp_location = strstr(download->memory, "Location:"); + char *tmp_location = strcasestr(download->memory, "Location:"); if (tmp_location) { temporary = strchr(tmp_location, '\r'); if (temporary == NULL) @@ -325,7 +308,7 @@ wake_up_device: location = strrchr(tmp_location,'/'); if (location) { result = strdup(location); - DBG( 1, "Create NewJob : %s\n", result); + DBG( 10, "Create NewJob : %s\n", result); *temporary = '\n'; *location = '\0'; location = strrchr(tmp_location,'/'); @@ -333,7 +316,7 @@ wake_up_device: if (location) { location++; scanner->scanJob = strdup(location); - DBG( 1, "Full location header [%s]\n", scanner->scanJob); + DBG( 10, "Full location header [%s]\n", scanner->scanJob); } else scanner->scanJob = strdup("ScanJobs"); @@ -341,14 +324,14 @@ wake_up_device: } } if (result == NULL) { - DBG( 1, "Error : Create NewJob, no location: %s\n", download->memory); + DBG( 10, "Error : Create NewJob, no location: %s\n", download->memory); *status = SANE_STATUS_INVAL; } free(download->memory); download->memory = NULL; } else { - DBG( 1, "Create NewJob : The creation of the failed job: %s\n", download->memory); + DBG( 10, "Create NewJob : The creation of the failed job: %s\n", download->memory); // If "409 Conflict" appear it means that there is no paper in feeder if (strstr(download->memory, "409 Conflict") != NULL) *status = SANE_STATUS_NO_DOCS; @@ -363,7 +346,7 @@ wake_up_device: } else { *status = SANE_STATUS_NO_MEM; - DBG( 1, "Create NewJob : The creation of the failed job\n"); + DBG( 10, "Create NewJob : The creation of the failed job\n"); return (NULL); } } diff --git a/backend/escl/escl_pdf.c b/backend/escl/escl_pdf.c index 8277e1d..0bfa3b3 100644 --- a/backend/escl/escl_pdf.c +++ b/backend/escl/escl_pdf.c @@ -121,21 +121,21 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) file = g_mapped_file_new_from_fd (fileno (scanner->tmp), 0, NULL); if (!file) { - DBG(1, "Error : g_mapped_file_new_from_fd"); + DBG(10, "Error : g_mapped_file_new_from_fd"); status = SANE_STATUS_INVAL; goto close_file; } bytes = g_mapped_file_get_bytes (file); if (!bytes) { - DBG(1, "Error : g_mapped_file_get_bytes"); + DBG(10, "Error : g_mapped_file_get_bytes"); status = SANE_STATUS_INVAL; goto free_file; } doc = poppler_document_new_from_bytes (bytes, NULL, NULL); if (!doc) { - DBG(1, "Error : poppler_document_new_from_bytes"); + DBG(10, "Error : poppler_document_new_from_bytes"); status = SANE_STATUS_INVAL; goto free_bytes; } @@ -145,14 +145,14 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) data = (char*)set_file_in_buffer(scanner->tmp, &size); if (!data) { - DBG(1, "Error : set_file_in_buffer"); + DBG(10, "Error : set_file_in_buffer"); status = SANE_STATUS_INVAL; goto close_file; } doc = poppler_document_new_from_data (data, size, NULL, NULL); if (!doc) { - DBG(1, "Error : poppler_document_new_from_data"); + DBG(10, "Error : poppler_document_new_from_data"); status = SANE_STATUS_INVAL; goto free_data; } @@ -160,7 +160,7 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) page = poppler_document_get_page (doc, 0); if (!page) { - DBG(1, "Error : poppler_document_get_page"); + DBG(10, "Error : poppler_document_get_page"); status = SANE_STATUS_INVAL; goto free_doc; } @@ -172,14 +172,14 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) h = (int)ceil(dh); cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); if (!cairo_surface) { - DBG(1, "Error : cairo_image_surface_create"); + DBG(10, "Error : cairo_image_surface_create"); status = SANE_STATUS_INVAL; goto free_page; } cr = cairo_create (cairo_surface); if (!cairo_surface) { - DBG(1, "Error : cairo_create"); + DBG(10, "Error : cairo_create"); status = SANE_STATUS_INVAL; goto free_surface; } @@ -196,26 +196,26 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps) int st = cairo_status(cr); if (st) { - DBG(1, "%s", cairo_status_to_string (st)); + DBG(10, "%s", cairo_status_to_string (st)); status = SANE_STATUS_INVAL; goto destroy_cr; } *bps = 3; - DBG(1, "Escl Pdf : Image Size [%dx%d]\n", w, h); + DBG(10, "Escl Pdf : Image Size [%dx%d]\n", w, h); surface = cairo_surface_to_pixels (cairo_surface, *bps); if (!surface) { status = SANE_STATUS_NO_MEM; - DBG(1, "Escl Pdf : Surface Memory allocation problem"); + DBG(10, "Escl Pdf : Surface Memory allocation problem"); goto destroy_cr; } // If necessary, trim the image. surface = escl_crop_surface(scanner, surface, w, h, *bps, width, height); if (!surface) { - DBG(1, "Escl Pdf Crop: Surface Memory allocation problem"); + DBG(10, "Escl Pdf Crop: Surface Memory allocation problem"); status = SANE_STATUS_NO_MEM; } diff --git a/backend/escl/escl_png.c b/backend/escl/escl_png.c index 294ec00..fc8d02d 100644 --- a/backend/escl/escl_png.c +++ b/backend/escl/escl_png.c @@ -64,7 +64,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) // check for valid magic number if (!png_check_sig (magic, sizeof (magic))) { - DBG( 1, "Escl Png : PNG error is not a valid PNG image!\n"); + DBG( 10, "Escl Png : PNG error is not a valid PNG image!\n"); status = SANE_STATUS_INVAL; goto close_file; } @@ -73,7 +73,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { - DBG( 1, "Escl Png : PNG error create a png read struct\n"); + DBG( 10, "Escl Png : PNG error create a png read struct\n"); status = SANE_STATUS_INVAL; goto close_file; } @@ -81,7 +81,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) png_infop info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { - DBG( 1, "Escl Png : PNG error create a png info struct\n"); + DBG( 10, "Escl Png : PNG error create a png info struct\n"); png_destroy_read_struct (&png_ptr, NULL, NULL); status = SANE_STATUS_INVAL; goto close_file; @@ -93,7 +93,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) png_destroy_read_struct (&png_ptr, &info_ptr, NULL); if (surface) free (surface); - DBG( 1, "Escl Png : PNG read error.\n"); + DBG( 10, "Escl Png : PNG read error.\n"); status = SANE_STATUS_INVAL; goto close_file; } @@ -115,7 +115,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) png_set_palette_to_rgb (png_ptr); else if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA) { - DBG(1, "PNG format not supported.\n"); + DBG(10, "PNG format not supported.\n"); status = SANE_STATUS_NO_MEM; goto close_file; } @@ -145,7 +145,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) surface = (unsigned char *)malloc (sizeof (unsigned char) * w * h * components); if (!surface) { - DBG( 1, "Escl Png : texels Memory allocation problem\n"); + DBG( 10, "Escl Png : texels Memory allocation problem\n"); status = SANE_STATUS_NO_MEM; goto close_file; } @@ -153,7 +153,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) // setup a pointer array. Each one points at the begening of a row. row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * h); if (!row_pointers) { - DBG( 1, "Escl Png : row_pointers Memory allocation problem\n"); + DBG( 10, "Escl Png : row_pointers Memory allocation problem\n"); free(surface); status = SANE_STATUS_NO_MEM; goto close_file; @@ -169,7 +169,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps) // If necessary, trim the image. surface = escl_crop_surface(scanner, surface, w, h, components, width, height); if (!surface) { - DBG( 1, "Escl Png : Surface Memory allocation problem\n"); + DBG( 10, "Escl Png : Surface Memory allocation problem\n"); status = SANE_STATUS_NO_MEM; goto close_file; } diff --git a/backend/escl/escl_reset.c b/backend/escl/escl_reset.c index 95e3f2d..ad3080b 100644 --- a/backend/escl/escl_reset.c +++ b/backend/escl/escl_reset.c @@ -44,7 +44,32 @@ write_callback(void __sane_unused__*str, * This function is called in the 'sane_cancel' function. */ void -escl_scanner(const ESCL_Device *device, char *scanJob, char *result) +escl_delete(const ESCL_Device *device, char *uri) +{ + CURL *curl_handle = NULL; + long answer = 0; + + if (uri == NULL) + return; + curl_handle = curl_easy_init(); + if (curl_handle != NULL) { + escl_curl_url(curl_handle, device, uri); + curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "DELETE"); + if (curl_easy_perform(curl_handle) == CURLE_OK) { + curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &answer); + return; + } + curl_easy_cleanup(curl_handle); + } +} + +/** + * \fn void escl_scanner(const ESCL_Device *device, char *result) + * \brief Function that resets the scanner after each scan, using curl. + * This function is called in the 'sane_cancel' function. + */ +void +escl_scanner(const ESCL_Device *device, char *scanJob, char *result, SANE_Bool status) { CURL *curl_handle = NULL; const char *scan_jobs = "/eSCL/"; @@ -70,10 +95,15 @@ CURL_CALL: if (i >= 15) return; } curl_easy_cleanup(curl_handle); - if (SANE_STATUS_GOOD != escl_status(device, - PLATEN, - NULL, - NULL)) - goto CURL_CALL; + char* end = strrchr(scan_cmd, '/'); + *end = 0; + escl_delete(device, scan_cmd); + if (status) { + if (SANE_STATUS_GOOD != escl_status(device, + PLATEN, + NULL, + NULL)) + goto CURL_CALL; + } } } diff --git a/backend/escl/escl_scan.c b/backend/escl/escl_scan.c index 8af6bb2..b7f344d 100644 --- a/backend/escl/escl_scan.c +++ b/backend/escl/escl_scan.c @@ -83,7 +83,7 @@ escl_scan(capabilities_t *scanner, const ESCL_Device *device, char *scanJob, cha curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, scanner); CURLcode res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { - DBG( 1, "Unable to scan: %s\n", curl_easy_strerror(res)); + DBG( 10, "Unable to scan: %s\n", curl_easy_strerror(res)); scanner->real_read = 0; fclose(scanner->tmp); scanner->tmp = NULL; diff --git a/backend/escl/escl_status.c b/backend/escl/escl_status.c index 1f848a2..eec8041 100644 --- a/backend/escl/escl_status.c +++ b/backend/escl/escl_status.c @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <libxml/parser.h> @@ -52,7 +53,7 @@ memory_callback_s(void *contents, size_t size, size_t nmemb, void *userp) char *str = realloc(mem->memory, mem->size + realsize + 1); if (str == NULL) { - DBG(1, "not enough memory (realloc returned NULL)\n"); + DBG(10, "not enough memory (realloc returned NULL)\n"); return (0); } mem->memory = str; @@ -224,7 +225,7 @@ reload: curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 3L); CURLcode res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { - DBG( 1, "The scanner didn't respond: %s\n", curl_easy_strerror(res)); + DBG( 10, "The scanner didn't respond: %s\n", curl_easy_strerror(res)); status = SANE_STATUS_INVAL; goto clean_data; } @@ -270,3 +271,135 @@ clean_data: } return (status); } + +static void +print_xml_job_finish(xmlNode *node, + SANE_Status *job) +{ + while (node) { + if (node->type == XML_ELEMENT_NODE) { + if (find_nodes_s(node)) { + if (strcmp((const char *)node->name, "JobState") == 0) { + const char *state = (const char *)xmlNodeGetContent(node); + if (!strcmp(state, "Canceled")) { + *job = SANE_STATUS_GOOD; + DBG(10, "jobId Completed SANE_STATUS_GOOD\n"); + } + else if (!strcmp(state, "Aborted")) { + *job = SANE_STATUS_GOOD; + DBG(10, "jobId Completed SANE_STATUS_GOOD\n"); + } + else if (!strcmp(state, "Completed")) { + *job = SANE_STATUS_GOOD; + DBG(10, "jobId Completed SANE_STATUS_GOOD\n"); + } + } + } + } + print_xml_job_finish(node->children, job); + node = node->next; + } +} + +static void +print_xml_reset_all_jobs (xmlNode *node, + ESCL_Device *device) +{ + DBG(10, "print_xml_reset_all_jobs\n"); + SANE_Status status = SANE_STATUS_DEVICE_BUSY; + while (node) { + if (node->type == XML_ELEMENT_NODE) { + if (find_nodes_s(node)) { + if (strcmp((const char *)node->name, "JobUri") == 0) { + DBG(10, "print_xml_reset_all_jobs: %s\n", node->name); + if (device != NULL) { + print_xml_job_finish (node, &status); + if (status == SANE_STATUS_DEVICE_BUSY) { + char *jobUri = (char *)xmlNodeGetContent(node); + char *job = strrchr((const char *)jobUri, '/'); + char *scanj = NULL; + if (job != NULL) { + if (strstr(jobUri,"ScanJobs")) + scanj = strdup("ScanJobs"); + else + scanj = strdup("ScanJob"); + DBG(10, "print_xml_reset_all_jobs: %s/%s\n", scanj, job); + escl_scanner(device, scanj, job, SANE_FALSE); + free(scanj); + } + DBG(10, "print_xml_reset_all_jobs: sleep to finish the job\n"); + } + } + } + } + } + print_xml_reset_all_jobs (node->children, + device); + node = node->next; + } +} + +/** + * \fn SANE_Status escl_reset_all_jobs (ESCL_Device *device, , char *scanJob) + * \brief Function that forces the end of jobs, using curl. + * This function is called in the 'sane_start' function. + * + * \return status (if everything is OK, status = SANE_STATUS_GOOD, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL) + */ +SANE_Status +escl_reset_all_jobs(ESCL_Device *device) +{ + CURL *curl_handle = NULL; + xmlDoc *data = NULL; + xmlNode *node = NULL; + struct idle *var = NULL; + const char *scanner_status = "/eSCL/ScannerStatus"; + SANE_Status status = SANE_STATUS_DEVICE_BUSY; + + DBG(10, "escl_reset_all_jobs\n"); + if (device == NULL) + return (SANE_STATUS_NO_MEM); + DBG(10, "1 - escl_reset_all_jobs\n"); + var = (struct idle*)calloc(1, sizeof(struct idle)); + if (var == NULL) + return (SANE_STATUS_NO_MEM); + DBG(10, "2 - escl_reset_all_jobs\n"); + var->memory = malloc(1); + var->size = 0; + curl_handle = curl_easy_init(); + + escl_curl_url(curl_handle, device, scanner_status); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, memory_callback_s); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)var); + curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 3L); + CURLcode res = curl_easy_perform(curl_handle); + if (res != CURLE_OK) { + DBG( 10, "The scanner didn't respond: %s\n", curl_easy_strerror(res)); + status = SANE_STATUS_INVAL; + goto clean_data1; + } + DBG(10, "3 - escl_reset_all_jobs\n"); + DBG( 10, "eSCL : Status : %s.\n", var->memory); + data = xmlReadMemory(var->memory, var->size, "file.xml", NULL, 0); + if (data == NULL) { + status = SANE_STATUS_NO_MEM; + goto clean_data1; + } + node = xmlDocGetRootElement(data); + if (node == NULL) { + status = SANE_STATUS_NO_MEM; + goto clean1; + } + print_xml_reset_all_jobs (node, device); + status = SANE_STATUS_GOOD; +clean1: + xmlFreeDoc(data); +clean_data1: + xmlCleanupParser(); + xmlMemoryDump(); + curl_easy_cleanup(curl_handle); + free(var->memory); + free(var); + return status; +} diff --git a/backend/escl/escl_tiff.c b/backend/escl/escl_tiff.c index e17554e..6270ff4 100644 --- a/backend/escl/escl_tiff.c +++ b/backend/escl/escl_tiff.c @@ -65,7 +65,7 @@ get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps) lseek(fileno(scanner->tmp), 0, SEEK_SET); tif = TIFFFdOpen(fileno(scanner->tmp), "temp", "r"); if (!tif) { - DBG( 1, "Escl Tiff : Can not open, or not a TIFF file.\n"); + DBG( 10, "Escl Tiff : Can not open, or not a TIFF file.\n"); status = SANE_STATUS_INVAL; goto close_file; } @@ -76,14 +76,14 @@ get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps) surface = (unsigned char*) malloc(npixels * sizeof (uint32_t)); if (surface == NULL) { - DBG( 1, "Escl Tiff : raster Memory allocation problem.\n"); + DBG( 10, "Escl Tiff : raster Memory allocation problem.\n"); status = SANE_STATUS_INVAL; goto close_tiff; } if (!TIFFReadRGBAImage(tif, w, h, (uint32_t *)surface, 0)) { - DBG( 1, "Escl Tiff : Problem reading image data.\n"); + DBG( 10, "Escl Tiff : Problem reading image data.\n"); status = SANE_STATUS_INVAL; free(surface); goto close_tiff; @@ -94,7 +94,7 @@ get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps) // If necessary, trim the image. surface = escl_crop_surface(scanner, surface, w, h, components, width, height); if (!surface) { - DBG( 1, "Escl Tiff : Surface Memory allocation problem\n"); + DBG( 10, "Escl Tiff : Surface Memory allocation problem\n"); status = SANE_STATUS_INVAL; } diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index ab1367e..74ef74e 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -840,7 +840,8 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D // FIXME: should porbably wait for some timeout Status status; - for (unsigned i = 0;; ++i) { +// for (unsigned i = 0;; ++i) { + for(;;) { status = scanner_read_status(dev); if (status.is_feeding_finished || ( direction == Direction::BACKWARD && status.is_at_home)) diff --git a/backend/genesys/gl124.cpp b/backend/genesys/gl124.cpp index af193a3..ef3cca0 100644 --- a/backend/genesys/gl124.cpp +++ b/backend/genesys/gl124.cpp @@ -83,8 +83,8 @@ gl124_init_registers (Genesys_Device * dev) dev->reg.init_reg(0x05, 0x00); if(dev->model->sensor_id == SensorId::CIS_CANON_LIDE_120) { - dev->reg.init_reg(0x06, 0x50); - dev->reg.init_reg(0x07, 0x00); + dev->reg.init_reg(0x06, 0x50); + dev->reg.init_reg(0x07, 0x00); } else { dev->reg.init_reg(0x03, 0x50 & ~REG_0x03_AVEENB); dev->reg.init_reg(0x06, 0x50 | REG_0x06_GAIN4); diff --git a/backend/genesys/gl124_registers.h b/backend/genesys/gl124_registers.h index dfc25f6..2c08e1c 100644 --- a/backend/genesys/gl124_registers.h +++ b/backend/genesys/gl124_registers.h @@ -290,4 +290,4 @@ static constexpr RegAddr REG_TRUEB = 0x112; } // namespace gl124 } // namespace genesys -#endif // BACKEND_GENESYS_GL843_REGISTERS_H +#endif // BACKEND_GENESYS_GL124_REGISTERS_H diff --git a/backend/hp-option.c b/backend/hp-option.c index 6aed680..99dad31 100644 --- a/backend/hp-option.c +++ b/backend/hp-option.c @@ -3809,7 +3809,7 @@ hp_optset_isEnabled (HpOptSet this, HpData data, const char *name, SANE_Status sanei_hp_optset_download (HpOptSet this, HpData data, HpScsi scsi) { - int i, errcount = 0; + int i; //, errcount = 0; DBG(3, "Start downloading parameters to scanner\n"); @@ -3839,7 +3839,7 @@ sanei_hp_optset_download (HpOptSet this, HpData data, HpScsi scsi) if ( sanei_hp_scl_errcheck (scsi) != SANE_STATUS_GOOD ) { - errcount++; + //errcount++; DBG(3, "Option %s generated scanner error\n", this->options[i]->descriptor->name); diff --git a/backend/hp-scl.c b/backend/hp-scl.c index 37a01e8..8b6ada1 100644 --- a/backend/hp-scl.c +++ b/backend/hp-scl.c @@ -143,7 +143,7 @@ typedef struct /* Initialize structure where we remember out open file descriptors */ void -sanei_hp_init_openfd () +sanei_hp_init_openfd (void) {int iCount; memset (asHpOpenFd, 0, sizeof (asHpOpenFd)); diff --git a/backend/hp3900_config.c b/backend/hp3900_config.c index c40920f..9f64d31 100644 --- a/backend/hp3900_config.c +++ b/backend/hp3900_config.c @@ -3813,7 +3813,7 @@ static SANE_Int cfg_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timin /** SEC: Motor curves ---------- */ -static SANE_Int *bq5550_motor() +static SANE_Int *bq5550_motor(void) { SANE_Int *rst = NULL; SANE_Int steps[] = @@ -3835,7 +3835,7 @@ static SANE_Int *bq5550_motor() return rst; } -static SANE_Int *hp4370_motor() +static SANE_Int *hp4370_motor(void) { SANE_Int *rst = NULL; SANE_Int steps[] = @@ -3936,7 +3936,7 @@ static SANE_Int *hp4370_motor() return rst; } -static SANE_Int *hp3970_motor() +static SANE_Int *hp3970_motor(void) { SANE_Int *rst = NULL; SANE_Int steps[] = @@ -4037,7 +4037,7 @@ static SANE_Int *hp3970_motor() return rst; } -static SANE_Int *hp3800_motor() +static SANE_Int *hp3800_motor(void) { SANE_Int *rst = NULL; SANE_Int steps[] = @@ -4182,7 +4182,7 @@ static SANE_Int *hp3800_motor() return rst; } -static SANE_Int *cfg_motorcurve_get() +static SANE_Int *cfg_motorcurve_get(void) { /* returns motor setting buffer for a device */ diff --git a/backend/hp3900_rts8822.c b/backend/hp3900_rts8822.c index f74d586..5cdfafe 100644 --- a/backend/hp3900_rts8822.c +++ b/backend/hp3900_rts8822.c @@ -618,7 +618,7 @@ RTS_Free (struct st_device *dev) } static struct st_device * -RTS_Alloc () +RTS_Alloc (void) { /* this function allocates space for device's variable */ @@ -6304,7 +6304,7 @@ Gamma_GetTables (struct st_device *dev, SANE_Byte * Gamma_buffer) } static void -Gamma_FreeTables () +Gamma_FreeTables (void) { SANE_Int c; @@ -11319,7 +11319,7 @@ Head_Relocate (struct st_device *dev, SANE_Int speed, SANE_Int direction, } static SANE_Int -Calib_CreateFixedBuffers () +Calib_CreateFixedBuffers (void) { SANE_Byte channel; SANE_Int ret; @@ -14002,7 +14002,7 @@ Free_Constrains (struct st_device *dev) } static void -RTS_DebugInit () +RTS_DebugInit (void) { /* Default values */ RTS_Debug->dev_model = HP3970; diff --git a/backend/hp3900_sane.c b/backend/hp3900_sane.c index 5face5e..daf04f1 100644 --- a/backend/hp3900_sane.c +++ b/backend/hp3900_sane.c @@ -1752,7 +1752,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) SANE_Char line[PATH_MAX]; SANE_Char *str = NULL; SANE_String_Const proper_str; - SANE_Int nline = 0; + //SANE_Int nline = 0; /* Initialize debug */ DBG_INIT (); @@ -1771,7 +1771,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { while (sanei_config_read (line, sizeof (line), conf_fp)) { - nline++; + //nline++; if (str) free (str); diff --git a/backend/hp5400_internal.c b/backend/hp5400_internal.c index 95866c4..e78e9e5 100644 --- a/backend/hp5400_internal.c +++ b/backend/hp5400_internal.c @@ -109,7 +109,7 @@ static TScannerModel Model_HP54xx = HP5400_SANE_STATIC int -InitHp5400_internal() { +InitHp5400_internal(void) { MatchVersions = malloc( sizeof(versionString) * numVersions ); strcpy( MatchVersions[0].strVersion, "SilitekIBlizd C3 ScannerV0.84"); @@ -121,7 +121,7 @@ InitHp5400_internal() { HP5400_SANE_STATIC int -FreeHp5400_internal() { +FreeHp5400_internal(void) { free(MatchVersions); MatchVersions = NULL; diff --git a/backend/hp5590.c b/backend/hp5590.c index 78c9313..56acfb1 100644 --- a/backend/hp5590.c +++ b/backend/hp5590.c @@ -2154,6 +2154,24 @@ sane_read_internal (struct hp5590_scanner * scanner, SANE_Byte * data, max_length, scanner->transferred_image_size); + /* + * We will truncate down the buffer size to *under* what the + * internal USB reading buffer can supply. This will avoid page read issues + * at the end of the buffer. + * + * See: https://gitlab.com/sane-project/backends/-/issues/781 + * + */ + if (max_length > BULK_READ_PAGE_SIZE * MAX_READ_PAGES) + { + DBG (DBG_proc, "%s, truncating sane_read buffer from %u to %u\n", + __func__, + max_length, + BULK_READ_PAGE_SIZE * MAX_READ_PAGES); + + max_length = BULK_READ_PAGE_SIZE * MAX_READ_PAGES; + } + SANE_Int length_limited = 0; *length = max_length; if ((unsigned long long) *length > scanner->transferred_image_size) diff --git a/backend/hp5590_low.c b/backend/hp5590_low.c index 2d19dcf..7038f43 100644 --- a/backend/hp5590_low.c +++ b/backend/hp5590_low.c @@ -99,9 +99,15 @@ struct usb_in_usb_ctrl_setup { #define CORE_FLAG_NOT_READY 1 << 1 /* Bulk transfers are done in pages, below their respective sizes */ +/* + * Note that we limit the amount we can supply to sane_read() to avoid + * clashes with the size of the internal read buffer. + * + */ #define BULK_WRITE_PAGE_SIZE 0x0f000 #define BULK_READ_PAGE_SIZE 0x10000 -#define ALLOCATE_BULK_READ_PAGES 16 /* 16 * 65536 = 1Mb */ +#define ALLOCATE_BULK_READ_PAGES 17 /* 16 * 65536 = 1Mb */ +#define MAX_READ_PAGES 16 /* maximum that we will return to sane_read() */ /* Structure describing bulk read state, because bulk reads will be done in * pages, but function caller uses its own buffer, whose size is certainly diff --git a/backend/hpsj5s.c b/backend/hpsj5s.c index 5ff5064..4c58dbf 100644 --- a/backend/hpsj5s.c +++ b/backend/hpsj5s.c @@ -648,7 +648,7 @@ DetectScanner (void) } static void -StandByScanner () +StandByScanner (void) { WriteScannerRegister (0x74, 0x80); WriteScannerRegister (0x75, 0x0C); @@ -678,7 +678,7 @@ SwitchHardwareState (SANE_Byte mask, SANE_Byte invert_mask) /*return value: 0 - no paper, 1 - paper loaded.*/ static int -CheckPaperPresent () +CheckPaperPresent (void) { if ((CallFunctionWithRetVal (0xB2) & 0x10) == 0) return 1; /*Ok - paper present. */ @@ -686,7 +686,7 @@ CheckPaperPresent () } static int -ReleasePaper () +ReleasePaper (void) { int i; @@ -874,7 +874,7 @@ TurnOnPaperPulling (enumColorDepth enColor, SANE_Word wResolution) } static void -TurnOffPaperPulling () +TurnOffPaperPulling (void) { CallFunctionWithParameter (0x91, 0); } @@ -884,7 +884,7 @@ TurnOffPaperPulling () While paper not loaded this is base "white point". */ static SANE_Byte -GetCalibration () +GetCalibration (void) { int i; int Result; @@ -1041,7 +1041,7 @@ PaperFeed (SANE_Word wLinesToFeed) /*For now we do no calibrate elements - just set maximum limits. FIX ME?*/ static void -CalibrateScanElements () +CalibrateScanElements (void) { /*Those arrays will be used in future for correct calibration. */ /*Then we need to transfer UP brightness border, we use these registers */ @@ -1260,7 +1260,7 @@ CalibrateScanElements () /*Returns 0 in case of fail and 1 in success.*/ static int -OutputCheck () +OutputCheck (void) { int i; @@ -1277,7 +1277,7 @@ OutputCheck () } static int -InputCheck () +InputCheck (void) { int i; SANE_Byte Buffer[256]; @@ -1298,7 +1298,7 @@ InputCheck () } static int -CallCheck () +CallCheck (void) { int i; SANE_Byte Buffer[256]; @@ -1331,7 +1331,7 @@ CallCheck () } static void -LoadingPaletteToScanner () +LoadingPaletteToScanner (void) { /*For now we have statical gamma. */ SANE_Byte Gamma[256]; @@ -1394,7 +1394,7 @@ CallFunctionWithRetVal (SANE_Byte Function) } static SANE_Byte -ReadDataByte () +ReadDataByte (void) { SANE_Byte Result; diff --git a/backend/kodakaio.c b/backend/kodakaio.c index 0241e2a..da3e234 100644 --- a/backend/kodakaio.c +++ b/backend/kodakaio.c @@ -1827,7 +1827,7 @@ k_init_parametersta(KodakAio_Scanner * s) SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w)); /* - * The default color depth is stored in mode_params.depth:†+ * The default color depth is stored in mode_params.depth: */ if (mode_params[s->val[OPT_MODE].w].depth == 1) s->params.depth = 1; diff --git a/backend/lexmark_low.c b/backend/lexmark_low.c index 246455f..a0237c7 100644 --- a/backend/lexmark_low.c +++ b/backend/lexmark_low.c @@ -2497,7 +2497,7 @@ sanei_lexmark_low_find_start_line (Lexmark_Device * dev) */ - int blackLineCount = 0; +// int blackLineCount = 0; int whiteLineCount = 0; int blackByteCounter = 0; unsigned char max_byte = 0; @@ -2838,14 +2838,14 @@ sanei_lexmark_low_find_start_line (Lexmark_Device * dev) if (blackByteCounter > 0) { /* This was a black line */ - blackLineCount++; +// blackLineCount++; whiteLineCount = 0; } else { /* This is a white line */ whiteLineCount++; - blackLineCount = 0; +// blackLineCount = 0; } } /* end for buffer */ diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 610064e..08a5e3b 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -624,7 +624,7 @@ attach_one (SANE_String_Const devname) } SANE_Status -scan_devices(){ +scan_devices(void){ DBG (2, "scan_devices\n"); SANE_Char config_line[PATH_MAX]; FILE *fp; diff --git a/backend/magicolor.c b/backend/magicolor.c index 5278937..aac46be 100644 --- a/backend/magicolor.c +++ b/backend/magicolor.c @@ -105,16 +105,19 @@ static struct MagicolorCmd magicolor_cmd[] = { {"mc1690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03}, {"mc4690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03}, + {"es2323am", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03}, }; static SANE_Int magicolor_default_resolutions[] = {150, 300, 600}; static SANE_Int magicolor_default_depths[] = {1,8}; +static SANE_Int estudio_default_resolutions[] = {150, 200, 300, 400, 600}; + static struct MagicolorCap magicolor_cap[] = { /* KONICA MINOLTA magicolor 1690MF, USB ID 0x123b:2089 */ { - 0x2089, "mc1690mf", "KONICA MINOLTA magicolor 1690MF", ".1.3.6.1.4.1.18334.1.1.1.1.1.23.1.1", + 0x2089, "mc1690mf", "magicolor 1690MF", ".1.3.6.1.4.1.18334.1.1.1.1.1.23.1.1", -1, 0x85, 600, {150, 600, 0}, magicolor_default_resolutions, 3, /* 600 dpi max, 3 resolutions */ 8, magicolor_default_depths, /* color depth 8 default, 1 and 8 possible */ @@ -126,7 +129,7 @@ static struct MagicolorCap magicolor_cap[] = { /* KONICA MINOLTA magicolor 4690MF, USB ID 0x132b:2079 */ { - 0x2079, "mc4690mf", "KONICA MINOLTA magicolor 4690MF", + 0x2079, "mc4690mf", "magicolor 4690MF", "FIXME", /* FIXME: fill in the correct OID! */ 0x03, 0x85, 600, {150, 600, 0}, magicolor_default_resolutions, 3, /* 600 dpi max, 3 resolutions */ @@ -137,13 +140,25 @@ static struct MagicolorCap magicolor_cap[] = { {0, SANE_FIX(0x1390 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x20dc * MM_PER_INCH / 600), 0}, }, + /* TOSHIBA e-STUDIO2323AM, USB ID 0x08a6:8056 */ + { + 0x8056, "es2323am", "e-STUDIO2323AM", ".1.3.6.1.4.1.1129.2.3.72.1", + 0x03, 0x85, + 600, {150, 600, 0}, estudio_default_resolutions, 5, + 8, magicolor_default_depths, + {-100, 100, 0}, + {0, SANE_FIX(0x13f8 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x1b9c * MM_PER_INCH / 600), 0}, + SANE_TRUE, SANE_TRUE, + {0, SANE_FIX(0x1390 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x20dc * MM_PER_INCH / 600), 0}, + }, + }; static int MC_SNMP_Timeout = 2500; static int MC_Scan_Data_Timeout = 15000; static int MC_Request_Timeout = 5000; - +#define ESTUDIO_DEVICE(s) ((s)->hw->cap->id == 0x8056) /**************************************************************************** * General configuration parameter definitions @@ -235,7 +250,7 @@ print_params(const SANE_Parameters params) #define MAGICOLOR_SNMP_SYSOBJECT_OID ".1.3.6.1.2.1.1.2.0" #define MAGICOLOR_SNMP_MAC_OID ".1.3.6.1.2.1.2.2.1.6.1" #define MAGICOLOR_SNMP_DEVICE_TREE ".1.3.6.1.4.1.18334.1.1.1.1.1" - +#define ESTUDIO_SNMP_DEVICE_TREE ".1.3.6.1.4.1.1129.2.3.72.1" /* We don't have a packet wrapper, which holds packet size etc., so we don't have to use a *read_raw and a *_read function... */ @@ -342,8 +357,13 @@ sanei_magicolor_net_open(struct Magicolor_Scanner *s) buf[1] = cmd->net_lock; buf[2] = 0x00; /* Copy the device's USB id to bytes 3-4: */ - buf[3] = s->hw->cap->id & 0xff; - buf[4] = (s->hw->cap->id >> 8) & 0xff; + if (ESTUDIO_DEVICE(s)) { + buf[3] = (s->hw->cap->id >> 8) & 0xff; + buf[4] = s->hw->cap->id & 0xff; + } else { + buf[3] = s->hw->cap->id & 0xff; + buf[4] = (s->hw->cap->id >> 8) & 0xff; + } DBG(32, "Proper welcome message received, locking the scanner...\n"); sanei_magicolor_net_write_raw(s, buf, 5, &status); @@ -777,7 +797,6 @@ cmd_finish_scan (SANE_Handle handle) return status; } memset (&returned[0], 0x00, 0x0b); - status = mc_txrx (s, buf, buflen, returned, 0x0b); free (buf); if (status != SANE_STATUS_GOOD) @@ -995,7 +1014,20 @@ cmd_read_data (SANE_Handle handle, unsigned char *buf, size_t len) /* Temporarily set the poll timeout to 10 seconds instead of 2, * because a color scan needs >5 seconds to initialize. */ MC_Request_Timeout = MC_Scan_Data_Timeout; - status = mc_txrx (s, txbuf, txbuflen, buf, len); + + if (ESTUDIO_DEVICE(s)) { + /* e-STUDIO device returns 5-bytes of ack data here + * ignore it to not mess up image buffer */ + unsigned char ack[5]; + + status = mc_txrx (s, txbuf, txbuflen, ack, sizeof(ack)); + if (status == SANE_STATUS_GOOD) { + mc_recv (s, buf, len, &status); + } + } else { + status = mc_txrx (s, txbuf, txbuflen, buf, len); + } + MC_Request_Timeout = oldtimeout; free (txbuf); if (status != SANE_STATUS_GOOD) @@ -1029,8 +1061,8 @@ mc_dev_init(Magicolor_Device *dev, const char *devname, int conntype) dev->connection = conntype; dev->sane.name = devname; dev->sane.model = NULL; - dev->sane.type = "flatbed scanner"; - dev->sane.vendor = "Magicolor"; + dev->sane.type = "multi-function peripheral"; + dev->sane.vendor = "Konica Minolta"; dev->cap = &magicolor_cap[MAGICOLOR_CAP_DEFAULT]; dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_DEFAULT]; /* Change default level when using a network connection */ @@ -1042,8 +1074,10 @@ static SANE_Status mc_dev_post_init(struct Magicolor_Device *dev) { DBG(5, "%s\n", __func__); - NOT_USED (dev); /* Correct device parameters if needed */ + if (dev->cap->id == 0x8056) + dev->sane.vendor = "Toshiba"; + return SANE_STATUS_GOOD; } @@ -1305,7 +1339,8 @@ mc_scan_finish(Magicolor_Scanner * s) s->buf = s->end = s->ptr = NULL; /* TODO: Any magicolor command for "scan finished"? */ - status = cmd_finish_scan (s); + if (!ESTUDIO_DEVICE(s)) + status = cmd_finish_scan (s); status = cmd_request_error(s); if (status != SANE_STATUS_GOOD) { @@ -1922,8 +1957,16 @@ mc_network_discovery_handle (struct snmp_pdu *pdu, snmp_discovery_data *magic) vp->val.objid, value_len) == 0) { DBG (5, "%s: Device appears to be a magicolor device (OID=%s)\n", __func__, device); } else { - DBG (5, "%s: Device is not a Magicolor device\n", __func__); - return 0; + anOID_len = MAX_OID_LEN; + read_objid(ESTUDIO_SNMP_DEVICE_TREE, anOID, &anOID_len); + + if (netsnmp_oid_is_subtree (anOID, anOID_len, + vp->val.objid, value_len) == 0) { + DBG (5, "%s: Device appears to be a estudio device (OID=%s)\n", __func__, device); + } else { + DBG (5, "%s: Device is not a e-STUDIO / Magicolor device\n", __func__); + return 0; + } } } diff --git a/backend/mustek_scsi_pp.c b/backend/mustek_scsi_pp.c index 98e3f20..860fca3 100644 --- a/backend/mustek_scsi_pp.c +++ b/backend/mustek_scsi_pp.c @@ -78,7 +78,7 @@ static int mustek_scsi_pp_timeout = 5000; /* FIXME: use same method as mustek.c ? */ static int -mustek_scsi_pp_get_time () +mustek_scsi_pp_get_time (void) { struct timeval tv; int retval; diff --git a/backend/mustek_usb2.c b/backend/mustek_usb2.c index cb511b9..785bdb3 100644 --- a/backend/mustek_usb2.c +++ b/backend/mustek_usb2.c @@ -537,7 +537,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -GetDeviceStatus () +GetDeviceStatus (void) { DBG (DBG_FUNC, "GetDeviceStatus: start\n"); return MustScanner_GetScannerState (); @@ -576,7 +576,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -CarriageHome () +CarriageHome (void) { DBG (DBG_FUNC, "CarriageHome: start\n"); return MustScanner_BackHome (); @@ -914,7 +914,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -StartScan () +StartScan (void) { DBG (DBG_FUNC, "StartScan: start\n"); if (ST_Reflective == g_ScanType) @@ -1099,7 +1099,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -StopScan () +StopScan (void) { SANE_Bool rt; int i; @@ -1159,7 +1159,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -IsTAConnected () +IsTAConnected (void) { SANE_Bool hasTA; diff --git a/backend/mustek_usb2_high.c b/backend/mustek_usb2_high.c index e8b067f..cf0157b 100644 --- a/backend/mustek_usb2_high.c +++ b/backend/mustek_usb2_high.c @@ -199,7 +199,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -MustScanner_Init () +MustScanner_Init (void) { DBG (DBG_FUNC, "MustScanner_Init: Call in\n"); @@ -260,7 +260,7 @@ Return value: return FASLE ***********************************************************************/ static SANE_Bool -MustScanner_GetScannerState () +MustScanner_GetScannerState (void) { if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) @@ -343,7 +343,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -MustScanner_BackHome () +MustScanner_BackHome (void) { DBG (DBG_FUNC, "MustScanner_BackHome: call in \n"); @@ -3081,7 +3081,7 @@ Return value: the lines of scanned ***********************************************************************/ static unsigned int -GetScannedLines () +GetScannedLines (void) { unsigned int dwScannedLines = 0; @@ -3103,7 +3103,7 @@ Return value: the lines which pass to superstratum ***********************************************************************/ static unsigned int -GetReadyLines () +GetReadyLines (void) { unsigned int dwReadyLines = 0; @@ -3143,7 +3143,7 @@ Return value: none ***********************************************************************/ static void -AddReadyLines () +AddReadyLines (void) { pthread_mutex_lock (&g_readyLinesMutex); g_wtheReadyLines++; diff --git a/backend/mustek_usb2_reflective.c b/backend/mustek_usb2_reflective.c index ed37296..e0b0d10 100644 --- a/backend/mustek_usb2_reflective.c +++ b/backend/mustek_usb2_reflective.c @@ -72,7 +72,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Reflective_Reset () +Reflective_Reset (void) { DBG (DBG_FUNC, "Reflective_Reset: call in\n"); @@ -576,7 +576,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Reflective_AdjustAD () +Reflective_AdjustAD (void) { SANE_Byte * lpCalData; unsigned short wCalWidth; @@ -1293,7 +1293,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Reflective_StopScan () +Reflective_StopScan (void) { DBG (DBG_FUNC, "Reflective_StopScan: call in\n"); if (!g_bOpened) @@ -1338,7 +1338,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Reflective_LineCalibration16Bits () +Reflective_LineCalibration16Bits (void) { SANE_Status status; SANE_Byte * lpWhiteData; @@ -1758,7 +1758,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Reflective_PrepareScan () +Reflective_PrepareScan (void) { g_wScanLinesPerBlock = g_dwBufferSize / g_BytesPerRow; g_wMaxScanLines = g_dwImageBufferSize / g_BytesPerRow; diff --git a/backend/mustek_usb2_transparent.c b/backend/mustek_usb2_transparent.c index 1c4b91b..04b9eda 100644 --- a/backend/mustek_usb2_transparent.c +++ b/backend/mustek_usb2_transparent.c @@ -73,7 +73,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Transparent_Reset () +Transparent_Reset (void) { DBG (DBG_FUNC, "Transparent_Reset: call in\n"); @@ -502,7 +502,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Transparent_StopScan () +Transparent_StopScan (void) { DBG (DBG_FUNC, "Transparent_StopScan: call in\n"); @@ -613,7 +613,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Transparent_AdjustAD () +Transparent_AdjustAD (void) { SANE_Byte * lpCalData; unsigned short wCalWidth; @@ -1659,7 +1659,7 @@ Return value: return FALSE ***********************************************************************/ static SANE_Bool -Transparent_PrepareScan () +Transparent_PrepareScan (void) { DBG (DBG_FUNC, "Transparent_PrepareScan: call in\n"); diff --git a/backend/net.c b/backend/net.c index 7b1ea05..bea22cc 100644 --- a/backend/net.c +++ b/backend/net.c @@ -313,7 +313,7 @@ add_device (const char *name, Net_Device ** ndp) #endif /* NET_USES_AF_INDEP */ /* Calls getpwuid_r(). The return value must be freed by the caller. */ -char* get_current_username() +static char* get_current_username(void) { long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize == -1) diff --git a/backend/pixma/pixma_common.h b/backend/pixma/pixma_common.h index 5b393dc..68d10ff 100644 --- a/backend/pixma/pixma_common.h +++ b/backend/pixma/pixma_common.h @@ -70,7 +70,7 @@ #define PIXMA_STATUS_FAILED 0x1515 #define PIXMA_STATUS_BUSY 0x1414 -#define PIXMA_MAX_ID_LEN 30 +#define PIXMA_MAX_ID_LEN 40 /* These may have been defined elsewhere */ #ifndef MIN diff --git a/backend/pixma/pixma_imageclass.c b/backend/pixma/pixma_imageclass.c index 83b19bd..c750b20 100644 --- a/backend/pixma/pixma_imageclass.c +++ b/backend/pixma/pixma_imageclass.c @@ -953,6 +953,7 @@ const pixma_config_t pixma_iclass_devices[] = { DEV ("Canon i-SENSYS MF4700 Series", "MF4700", MF4700_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF4800 Series", "MF4800", MF4800_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon imageCLASS MF4570dw", "MF4570dw", MF4570_PID, 600, 0, 640, 877, 0), + DEV ("Canon imageClass MF4500w Series", "MF4500w", MF4570_PID, 600, 0, 640, 877, 0), DEV ("Canon i-SENSYS MF8200C Series", "MF8200C", MF8200_PID, 600, 300, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF8300 Series", "MF8300", MF8300_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon imageCLASS D530", "D530", D530_PID, 600, 0, 640, 877, 0), diff --git a/backend/pixma/pixma_io_sanei.c b/backend/pixma/pixma_io_sanei.c index 394523e..756e0de 100644 --- a/backend/pixma/pixma_io_sanei.c +++ b/backend/pixma/pixma_io_sanei.c @@ -132,7 +132,7 @@ attach_bjnp (SANE_String_Const devname, return SANE_STATUS_NO_MEM; si->cfg = cfg; - sprintf(si->serial, "%s_%s", cfg->model, serial); + snprintf(si->serial, sizeof(si->serial), "%s_%s", cfg->model, serial); si -> interface = INT_BJNP; si->next = first_scanner; first_scanner = si; @@ -188,7 +188,7 @@ u16tohex (uint16_t x, char *str) static void read_serial_number (scanner_info_t * si) { - uint8_t unicode[2 * (PIXMA_MAX_ID_LEN - 9) + 2]; + uint8_t unicode[2 * (PIXMA_MAX_ID_LEN - 9) + 2]; // 9 = size of VID + PID + "_" uint8_t ddesc[18]; int iSerialNumber; SANE_Int usb; diff --git a/backend/pixma/pixma_mp150.c b/backend/pixma/pixma_mp150.c index 99024ca..b582c48 100644 --- a/backend/pixma/pixma_mp150.c +++ b/backend/pixma/pixma_mp150.c @@ -363,6 +363,18 @@ #define TS7700A_PID 0x1111 #define GX6500_PID 0x1148 +/* 2024 new device (untested) */ +#define TS3600_PID 0x1156 +#define TS3700_PID 0x1158 +#define E3600_PID 0x1157 + +#define G4090_PID 0x114A +#define G4080_PID 0x114B +#define G3090_PID 0x114C +#define G3080_PID 0x114D +#define TS8800_PID 0x1159 +#define XK130_PID 0x115A + /* Generation 4 XML messages that encapsulates the Pixma protocol messages */ #define XML_START_1 \ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\ @@ -2017,5 +2029,17 @@ const pixma_config_t pixma_mp150_devices[] = { DEVICE ("Canon PIXMA TS7700A series", "TS7700A", TS7700A_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA GX6500 series", "GX6500", GX6500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + DEVICE ("Canon PIXMA TS3600 Series", "TS3600", TS3600_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA TS3700 Series", "TS3700", TS3700_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA E3600 Series", "E3600", E3600_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), + + DEVICE ("Canon PIXMA G4090", "G4090", G4090_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA G4080", "G4080", G4080_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA G3090", "G3090", G3090_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA G3080", "G3080", G3080_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA TS8800 series", "TS8800", TS8800_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), + DEVICE ("Canon PIXMA XK130 series", "XK130", XK130_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), + + END_OF_DEVICE_LIST }; diff --git a/backend/plustek-pp_io.c b/backend/plustek-pp_io.c index 45ffe8b..d979c8b 100644 --- a/backend/plustek-pp_io.c +++ b/backend/plustek-pp_io.c @@ -422,7 +422,7 @@ static Bool ioP98OpenScanPath( pScanData ps ) { Byte tmp; ULong dw; - ULong dwTime = 1; +// ULong dwTime = 1; // Doesn't seem to be used. [RL] if( 0 == ps->IO.bOpenCount ) { @@ -457,7 +457,7 @@ static Bool ioP98OpenScanPath( pScanData ps ) ps->IO.bOpenCount = 0; } - dwTime++; +// dwTime++; // Doesn't seem to be used. [RL] } DBG( DBG_IO, "ioP98OpenScanPath() failed!\n" ); return _FALSE; diff --git a/backend/rts8891.c b/backend/rts8891.c index 2732871..16aecca 100644 --- a/backend/rts8891.c +++ b/backend/rts8891.c @@ -83,6 +83,7 @@ #include <string.h> #include <ctype.h> #include <time.h> +#include <math.h> #include <sys/types.h> #include <unistd.h> @@ -109,12 +110,6 @@ #define MARGIN_LEVEL 128 /* white level for margin detection */ -/* width used for calibration */ -#define CALIBRATION_WIDTH 637 - -/* data size for calibration: one RGB line*/ -#define CALIBRATION_SIZE CALIBRATION_WIDTH*3 - /* #define FAST_INIT 1 */ #define BUILD 2401 @@ -233,6 +228,8 @@ static SANE_Status find_origin (struct Rts8891_Device *dev, static SANE_Status find_margin (struct Rts8891_Device *dev); static SANE_Status dark_calibration (struct Rts8891_Device *dev, int mode, int light); +static SANE_Status lamp_warm_up (struct Rts8891_Device *dev, int mode, + int light); static SANE_Status gain_calibration (struct Rts8891_Device *dev, int mode, int light); static SANE_Status offset_calibration (struct Rts8891_Device *dev, int mode, @@ -1051,6 +1048,8 @@ static char *sensor_name (int sensor) return "SENSOR_TYPE_4400"; case SENSOR_TYPE_4400_BARE: return "SENSOR_TYPE_4400_BARE"; + case SENSOR_TYPE_UMAX: + return "SENSOR_TYPE_UMAX"; default: return "BOGUS"; } @@ -1136,7 +1135,7 @@ sane_start (SANE_Handle handle) init_lamp (dev); /* do warming up if needed: just detected or at sane_open() */ - if (dev->needs_warming == SANE_TRUE) + if (dev->needs_warming == SANE_TRUE && dev->sensor != SENSOR_TYPE_UMAX) { DBG (DBG_info, "sane_start: warming lamp ...\n"); #ifdef HAVE_SYS_TIME_H @@ -1213,6 +1212,11 @@ sane_start (SANE_Handle handle) "sane_start: sensor changed to type 'SENSOR_TYPE_4400'!\n"); dev->sensor = SENSOR_TYPE_4400; break; + case SENSOR_TYPE_UMAX: + DBG (DBG_info, + "sane_start: sensor changed to type 'SENSOR_TYPE_XPA'!\n"); + dev->sensor = SENSOR_TYPE_XPA; + break; } } } @@ -1226,6 +1230,7 @@ sane_start (SANE_Handle handle) mode = 0x20; break; case SENSOR_TYPE_BARE: + case SENSOR_TYPE_UMAX: light = 0x3b; mode = 0x20; break; @@ -1272,6 +1277,21 @@ sane_start (SANE_Handle handle) sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, dev->regs + LAMP_BRIGHT_REG); + /* step 3a: lamp warm-up (UMAX-only) */ + if (dev->sensor == SENSOR_TYPE_UMAX) + { + status = lamp_warm_up(dev, mode, light); + if (status != SANE_STATUS_GOOD) + { + if (dev->conf.allowsharing == SANE_TRUE) + { + sanei_usb_release_interface (dev->devnum, 0); + } + DBG (DBG_error, "sane_start: lamp warm-up failed!\n"); + return status; + } + } + /* step 4: gain calibration */ status = gain_calibration (dev, mode, light); if (status != SANE_STATUS_GOOD) @@ -1771,8 +1791,11 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, return SANE_STATUS_EOF; } - dev->regs[LAMP_REG] = 0xad; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + dev->regs[LAMP_REG] = 0xad; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); + } /* byte length for high dpi mode */ length = (session->params.bytes_per_line * 8) / session->params.depth; @@ -1830,8 +1853,11 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, dev->current = dev->start; } - dev->regs[LAMP_REG] = 0x8d; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + dev->regs[LAMP_REG] = 0x8d; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); + } /* it seems there is no gray or lineart hardware mode for the rts8891 */ if (session->params.format == SANE_FRAME_GRAY @@ -2912,6 +2938,15 @@ average_area (int color, SANE_Byte * data, int width, int height, return global; } +static void +gamma_correction (unsigned char *data, int length, float gamma) +{ + int i; + + for (i = 0; i < length; i++) + data[i] = 255 * pow(data[i] / 255.0, 1/gamma); +} + /** * Sets lamp brightness (hum, maybe some timing before light off) @@ -2922,6 +2957,11 @@ set_lamp_brightness (struct Rts8891_Device *dev, int level) SANE_Status status = SANE_STATUS_GOOD; SANE_Byte reg; + if (dev->sensor == SENSOR_TYPE_UMAX) + { + return status; + } + reg = 0xA0 | (level & 0x0F); sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, ®); switch (level) @@ -2945,7 +2985,12 @@ set_lamp_brightness (struct Rts8891_Device *dev, int level) sanei_rts88xx_get_status (dev->devnum, dev->regs); DBG (DBG_io, "set_lamp_brightness: status=0x%02x 0x%02x\n", dev->regs[0x10], dev->regs[0x11]); - if (dev->sensor != SENSOR_TYPE_4400) + if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x10] = 0x20; + dev->regs[0x11] = 0x3b; + } + else if (dev->sensor != SENSOR_TYPE_4400) { dev->regs[0x10] = 0x28; dev->regs[0x11] = 0x3f; @@ -2988,7 +3033,12 @@ init_lamp (struct Rts8891_Device *dev) sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); - if (dev->sensor != SENSOR_TYPE_4400 && dev->sensor != SENSOR_TYPE_4400_BARE) + if (dev->sensor == SENSOR_TYPE_UMAX) + { + sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x3b); + dev->regs[0x11] = 0x3b; + } + else if (dev->sensor != SENSOR_TYPE_4400 && dev->sensor != SENSOR_TYPE_4400_BARE) { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3f); dev->regs[0x11] = 0x3f; @@ -2998,11 +3048,14 @@ init_lamp (struct Rts8891_Device *dev) sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x22); dev->regs[0x11] = 0x22; } - reg = 0x8d; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); - dev->regs[LAMP_REG] = 0xa2; - dev->regs[LAMP_BRIGHT_REG] = 0xa0; - rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + reg = 0x8d; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + dev->regs[LAMP_REG] = 0xa2; + dev->regs[LAMP_BRIGHT_REG] = 0xa0; + rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); + } return set_lamp_brightness (dev, 7); } @@ -3022,7 +3075,7 @@ find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) int startx = 300; int width = 1200; int x, y, sum, current; - int starty = 18; + int starty = (dev->sensor == SENSOR_TYPE_UMAX) ? 42 : 18; int height = 180; int timing; @@ -3152,6 +3205,38 @@ find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) dev->regs[0xd7] = 0x30; /* 0x10 */ dev->regs[0xda] = 0xa7; /* 0xa0 */ } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x14] = 0xf0; + dev->regs[0x16] = 0x0f; + dev->regs[0x23] = 0x00; + dev->regs[0x35] = 0x0e; + dev->regs[0x36] = 0x2c; + dev->regs[0x3a] = 0x0e; + dev->regs[0xc0] = 0x87; + dev->regs[0xc1] = 0x07; + dev->regs[0xc2] = 0xf8; + dev->regs[0xc3] = 0x78; + dev->regs[0xc4] = 0xf8; + dev->regs[0xc5] = 0x07; + dev->regs[0xc6] = 0x87; + dev->regs[0xc7] = 0x07; + dev->regs[0xc8] = 0xf8; + dev->regs[0xc9] = 0xfc; + dev->regs[0xca] = 0x0f; + dev->regs[0xcd] = 0x00; + dev->regs[0xce] = 0x80; + dev->regs[0xcf] = 0xe2; + dev->regs[0xd0] = 0xe4; + dev->regs[0xd7] = 0x10; + dev->regs[0xd8] = 0xa6; + dev->regs[0xd9] = 0x2d; + dev->regs[0xda] = 0x00; + dev->regs[0xe2] = 0x03; + SET_DOUBLE (dev->regs, EXPOSURE_REG, 2061); + /* dev->regs[0xe5] = 0x0d; + dev->regs[0xe6] = 0x08; 080d=2061 */ + } SET_DOUBLE (dev->regs, TIMING_REG, timing); SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); @@ -3180,8 +3265,11 @@ find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) sanei_rts88xx_set_gain (dev->regs, 0x10, 0x10, 0x10); /* gray level scan */ - dev->regs[LAMP_REG] = 0xad; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, dev->regs + LAMP_REG); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + dev->regs[LAMP_REG] = 0xad; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, dev->regs + LAMP_REG); + } if (dev->sensor != SENSOR_TYPE_4400 && (dev->sensor != SENSOR_TYPE_4400_BARE)) { @@ -3208,6 +3296,16 @@ find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) write_gray_data (data, "find_origin.pnm", width, height); } + /* strong gamma correction (16) for reliable detection with cold lamp */ + if (dev->sensor == SENSOR_TYPE_UMAX) + { + gamma_correction(data, total, 16); + if (DBG_LEVEL > DBG_io2) + { + write_gray_data (data, "find_origin_gamma.pnm", width, height); + } + } + /* now we have the data, search for the black area so that we can */ /* deduce start of scan area */ /* we apply an Y direction sobel filter to get reliable edge detection */ @@ -3291,6 +3389,20 @@ find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) dev->regs[0xe6] = 0x08; 0x10 080d=2061=1030*2+1 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 2061); } + else if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x36] = 0x24; /* direction reverse (& ~0x08) */ + dev->regs[0xb2] = 0x02; + dev->regs[0xd9] = 0x2d; + dev->regs[0xda] = 0x00; + dev->regs[0xe2] = 0x07; + + /* + dev->regs[0xe5] = 0x06; + dev->regs[0xe6] = 0x04; 406=1030 */ + SET_DOUBLE (dev->regs, EXPOSURE_REG, 1030); + sum -= 32; + } else { dev->regs[0x11] = 0x3f; /* 0x3b */ @@ -3306,6 +3418,7 @@ find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) } /* move by a fixed amount relative to the 'top' of the scanner */ + DBG (DBG_info, "find_origin: moving back %d lines\n", height - sum + 10); sanei_rts88xx_set_scan_area (dev->regs, height - sum + 10, height - sum + 11, 637, 893); rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); @@ -3341,6 +3454,7 @@ find_margin (struct Rts8891_Device *dev) int height = 1; SANE_Byte reg = 0xa2; int timing=0; + unsigned char margin_level = MARGIN_LEVEL; DBG (DBG_proc, "find_margin: start\n"); @@ -3352,12 +3466,25 @@ find_margin (struct Rts8891_Device *dev) { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x23); } + else if (dev->sensor == SENSOR_TYPE_UMAX) + { + sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x3b); + } else { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3b); } - sanei_rts88xx_set_gain (dev->regs, 0x3f, 0x3f, 0x3f); + if (dev->sensor == SENSOR_TYPE_UMAX) + { + sanei_rts88xx_set_offset (dev->regs, 0xad, 0xb2, 0xb1); + sanei_rts88xx_set_gain (dev->regs, 0x00, 0x00, 0x00); + startx = 66; + } + else + { + sanei_rts88xx_set_gain (dev->regs, 0x3f, 0x3f, 0x3f); + } /* set scan parameters */ dev->regs[0x33] = 0x01; @@ -3447,6 +3574,49 @@ find_margin (struct Rts8891_Device *dev) dev->regs[0x8d] = 0x3b; /* 0x00 */ timing=0x00b0; } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x35] = 0x0e; + dev->regs[0x3a] = 0x0e; + dev->regs[0x40] = 0x20; + dev->regs[0x72] = 0xe1; + dev->regs[0x73] = 0x14; + dev->regs[0x74] = 0x18; + dev->regs[0x7a] = 0x01; + dev->regs[0x8d] = 0x07; + timing=0x32; + dev->regs[0xc1] = 0x07; + dev->regs[0xc2] = 0x80; + dev->regs[0xc4] = 0xf8; + dev->regs[0xc5] = 0x7f; + dev->regs[0xc6] = 0xff; + dev->regs[0xc7] = 0x07; + dev->regs[0xc8] = 0x80; + dev->regs[0xc9] = 0x00; + dev->regs[0xca] = 0x0f; + dev->regs[0xcb] = 0x00; + dev->regs[0xcc] = 0xfe; + dev->regs[0xcd] = 0x00; + dev->regs[0xce] = 0x00; + dev->regs[0xcf] = 0xf7; + dev->regs[0xd0] = 0xe1; + dev->regs[0xd1] = 0xea; + dev->regs[0xd2] = 0x0b; + dev->regs[0xd3] = 0x03; + dev->regs[0xd4] = 0x05; + dev->regs[0xd6] = 0xab; + dev->regs[0xd7] = 0x10; + dev->regs[0xd8] = 0xa6; + dev->regs[0xda] = 0x00; + dev->regs[0xe2] = 0x03; + dev->regs[0xee] = 0x00; + dev->regs[0xf1] = 0x00; + + /* dev->regs[0xe5] = 0xbd; + dev->regs[0xe6] = 0x0a; 0abd=2749 */ + SET_DOUBLE (dev->regs, EXPOSURE_REG, 2749); + margin_level = 32; + } SET_DOUBLE (dev->regs, TIMING_REG, timing); SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); @@ -3480,11 +3650,28 @@ find_margin (struct Rts8891_Device *dev) write_gray_data (data, "find_margin.pnm", width, height); } - /* we search from left to right the first white pixel */ + /* gamma correction (2) for reliable detection with cold lamp */ + if (dev->sensor == SENSOR_TYPE_UMAX) + { + gamma_correction(data, total, 2); + if (DBG_LEVEL > DBG_io2) + { + write_gray_data (data, "find_margin_gamma.pnm", width, height); + } + } + + /* search from left for the first white pixel (4 consecutive for UMAX) */ x = 0; - while (x < width && data[x] < MARGIN_LEVEL) - x++; - if (x == width) + if (dev->sensor == SENSOR_TYPE_UMAX) + while (x < width - 3 && (data[x] < margin_level || + data[x + 1] < margin_level || + data[x + 2] < margin_level || + data[x + 3] < margin_level)) + x++; + else + while (x < width && data[x] < margin_level) + x++; + if (x == width || (dev->sensor == SENSOR_TYPE_UMAX && x == width - 3)) { DBG (DBG_warn, "find_margin: failed to find left margin!\n"); DBG (DBG_warn, "find_margin: using default...\n"); @@ -3679,7 +3866,10 @@ initialize_device (struct Rts8891_Device *dev) dev->regs[0xd5] = 0x86; /* 0x06 */ dev->regs[0xd7] = 0x30; /* 0x10 */ dev->regs[0xd8] = 0xf6; /* 0x7a */ - dev->regs[0xd9] = 0x80; /* 0x00 */ + if (dev->sensor != SENSOR_TYPE_UMAX) + { + dev->regs[0xd9] = 0x80; /* 0x00 */ + } dev->regs[0xda] = 0x00; /* 0x15 */ dev->regs[0xe2] = 0x01; /* 0x00 */ /* dev->regs[0xe5] = 0x14; 0x0f */ @@ -4011,6 +4201,38 @@ int i; dev->regs[0x90] = 0x80; /* 0x00 */ } break; + case SENSOR_TYPE_UMAX: + for (i = 0; i < dev->reg_count; i++) + dev->regs[i] = 0x00; + dev->regs[0x00] = 0xe5; + dev->regs[0x01] = 0x41; + dev->regs[0x0b] = 0x70; + dev->regs[0x10] = 0xd0; + dev->regs[0x11] = 0x1b; + dev->regs[0x13] = 0x20; + dev->regs[0x15] = 0x20; + dev->regs[0x1d] = 0x20; + dev->regs[0x20] = 0x3a; + dev->regs[0x21] = 0xf2; + dev->regs[0x34] = 0x10; + dev->regs[0x36] = 0x07; + dev->regs[0x40] = 0x20; + dev->regs[0x44] = 0x8c; + dev->regs[0x45] = 0x76; + dev->regs[0x8d] = 0x80; + dev->regs[0x8e] = 0x68; + dev->regs[0x93] = 0x02; + dev->regs[0x94] = 0x0e; + dev->regs[0xa3] = 0xcc; + dev->regs[0xa4] = 0x27; + dev->regs[0xa5] = 0x64; + dev->regs[0xb2] = 0x02; + dev->regs[0xd5] = 0x86; + dev->regs[0xd6] = 0x1b; + dev->regs[0xd8] = 0xff; + dev->regs[0xe2] = 0x01; + dev->regs[0xe5] = 0x14; + break; } return SANE_STATUS_GOOD; } @@ -4093,6 +4315,14 @@ init_device (struct Rts8891_Device *dev) DBG (DBG_io, "init_device: status=0x%02x 0x%02x\n", dev->regs[0x10], dev->regs[0x11]); + if (dev->model->sensor == SENSOR_TYPE_UMAX) + { + /* bit 7 in reg 0x10 is set on USB plug when UTA is attached + * we keep track of it and set it back on exit so we can detect UTA next time + */ + dev->has_uta = (dev->regs[0x10] & 0x80) ? SANE_TRUE : SANE_FALSE; + DBG (DBG_io, "init_device: UMAX UTA (Transparency adapter) %s\n", dev->has_uta ? "detected":"not detected"); + } /* reads lamp status and sensor information */ sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs); DBG (DBG_io, "init_device: lamp status=0x%02x\n", dev->regs[0x8e]); @@ -4194,39 +4424,77 @@ init_device (struct Rts8891_Device *dev) DBG (DBG_warn, "init_device: got unexpected id 0x%02x\n", id); } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x10] = 0x28; + dev->regs[0x11] = 0x28; + dev->regs[0x12] = 0xff; + dev->regs[0x14] = 0xf0; /* GPIO/buttons direction? */ + dev->regs[0x15] = 0x28; + dev->regs[0x16] = 0x0f; /* GPIO/buttons direction? */ + dev->regs[0x18] = 0xff; + dev->regs[0x24] = 0xff; + dev->regs[0x72] = 0xe1; + dev->regs[0x73] = 0x14; + dev->regs[0x74] = 0x18; + dev->regs[0x75] = 0x15; + dev->regs[0xc0] = 0x87; + dev->regs[0xc1] = 0x07; + dev->regs[0xc2] = 0xf8; + dev->regs[0xc3] = 0x78; + dev->regs[0xc4] = 0xf8; + dev->regs[0xc5] = 0x07; + dev->regs[0xc6] = 0x87; + dev->regs[0xc7] = 0x07; + dev->regs[0xc8] = 0xf8; + dev->regs[0xc9] = 0xfc; + dev->regs[0xca] = 0x0f; + dev->regs[0xce] = 0x80; + dev->regs[0xcf] = 0xe2; + dev->regs[0xd0] = 0xe4; + dev->regs[0xd1] = 0xea; + dev->regs[0xd2] = 0x0b; + dev->regs[0xd3] = 0x03; + dev->regs[0xd4] = 0x05; + dev->regs[0xd7] = 0x10; + dev->regs[0xd8] = 0xa6; + } + else + { + dev->regs[0x12] = 0xff; + dev->regs[0x14] = 0xf8; + dev->regs[0x15] = 0x28; + dev->regs[0x16] = 0x07; + dev->regs[0x18] = 0xff; + dev->regs[0x23] = 0xff; + dev->regs[0x24] = 0xff; - dev->regs[0x12] = 0xff; - dev->regs[0x14] = 0xf8; - dev->regs[0x15] = 0x28; - dev->regs[0x16] = 0x07; - dev->regs[0x18] = 0xff; - dev->regs[0x23] = 0xff; - dev->regs[0x24] = 0xff; + dev->regs[0x72] = 0xe1; + dev->regs[0x73] = 0x14; + dev->regs[0x74] = 0x18; + dev->regs[0x75] = 0x15; + dev->regs[0xc0] = 0xff; + dev->regs[0xc1] = 0x0f; + dev->regs[0xc3] = 0xff; + dev->regs[0xc4] = 0xff; + dev->regs[0xc5] = 0xff; + dev->regs[0xc6] = 0xff; + dev->regs[0xc7] = 0xff; + dev->regs[0xc8] = 0xff; + dev->regs[0xca] = 0x0e; + dev->regs[0xcd] = 0xf0; + dev->regs[0xce] = 0xff; + dev->regs[0xcf] = 0xf5; + dev->regs[0xd0] = 0xf7; + dev->regs[0xd1] = 0xea; + dev->regs[0xd2] = 0x0b; + dev->regs[0xd3] = 0x03; + dev->regs[0xd4] = 0x05; + dev->regs[0xd7] = 0x30; + dev->regs[0xd8] = 0xf6; + dev->regs[0xd9] = 0x80; + } - dev->regs[0x72] = 0xe1; - dev->regs[0x73] = 0x14; - dev->regs[0x74] = 0x18; - dev->regs[0x75] = 0x15; - dev->regs[0xc0] = 0xff; - dev->regs[0xc1] = 0x0f; - dev->regs[0xc3] = 0xff; - dev->regs[0xc4] = 0xff; - dev->regs[0xc5] = 0xff; - dev->regs[0xc6] = 0xff; - dev->regs[0xc7] = 0xff; - dev->regs[0xc8] = 0xff; - dev->regs[0xca] = 0x0e; - dev->regs[0xcd] = 0xf0; - dev->regs[0xce] = 0xff; - dev->regs[0xcf] = 0xf5; - dev->regs[0xd0] = 0xf7; - dev->regs[0xd1] = 0xea; - dev->regs[0xd2] = 0x0b; - dev->regs[0xd3] = 0x03; - dev->regs[0xd4] = 0x05; - dev->regs[0xd7] = 0x30; - dev->regs[0xd8] = 0xf6; - dev->regs[0xd9] = 0x80; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); /* now we are writing and reading back from memory, it is surely a memory test since the written data @@ -4370,14 +4638,17 @@ init_device (struct Rts8891_Device *dev) return SANE_STATUS_IO_ERROR; } } - reg = 0x80; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); - reg = 0xad; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); - sanei_rts88xx_read_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); - /* we expect 0xF8 0x28 here */ - dev->regs[0x14] = dev->regs[0x14] & 0x7F; - sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + reg = 0x80; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + reg = 0xad; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + sanei_rts88xx_read_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); + /* we expect 0xF8 0x28 here */ + dev->regs[0x14] = dev->regs[0x14] & 0x7F; + sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); + } /* reads scanner status */ sanei_rts88xx_get_status (dev->devnum, dev->regs); @@ -4387,10 +4658,13 @@ init_device (struct Rts8891_Device *dev) DBG (DBG_io, "init_device: link=0x%02x\n", control); sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); - reg = 0x8d; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); - reg = 0xad; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + reg = 0x8d; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + reg = 0xad; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + } /* here, we are in iddle state */ @@ -4480,19 +4754,25 @@ init_device (struct Rts8891_Device *dev) dev->regs[0x12] = 0xff; dev->regs[0x13] = 0x20; sanei_rts88xx_write_regs (dev->devnum, 0x12, dev->regs + 0x12, 2); - dev->regs[0x14] = 0xf8; - dev->regs[0x15] = 0x28; - sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + dev->regs[0x14] = 0xf8; + dev->regs[0x15] = 0x28; + sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); + } reg = 0; sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); - reg = 0x80; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + reg = 0x80; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + dev->regs[LAMP_REG] = 0xad; + } dev->regs[0x8b] = 0xff; dev->regs[0x8c] = 0x3f; - dev->regs[LAMP_REG] = 0xad; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); set_lamp_brightness (dev, 0); @@ -4601,7 +4881,7 @@ detect_device (struct Rts8891_Device *dev) /** * Do dark calibration. We scan a well defined area until average pixel value * of the black area is about 0x03 for each color channel. This calibration is - * currently done at 75 dpi regardless of the final scan dpi. + * currently done at 75 dpi (100 for UMAX) regardless of the final scan dpi. */ static SANE_Status dark_calibration (struct Rts8891_Device *dev, int mode, int light) @@ -4611,7 +4891,7 @@ dark_calibration (struct Rts8891_Device *dev, int mode, int light) int ro = 250, tro = 250, bro = 0; int bo = 250, tbo = 250, bbo = 0; int go = 250, tgo = 250, bgo = 0; - unsigned char image[CALIBRATION_SIZE]; + unsigned char image[dev->model->calibration_width * 3]; float global, ra, ga, ba; int num = 0; char name[32]; @@ -4628,7 +4908,15 @@ dark_calibration (struct Rts8891_Device *dev, int mode, int light) /* set up starting values */ sanei_rts88xx_set_gain (dev->regs, 0, 0, 0); - sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH); + if (dev->sensor == SENSOR_TYPE_UMAX) + { + /* UMAX calibratration area is 1500 but the width is halved by reg. 0x7a */ + sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 2, 2 + 2 * dev->model->calibration_width); + } + else + { + sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + dev->model->calibration_width); + } sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); @@ -4743,6 +5031,51 @@ dark_calibration (struct Rts8891_Device *dev, int mode, int light) dev->regs[0xef] = 0x02; /* 0x03 */ dev->regs[0xf0] = 0xa8; /* 0x70 */ } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x33] = 0x01; + dev->regs[0x35] = 0x47; + dev->regs[0x40] = 0xa0; + dev->regs[0x7a] = 0x02; + dev->regs[0x8d] = 0x46; + dev->regs[0xc0] = 0x66; + dev->regs[0xc1] = 0xc0; + dev->regs[0xc2] = 0x7f; + dev->regs[0xc3] = 0x99; + dev->regs[0xc4] = 0x3f; + dev->regs[0xc5] = 0x80; + dev->regs[0xc6] = 0x66; + dev->regs[0xc7] = 0xc0; + dev->regs[0xc8] = 0x7f; + dev->regs[0xc9] = 0xff; + dev->regs[0xcb] = 0x00; + dev->regs[0xcc] = 0x00; + dev->regs[0xcd] = 0x80; + dev->regs[0xce] = 0xff; + dev->regs[0xcf] = 0xe3; + dev->regs[0xd0] = 0xe8; + dev->regs[0xd1] = 0xee; + dev->regs[0xd2] = 0x0f; + dev->regs[0xd3] = 0x0b; + dev->regs[0xd4] = 0x0d; + dev->regs[0xd8] = 0xa6; + dev->regs[0xe2] = 0x07; + + /*dev->regs[0xe5] = 0x1b; 28=40 + dev->regs[0xe6] = 0x01; */ + SET_DOUBLE (dev->regs, EXPOSURE_REG, 283); + + dev->regs[0xe7] = 0x4b; + dev->regs[0xe9] = 0x40; + dev->regs[0xea] = 0x7d; + dev->regs[0xeb] = 0x04; + dev->regs[0xec] = 0x18; + dev->regs[0xed] = 0x85; + dev->regs[0xee] = 0x02; + dev->regs[0xef] = 0x0a; + dev->regs[0xf0] = 0x81; + dev->regs[0xf1] = 0x01; + } /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode * until each black average reaches the desired value */ @@ -4757,7 +5090,7 @@ dark_calibration (struct Rts8891_Device *dev, int mode, int light) /* do scan */ status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, - CALIBRATION_SIZE, image); + dev->model->calibration_width * 3, image); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "dark_calibration: failed to scan\n"); @@ -4768,12 +5101,13 @@ dark_calibration (struct Rts8891_Device *dev, int mode, int light) if (DBG_LEVEL >= DBG_io2) { sprintf (name, "dark%03d.pnm", num); - write_rgb_data (name, image, CALIBRATION_WIDTH, 1); + write_rgb_data (name, image, dev->model->calibration_width, 1); num++; } /* we now compute the average of red pixels from the first 15 pixels */ global = average_area (SANE_TRUE, image, 15, 1, &ra, &ga, &ba); +// global = average_area (SANE_TRUE, image, dev->model->calibration_width, 1, &ra, &ga, &ba); DBG (DBG_info, "dark_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n", global, ra, ga, ba); @@ -4855,6 +5189,133 @@ dark_calibration (struct Rts8891_Device *dev, int mode, int light) } /* + * wait until lamp is warmed up enough. We repeat 6 single-line scans at + * 1200dpi until the average value change between first and last is below + * 0.3 % + */ +static SANE_Status +lamp_warm_up (struct Rts8891_Device *dev, int mode, int light) +{ + SANE_Status status = SANE_STATUS_GOOD; + int num = 0; + char name[32]; + unsigned char image[9600 * 3]; + float global, ra, ga, ba, first = 0; + int seq = 1; +#define LAMP_MAX_CYCLES 360 /* max. 2 minutes (120s/2s * 6) */ + + DBG (DBG_proc, "lamp_warm_up: start\n"); + + sanei_rts88xx_set_gain (dev->regs, 0, 0, 0); + sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 400, 400 + 9600); /* why 400? */ + + sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); + + dev->regs[0x00] = 0xe5; /* scan */ + dev->regs[0x32] = 0x00; + dev->regs[0x33] = 0x03; + dev->regs[0x35] = 0x0e; + dev->regs[0x36] = 0x22; + dev->regs[0x3a] = 0x0e; + dev->regs[0x40] = 0x20; + + dev->regs[0x7a] = 0x01; + + dev->regs[0x8d] = 0x84; + dev->regs[0x8e] = 0x63; + + dev->regs[0xb2] = 0x02; + + dev->regs[0xc0] = 0x1f; + dev->regs[0xc1] = 0x00; + dev->regs[0xc2] = 0xfe; + dev->regs[0xc3] = 0xe0; + dev->regs[0xc4] = 0xff; + dev->regs[0xc5] = 0x01; + dev->regs[0xc6] = 0x1f; + dev->regs[0xc7] = 0x00; + dev->regs[0xc8] = 0xfe; + dev->regs[0xc9] = 0x00; + dev->regs[0xca] = 0x00; + dev->regs[0xcb] = 0x1c; + dev->regs[0xcc] = 0x00; + dev->regs[0xcd] = 0xc0; + dev->regs[0xce] = 0x01; + dev->regs[0xcf] = 0xeb; + dev->regs[0xd0] = 0xed; + dev->regs[0xd1] = 0xe1; + dev->regs[0xd2] = 0x02; + dev->regs[0xd3] = 0x12; + dev->regs[0xd4] = 0xf4; + dev->regs[0xd5] = 0x86; + dev->regs[0xd6] = 0x1b; + dev->regs[0xd7] = 0x10; + dev->regs[0xd8] = 0xa6; + dev->regs[0xd9] = 0x2d; + dev->regs[0xda] = 0x00; + dev->regs[0xe2] = 0x00; + + /*dev->regs[0xe5] = 0xf7; + dev->regs[0xe6] = 0x2a; */ + SET_DOUBLE (dev->regs, EXPOSURE_REG, 0x2af7); + + dev->regs[0xe7] = 0x00; + dev->regs[0xe8] = 0x00; + dev->regs[0xe9] = 0x00; + dev->regs[0xea] = 0x00; + dev->regs[0xeb] = 0x00; + dev->regs[0xec] = 0x00; + dev->regs[0xed] = 0x00; + dev->regs[0xef] = 0x00; + dev->regs[0xf0] = 0x00; + dev->regs[0xf2] = 0x00; + + /* scan 9600 pixels wide area in color mode 6 times + * if average value difference between first and last scan is 0.3% or greater, + * retry after 2 seconds */ + sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); + while (seq < LAMP_MAX_CYCLES) + { + /* do scan */ + status = + rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x12, + 9600 * 3, image); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "lamp_warm_up: failed to scan\n"); + return status; + } + + /* save scanned picture for data debugging */ + if (DBG_LEVEL >= DBG_io2) + { + sprintf (name, "warm%03d.pnm", num); + write_rgb_data (name, image, 9600, 1); + num++; + } + global = average_area (SANE_TRUE, image, 9600, 1, &ra, &ga, &ba); + if (seq % 6 == 1) + first = global; + if (seq % 6 == 0) + { + DBG (DBG_info, "lamp_warm_up: change=%f\n", global / first); + if (global / first < 1.003) + break; + sleep(2); + } + seq++; + } + if (seq >= LAMP_MAX_CYCLES) + { + DBG (DBG_error0, "lamp_warm_up: timed out waiting for lamp to stabilize\n"); + /* continue anyway */ + } + + DBG (DBG_proc, "lamp_warm_up: exit\n"); + return status; +} + +/* * do gain calibration. We do scans until averaged values of the area match * the target code. We're doing a dichotomy again. */ @@ -4871,9 +5332,9 @@ gain_calibration (struct Rts8891_Device *dev, int mode, int light) int trg, tbg, tgg, bgg, brg, bbg; int num = 0; char name[32]; - int width = CALIBRATION_WIDTH; - int length = CALIBRATION_SIZE; - unsigned char image[CALIBRATION_SIZE]; + int width = dev->model->calibration_width; + int length = dev->model->calibration_width * 3; + unsigned char image[dev->model->calibration_width * 3]; int pass = 0; int timing=0; @@ -4882,7 +5343,10 @@ gain_calibration (struct Rts8891_Device *dev, int mode, int light) DBG (DBG_proc, "gain_calibration: start\n"); /* set up starting values */ - sanei_rts88xx_set_scan_area (dev->regs, 1, 2, xstart, xstart + width); + if (dev->sensor == SENSOR_TYPE_UMAX) + sanei_rts88xx_set_scan_area (dev->regs, 1, 2, xstart, xstart + 2 * width); + else + sanei_rts88xx_set_scan_area (dev->regs, 1, 2, xstart, xstart + width); sanei_rts88xx_set_offset (dev->regs, dev->red_offset, dev->green_offset, dev->blue_offset); @@ -5023,6 +5487,54 @@ gain_calibration (struct Rts8891_Device *dev, int mode, int light) dev->regs[0x87] = 0x00; dev->regs[0x88] = 0x06; } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x33] = 0x01; + dev->regs[0x35] = 0x47; + dev->regs[0x40] = 0xa0; + dev->regs[0x7a] = 0x02; + timing = 0x32; + dev->regs[0x8d] = 0x4f; + dev->regs[0xc0] = 0x66; + dev->regs[0xc1] = 0xc0; + dev->regs[0xc2] = 0x7f; + dev->regs[0xc3] = 0x99; + dev->regs[0xc4] = 0x3f; + dev->regs[0xc5] = 0x80; + dev->regs[0xc6] = 0x66; + dev->regs[0xc7] = 0xc0; + dev->regs[0xc8] = 0x7f; + dev->regs[0xc9] = 0xff; + dev->regs[0xcb] = 0x00; + dev->regs[0xcc] = 0x00; + dev->regs[0xcd] = 0x80; + dev->regs[0xce] = 0xff; + dev->regs[0xcf] = 0xe3; + dev->regs[0xd0] = 0xe8; + dev->regs[0xd1] = 0xee; + dev->regs[0xd2] = 0x0f; + dev->regs[0xd3] = 0x0b; + dev->regs[0xd4] = 0x0d; + dev->regs[0xd7] = 0x10; + dev->regs[0xd8] = 0xa6; + dev->regs[0xda] = 0x00; + dev->regs[0xe2] = 0x07; + + /*dev->regs[0xe5] = 0x1b; 28=40 + dev->regs[0xe6] = 0x01; */ + SET_DOUBLE (dev->regs, EXPOSURE_REG, 283); + + dev->regs[0xe7] = 0x4b; + dev->regs[0xe9] = 0x40; + dev->regs[0xea] = 0x7d; + dev->regs[0xeb] = 0x04; + dev->regs[0xec] = 0x18; + dev->regs[0xed] = 0x85; + dev->regs[0xee] = 0x02; + dev->regs[0xef] = 0x0a; + dev->regs[0xf0] = 0x81; + dev->regs[0xf1] = 0x01; + } SET_DOUBLE (dev->regs, TIMING_REG, timing); SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); @@ -5039,9 +5551,18 @@ gain_calibration (struct Rts8891_Device *dev, int mode, int light) bgg = 0; bbg = 0; /* top values */ - trg = 0x1f; - tgg = 0x1f; - tbg = 0x1f; + if (dev->sensor == SENSOR_TYPE_UMAX) + { + trg = 0x3f; + tgg = 0x3f; + tbg = 0x3f; + } + else + { + trg = 0x1f; + tgg = 0x1f; + tbg = 0x1f; + } /* loop on gain calibration until we find until we find stable value * or we do more than 20 tries */ @@ -5228,7 +5749,7 @@ offset_calibration (struct Rts8891_Device *dev, int mode, int light) int ro = 250, tro = 250, bro = 123; int go = 250, tgo = 250, bgo = 123; int bo = 250, tbo = 250, bbo = 123; - unsigned char image[CALIBRATION_SIZE]; + unsigned char image[dev->model->calibration_width * 3]; float global, ra, ga, ba; int num = 0; char name[32]; @@ -5239,7 +5760,10 @@ offset_calibration (struct Rts8891_Device *dev, int mode, int light) /* gains from previous step are a little higher than the one used */ sanei_rts88xx_set_gain (dev->regs, dev->red_gain, dev->green_gain, dev->blue_gain); - sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH); + if (dev->sensor == SENSOR_TYPE_UMAX) + sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + 2 * dev->model->calibration_width); + else + sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + dev->model->calibration_width); dev->regs[0x32] = 0x00; dev->regs[0x33] = 0x03; @@ -5341,6 +5865,52 @@ offset_calibration (struct Rts8891_Device *dev, int mode, int light) dev->regs[0xef] = 0x02; /* 0x03 */ dev->regs[0xf0] = 0xa8; /* 0x70 */ } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + dev->regs[0x33] = 0x01; + dev->regs[0x35] = 0x47; + dev->regs[0x40] = 0xa0; + dev->regs[0x7a] = 0x02; + /* timing = 0x32; */ + dev->regs[0x8d] = 0x46; + dev->regs[0xc0] = 0x66; + dev->regs[0xc1] = 0xc0; + dev->regs[0xc2] = 0x7f; + dev->regs[0xc3] = 0x99; + dev->regs[0xc4] = 0x3f; + dev->regs[0xc5] = 0x80; + dev->regs[0xc6] = 0x66; + dev->regs[0xc7] = 0xc0; + dev->regs[0xc8] = 0x7f; + dev->regs[0xc9] = 0xff; + dev->regs[0xcb] = 0x00; + dev->regs[0xcc] = 0x00; + dev->regs[0xcd] = 0x80; + dev->regs[0xce] = 0xff; + dev->regs[0xcf] = 0xe3; + dev->regs[0xd0] = 0xe8; + dev->regs[0xd1] = 0xee; + dev->regs[0xd2] = 0x0f; + dev->regs[0xd3] = 0x0b; + dev->regs[0xd4] = 0x0d; + dev->regs[0xd8] = 0xa6; + dev->regs[0xe2] = 0x07; + + /*dev->regs[0xe5] = 0x1b; 28=40 + dev->regs[0xe6] = 0x01; */ + SET_DOUBLE (dev->regs, EXPOSURE_REG, 283); + + dev->regs[0xe7] = 0x4b; + dev->regs[0xe9] = 0x40; + dev->regs[0xea] = 0x7d; + dev->regs[0xeb] = 0x04; + dev->regs[0xec] = 0x18; + dev->regs[0xed] = 0x85; + dev->regs[0xee] = 0x02; + dev->regs[0xef] = 0x0a; + dev->regs[0xf0] = 0x81; + dev->regs[0xf1] = 0x01; + } /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode until each black average * reaches the desired value */ @@ -5351,13 +5921,13 @@ offset_calibration (struct Rts8891_Device *dev, int mode, int light) sanei_rts88xx_set_offset (dev->regs, ro, go, bo); sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, - CALIBRATION_SIZE, image); + dev->model->calibration_width * 3, image); /* save scanned picture for data debugging */ if (DBG_LEVEL >= DBG_io2) { sprintf (name, "offset%03d.pnm", num); - write_rgb_data (name, image, CALIBRATION_WIDTH, 1); + write_rgb_data (name, image, dev->model->calibration_width, 1); num++; } @@ -5465,7 +6035,7 @@ setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int *status1 |= 0x08; } - /* we default to 75 dpi then override needed registers */ + /* we default to 75 dpi (100 for UMAX) then override needed registers */ timing=0x00b0; regs[0x32] = 0x20; regs[0x33] = 0x83; @@ -5543,10 +6113,25 @@ setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int regs[0xe2] = 0x02; /* 0x05 */ exposure=443; } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + regs[0x36] = 0x29; + regs[0x7a] = 0x02; + timing = 0x32; + regs[0x8d] = 0x4f; + regs[0xe2] = 0x00; + /* regs[0xe5] = 0xdf; + regs[0xe6] = 0x08; 8df =2271 */ + exposure=2271; + regs[0xee] = 00; + regs[0xf1] = 00; + } switch (dev->xdpi) { case 75: + case 100: + case 200: break; case 150: @@ -5796,6 +6381,37 @@ setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 300 dpi\n"); return SANE_STATUS_INVAL; break; + case SENSOR_TYPE_UMAX: + DBG (DBG_io, + "setup_shading_calibration: setting up SENSOR_TYPE_UMAX for 300 dpi\n"); + regs[0x36] = 0x2c; + regs[0x40] = 0x20; + regs[0x7a] = 0x01; + regs[0x8d] = 0x12; + regs[0xc0] = 0x87; + regs[0xc1] = 0x07; + regs[0xc2] = 0xf8; + regs[0xc3] = 0x78; + regs[0xc4] = 0xf8; + regs[0xc5] = 0x07; + regs[0xc6] = 0x87; + regs[0xc7] = 0x07; + regs[0xc8] = 0xf8; + regs[0xc9] = 0xfc; + regs[0xca] = 0x0f; + regs[0xcd] = 0x00; + regs[0xce] = 0x80; + regs[0xcf] = 0xe2; + regs[0xd0] = 0xe4; + regs[0xd1] = 0xea; + regs[0xd2] = 0x0b; + regs[0xd3] = 0x17; + regs[0xd4] = 0x01; + regs[0xe2] = 0x07; + /* regs[0xe5] = 0xc9; + regs[0xe6] = 0x01; 0x1c9=457 */ + exposure=457; + break; } break; @@ -5950,6 +6566,46 @@ setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n"); return SANE_STATUS_INVAL; break; + case SENSOR_TYPE_UMAX: + DBG (DBG_io, + "setup_shading_calibration: setting up SENSOR_TYPE_UMAX for 600 dpi\n"); + *status1 = 0x20; + + regs[0x36] = 0x2c; + regs[0x40] = 0x20; + regs[0x7a] = 0x01; + regs[0x8d] = 0x24; + regs[0xc0] = 0xff; + regs[0xc1] = 0x07; + regs[0xc2] = 0x80; + regs[0xc3] = 0x00; + regs[0xc4] = 0xf8; + regs[0xc5] = 0x7f; + regs[0xc6] = 0xff; + regs[0xc7] = 0x07; + regs[0xc8] = 0x80; + regs[0xc9] = 0x00; + regs[0xca] = 0x0f; + regs[0xcc] = 0xfe; + regs[0xcd] = 0x00; + regs[0xce] = 0x00; + regs[0xcf] = 0xd7; + regs[0xd0] = 0x61; + regs[0xd1] = 0xaa; + regs[0xd2] = 0x0b; + regs[0xd3] = 0x03; + regs[0xd4] = 0x05; + regs[0xd5] = 0x86; + regs[0xd6] = 0x1b; + regs[0xd7] = 0x10; + regs[0xd8] = 0xa6; + regs[0xd9] = 0x2d; + + regs[0xe2] = 0x07; + /* regs[0xe5] = 0xae; + regs[0xe6] = 0x02;*/ + exposure=0x02ae; + break; } break; @@ -6100,6 +6756,44 @@ setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n"); return SANE_STATUS_INVAL; break; + + case SENSOR_TYPE_UMAX: + DBG (DBG_io, + "setup_shading_calibration: setting up SENSOR_TYPE_UMAX for 1200 dpi\n"); + *status1 = 0x20; + regs[0x36] = 0x2c; + regs[0x40] = 0x20; + regs[0x7a] = 0x01; + regs[0x8d] = 0x48; + + regs[0xc0] = 0x1f; + regs[0xc1] = 0x00; + regs[0xc2] = 0xfe; + regs[0xc3] = 0xe0; + regs[0xc4] = 0xff; + regs[0xc5] = 0x01; + regs[0xc6] = 0x1f; + regs[0xc7] = 0x00; + regs[0xc8] = 0xfe; + regs[0xc9] = 0x00; + regs[0xca] = 0x00; + regs[0xcb] = 0x1c; + regs[0xcc] = 0x00; + regs[0xcd] = 0xc0; + regs[0xce] = 0x01; + regs[0xcf] = 0xeb; + regs[0xd0] = 0xed; + regs[0xd1] = 0xe1; + regs[0xd2] = 0x02; + /* regs[0xd3] = 0x12; */ + regs[0xd4] = 0xf4; + regs[0xd5] = 0x86; + regs[0xd6] = 0x1b; + regs[0xe2] = 0x07; + /* regs[0xe5] = 0x5e; + regs[0xe6] = 0x05; 0x55e=1374 */ + exposure=1374; + break; } break; } @@ -6113,7 +6807,10 @@ setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int /* in logs, the driver use the computed offset minus 2 */ sanei_rts88xx_set_offset (regs, dev->red_offset, dev->green_offset, dev->blue_offset); sanei_rts88xx_set_gain (regs, dev->red_gain, dev->green_gain, dev->blue_gain); - sanei_rts88xx_set_scan_area (regs, 1, 1 + lines, dev->xstart, dev->xstart + dev->pixels); + if (dev->sensor == SENSOR_TYPE_UMAX && dev->xdpi == 100) + sanei_rts88xx_set_scan_area (regs, 1, 1 + lines, dev->xstart, dev->xstart + 2 * dev->pixels); + else + sanei_rts88xx_set_scan_area (regs, 1, 1 + lines, dev->xstart, dev->xstart + dev->pixels); DBG (DBG_proc, "setup_shading_calibration: exit\n"); return status; @@ -6153,7 +6850,10 @@ shading_calibration (struct Rts8891_Device *dev, SANE_Bool color, int mode, int } if (dev->shading_data != NULL) free (dev->shading_data); - dev->shading_data = (unsigned char *) malloc (dev->bytes_per_line); + if (dev->sensor == SENSOR_TYPE_UMAX && dev->xdpi == 100) + dev->shading_data = (unsigned char *) malloc (2 * dev->bytes_per_line); + else + dev->shading_data = (unsigned char *) malloc (dev->bytes_per_line); if (dev->shading_data == NULL) { free (image); @@ -6217,7 +6917,13 @@ shading_calibration (struct Rts8891_Device *dev, SANE_Bool color, int mode, int { sum += image[x + y * width]; } - dev->shading_data[x] = sum / (lines - 13); + if (dev->sensor == SENSOR_TYPE_UMAX && dev->xdpi == 100) + { + dev->shading_data[2 * x] = sum / (lines - 13); + dev->shading_data[2 * x + 1] = sum / (lines - 13); + } + else + dev->shading_data[x] = sum / (lines - 13); } if (DBG_LEVEL >= DBG_io2) { @@ -6292,10 +6998,17 @@ send_calibration_data (struct Rts8891_Session *session) /* 675 pixels at 75 DPI, 16 bits values, 3 color channels */ /* 5400 pixels at max sensor 600 dpi */ /* 3 16bits 256 value gamma tables plus start/end markers */ - /* must multiple of 32 */ - data_size = (675 * dev->xdpi) / 75; - - width = dev->pixels; + /* must multple of 32 */ + if (dev->sensor == SENSOR_TYPE_UMAX && dev->xdpi == 100) + { + data_size = (675 * 2 * dev->xdpi) / 75; + width = 2 * dev->pixels; + } + else + { + data_size = (675 * dev->xdpi) / 75; + width = dev->pixels; + } /* effective data calibration size */ size = data_size * 2 * 3 + 3 * (512 + 2); @@ -6563,7 +7276,11 @@ setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_ DBG (DBG_warn, "setup_scan_registers: native gray modes not implemented for this model, failure expected\n"); } - sanei_rts88xx_set_scan_area (regs, dev->ystart, dev->ystart + dev->lines, dev->xstart, dev->xstart + dev->pixels); + DBG (DBG_info, "setup_scan_registers: dev->xdpi = %d\n", dev->xdpi); + if (dev->sensor == SENSOR_TYPE_UMAX && dev->xdpi == 100) + sanei_rts88xx_set_scan_area (regs, dev->ystart, dev->ystart + dev->lines, dev->xstart, dev->xstart + 2 * dev->pixels); + else + sanei_rts88xx_set_scan_area (regs, dev->ystart, dev->ystart + dev->lines, dev->xstart, dev->xstart + dev->pixels); DBG (DBG_info, "setup_scan_registers: xstart=%d, pixels=%d\n", dev->xstart, dev->pixels); DBG (DBG_info, "setup_scan_registers: ystart=%d, lines =%d\n", dev->ystart, dev->lines); @@ -6590,7 +7307,7 @@ setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_ *status2 = 0x3b; } - /* default to 75 dpi color scan */ + /* default to 75 dpi (100 for UMAX) color scan */ regs[0x0b] = 0x70; regs[0x0c] = 0x00; regs[0x0d] = 0x00; @@ -6923,9 +7640,73 @@ setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_ regs[0xf0] = 0xa8; /* 0x00 */ regs[0xf2] = 0x01; /* 0x00 */ } + if (dev->sensor == SENSOR_TYPE_UMAX) + { + regs[0x14] = 0xf0; + regs[0x16] = 0x00; + regs[0x23] = 0x00; + regs[0x32] = 0x80; + regs[0x33] = 0x81; + regs[0x40] = 0xa4; + regs[0x7a] = 0x02; + timing=0x0182; + regs[0x85] = 0x10; + regs[0x86] = 0x14; + regs[0x87] = 0x20; + regs[0x88] = 0x22; + regs[0x8d] = 0x4f; + regs[0xc0] = 0x66; + regs[0xc1] = 0xc0; + regs[0xc2] = 0x7f; + regs[0xc3] = 0x99; + regs[0xc4] = 0x3f; + regs[0xc5] = 0x80; + regs[0xc6] = 0x66; + regs[0xc7] = 0xc0; + regs[0xc8] = 0x7f; + regs[0xc9] = 0xff; + regs[0xcb] = 0x00; + regs[0xcc] = 0x00; + regs[0xcd] = 0x80; + regs[0xce] = 0xff; + regs[0xcf] = 0xe3; + regs[0xd0] = 0xe8; + regs[0xd1] = 0xee; + regs[0xd2] = 0x0f; + /*regs[0xd3] = 0x0b;*/ + regs[0xd4] = 0x0d; + + regs[0xd6] = 0x0f; + regs[0xd7] = 0x10; /* 4111 */ + + regs[0xd8] = 0xa6; /* 0xa610=42512 */ + + regs[0xd9] = 0x2d; + regs[0xda] = 0x00; + regs[0xe2] = 0x07; + regs[0xe3] = 0xbd; + regs[0xe4] = 0x08; + + /* regs[0xe5] = 0x1b; + regs[0xe6] = 0x01; exposure time 0x011b=283 */ + exposure=283; + + regs[0xe7] = 0x4b; + regs[0xe9] = 0x40; + regs[0xea] = 0x7d; + regs[0xeb] = 0x04; + regs[0xec] = 0x18; + regs[0xed] = 0x85; + regs[0xee] = 0x02; + regs[0xef] = 0x0a; + regs[0xf0] = 0x81; + regs[0xf1] = 0x01; + } switch (dev->xdpi) { case 75: + case 100: + case 200: break; case 150: regs[0x35] = 0x45; @@ -7042,6 +7823,48 @@ setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_ regs[0xf0] = 0x02; regs[0xf2] = 0x00; break; + case SENSOR_TYPE_UMAX: + DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_UMAX for 150 dpi\n"); + regs[0x32] = 0x20; + regs[0x33] = 0x83; + regs[0x40] = 0x2c; + regs[0x7a] = 0x01; + regs[0x8d] = 0x09; + regs[0xc1] = 0x06; + regs[0xc2] = 0x7e; + regs[0xc4] = 0xf9; + regs[0xc5] = 0x81; + regs[0xc7] = 0x06; + regs[0xc8] = 0x7e; + regs[0xca] = 0x0f; + regs[0xcb] = 0xc0; + regs[0xcd] = 0x00; + regs[0xce] = 0x30; + regs[0xcf] = 0xe4; + regs[0xd0] = 0xe6; + regs[0xd1] = 0xea; + regs[0xd2] = 0x0b; + regs[0xd3] = 0x17; + regs[0xd4] = 0x01; + regs[0xe2] = 0x0f; + regs[0xe3] = 0x89; + regs[0xe4] = 0x03; + /* regs[0xe5] = 0xaa;*/ + exposure = 170; + + regs[0xe7] = 0x00; + regs[0xe8] = 0x79; + regs[0xe9] = 0x01; + regs[0xea] = 0x0b; + regs[0xeb] = 0x58; + regs[0xec] = 0x01; + regs[0xed] = 0x04; + regs[0xee] = 0xbc; + regs[0xef] = 0x00; + regs[0xf0] = 0x03; + regs[0xf1] = 0x00; + regs[0xf2] = 0x00; + break; } break; @@ -7194,6 +8017,59 @@ setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_ regs[0xf0] = 0x00; regs[0xf2] = 0x00; break; + case SENSOR_TYPE_UMAX: + DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_UMAX for 300 dpi\n"); + regs[0x32] = 0x20; + regs[0x33] = 0x83; + regs[0x35] = 0x0e; + regs[0x3a] = 0x0e; + regs[0x40] = 0x2c; + regs[0x7a] = 0x01; + timing=0x022b; + regs[0x85] = 0x18; + regs[0x86] = 0x1b; + regs[0x87] = 0x30; + regs[0x88] = 0x30; + regs[0x8d] = 0x12; + regs[0xc0] = 0x87; + regs[0xc1] = 0x07; + regs[0xc2] = 0xf8; + regs[0xc3] = 0x78; + regs[0xc4] = 0xf8; + regs[0xc5] = 0x07; + regs[0xc6] = 0x87; + regs[0xc7] = 0x07; + regs[0xc8] = 0xf8; + regs[0xc9] = 0xfc; + regs[0xca] = 0x0f; + regs[0xcd] = 0x00; + regs[0xce] = 0x80; + regs[0xcf] = 0xe2; + regs[0xd0] = 0xe4; + regs[0xd1] = 0xea; + regs[0xd2] = 0x0b; + regs[0xd3] = 0x17; + regs[0xd4] = 0x01; + regs[0xe3] = 0x00; + regs[0xe4] = 0x00; + /* regs[0xe5] = 0xc9; + regs[0xe6] = 0x01; */ + exposure = 457; + + regs[0xe7] = 0x00; + regs[0xe8] = 0x00; + regs[0xe9] = 0x00; + regs[0xea] = 0x00; + regs[0xeb] = 0x00; + regs[0xec] = 0x00; + regs[0xed] = 0x00; + regs[0xee] = 0x00; + regs[0xef] = 0x00; + regs[0xf0] = 0x00; + regs[0xf1] = 0x00; + regs[0xf2] = 0x00; + + break; } break; case 600: @@ -7391,6 +8267,75 @@ setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_ DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n"); return SANE_STATUS_INVAL; break; + + case SENSOR_TYPE_UMAX: + DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_UMAX for 600 dpi\n"); +/* *status1 = 0x10; + *status2 = 0x23;*/ + + regs[0x32] = 0x20; + regs[0x33] = 0x83; + regs[0x34] = 0xf0; + regs[0x35] = 0x1b; + regs[0x36] = 0x29; + regs[0x3a] = 0x1b; + regs[0x40] = 0x2c; + regs[0x7a] = 0x01; + regs[0x85] = 0x30; + regs[0x86] = 0x30; + regs[0x87] = 0x60; + regs[0x88] = 0x5a; + regs[0x8d] = 0x24; + + regs[0xc0] = 0xff; + regs[0xc1] = 0x07; + regs[0xc2] = 0x80; + regs[0xc3] = 0x00; + regs[0xc4] = 0xf8; + regs[0xc5] = 0x7f; + regs[0xc6] = 0xff; + regs[0xc7] = 0x07; + regs[0xc8] = 0x80; + regs[0xc9] = 0x00; + regs[0xca] = 0x0f; + + regs[0xcc] = 0xfe; + regs[0xcd] = 0x00; + regs[0xce] = 0x00; + regs[0xcf] = 0xd7; + regs[0xd0] = 0x61; + regs[0xd1] = 0xaa; + regs[0xd2] = 0x0b; + regs[0xd3] = 0x03; + regs[0xd4] = 0x05; + regs[0xd5] = 0x86; + regs[0xd6] = 0x1b; + regs[0xd7] = 0x10; + regs[0xd8] = 0xa6; + regs[0xd9] = 0x2d; + + regs[0xe0] = 0x00; + regs[0xe1] = 0x00; + regs[0xe2] = 0x01; + regs[0xe3] = 0x00; + regs[0xe4] = 0x00; +/* regs[0xe5] = 0xbd; + regs[0xe6] = 0x0a;*/ + exposure=0x0abd; + regs[0xe7] = 0x00; + regs[0xe8] = 0x00; + regs[0xe9] = 0x00; + regs[0xea] = 0x00; + regs[0xeb] = 0x00; + regs[0xec] = 0x00; + regs[0xed] = 0x00; + regs[0xee] = 0x00; + regs[0xef] = 0x00; + regs[0xf0] = 0x00; + regs[0xf1] = 0x00; + regs[0xf2] = 0x00; + timing=0x0425; + break; } break; case 1200: @@ -7584,6 +8529,68 @@ setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_ DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n"); return SANE_STATUS_INVAL; break; + + case SENSOR_TYPE_UMAX: + DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_UMAX for 1200 dpi\n"); + regs[0x32] = 0x20; + regs[0x33] = 0x83; + regs[0x34] = 0xf0; + regs[0x35] = 0x0e; + regs[0x36] = 0x29; + regs[0x3a] = 0x0e; + regs[0x40] = 0x2c; + regs[0x7a] = 0x01; + timing=0x081a; + regs[0x85] = 0x60; + regs[0x86] = 0x5a; + regs[0x87] = 0xc0; + regs[0x88] = 0xae; + regs[0x8d] = 0x48; + + regs[0xc0] = 0x1f; + regs[0xc1] = 0x00; + regs[0xc2] = 0xfe; + regs[0xc3] = 0xe0; + regs[0xc4] = 0xff; + regs[0xc5] = 0x01; + regs[0xc6] = 0x1f; + regs[0xc7] = 0x00; + regs[0xc8] = 0xfe; + regs[0xc9] = 0x00; + regs[0xca] = 0x00; + regs[0xcb] = 0x1c; + regs[0xcc] = 0x00; + regs[0xcd] = 0xc0; + regs[0xce] = 0x01; + regs[0xcf] = 0xeb; + regs[0xd0] = 0xed; + regs[0xd1] = 0xe1; + regs[0xd2] = 0x02; + /* regs[0xd3] = 0x12; */ + regs[0xd4] = 0xf4; + regs[0xd5] = 0x86; + regs[0xd6] = 0x1b; + + regs[0xe2] = 0x00; + regs[0xe3] = 0x00; + regs[0xe4] = 0x00; + /* regs[0xe5] = 0xf7; + regs[0xe6] = 0x2a; */ + exposure=0x2af7; + regs[0xe7] = 0x00; + regs[0xe8] = 0x00; + regs[0xe9] = 0x00; + regs[0xea] = 0x00; + regs[0xeb] = 0x00; + regs[0xec] = 0x00; + regs[0xed] = 0x00; + regs[0xee] = 0x00; + regs[0xef] = 0x00; + regs[0xf0] = 0x00; + regs[0xf1] = 0x00; + regs[0xf2] = 0x00; + + break; } break; } @@ -7661,10 +8668,13 @@ park_head (struct Rts8891_Device *dev, SANE_Bool wait) DBG (DBG_proc, "park_head: start\n"); - reg = 0x8d; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); - reg = 0xad; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + reg = 0x8d; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + reg = 0xad; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + } status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); @@ -7684,10 +8694,13 @@ park_head (struct Rts8891_Device *dev, SANE_Bool wait) } sanei_rts88xx_write_regs (dev->devnum, 0x16, dev->regs + 0x16, 2); - reg = 0x8d; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); - reg = 0xad; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + if (dev->sensor != SENSOR_TYPE_UMAX) + { + reg = 0x8d; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + reg = 0xad; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); + } /* 0x20 expected */ sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, ®); @@ -7738,6 +8751,11 @@ update_button_status (struct Rts8891_Session *session) /* effective button reading */ status = rts8891_read_buttons (session->dev->devnum, &mask); + if (session->dev->sensor == SENSOR_TYPE_UMAX) + { + mask >>= 8; + } + /* release interface if needed */ if (lock == SANE_TRUE) { @@ -7778,6 +8796,11 @@ set_lamp_state (struct Rts8891_Session *session, int on) } } + if (session->dev->sensor == SENSOR_TYPE_UMAX) /* main lamp on UMAX */ + { + sanei_rts88xx_set_status (session->dev->devnum, session->dev->regs, session->dev->has_uta ? 0xa0 : 0x20, on ? 0x3b : 0x1b); + } + status = sanei_rts88xx_read_reg (session->dev->devnum, LAMP_REG, ®); if (on) { diff --git a/backend/rts8891_devices.c b/backend/rts8891_devices.c index 8216a0a..82a934b 100644 --- a/backend/rts8891_devices.c +++ b/backend/rts8891_devices.c @@ -68,6 +68,9 @@ static Rts8891_Model hp4400c_model = { /* default sensor */ SENSOR_TYPE_4400, + /* calibration width */ + 637, + /* default gamma table */ {0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55, @@ -132,6 +135,9 @@ static Rts8891_Model hp4470c_model = { /* default sensor */ SENSOR_TYPE_XPA, + /* calibration width */ + 637, + /* default gamma table */ {0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55, @@ -177,11 +183,25 @@ static Rts8891_Model astra4400_model = { "Astra 4400", /* Device model name */ "flatbed scanner", /* Device type */ - {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ - {600, 300, 150, 0}, /* possible y-resolutions */ +/* Some resolutions supported by Windows driver are emulated: + driver dpi real dpi + ------------------------- + 75 (+preview) 200x100 very fast + 100 200x100 very fast + 150 150x150 + 200 200x200 + 300 300x300 + 400 600x400 + 600 600x600 + 800 1200x1200 + 1200 1200x1200 +*/ + + {1200, 600, 300, 150, 100, 0}, /* possible x-resolutions */ + {1200, 600, 400, 300, 150, 100, 0}, /* possible y-resolutions */ 1200, /* max physical x dpi */ - 600, /* max physical y dpi */ - 150, /* min physical y dpi */ + 1200, /* max physical y dpi */ + 100, /* min physical y dpi */ SANE_FIX (8.3), /* Start of scan area in mm (x) */ SANE_FIX (3.0), /* Start of scan area in mm (y) */ @@ -196,42 +216,43 @@ static Rts8891_Model astra4400_model = { 24, 12, 0, /* R, G, and B CCD Line-distance correction in lines at max motor resolution */ /* default sensor */ - SENSOR_TYPE_XPA, + SENSOR_TYPE_UMAX, + + /* calibration width */ + 750, /* default gamma table */ - {0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, - 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55, - 0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63, 0x64, 0x66, 0x67, - 0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, - 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, - 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, - 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb1, 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, - 0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbc, - 0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc3, 0xc3, 0xc4, - 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xcb, 0xcb, - 0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, - 0xd3, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9, - 0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, - 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, - 0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec, - 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, - 0xf2, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, - 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, - 0xfe, 0xfe, 0xff, 0xff}, + {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}, /* number of buttons */ - 11, + 4, /* button names */ - {"plus", "minus", "copy", "mail", "image-copy", "www", "scan", "power", - "cancel", "options", "toggle-mode"}, + {"scan", "copy", "mail", "custom"}, /* button titles */ - {"plus", "minus", "copy", "mail", "image copy", "www", "scan", "power", - "cancel", "options", "toggle color/gray mode"}, + {"scan", "copy", "mail", "custom"}, /* flags */ RTS8891_FLAG_EMULATED_GRAY_MODE diff --git a/backend/rts8891_low.c b/backend/rts8891_low.c index 1b95765..0eeab87 100644 --- a/backend/rts8891_low.c +++ b/backend/rts8891_low.c @@ -132,10 +132,16 @@ rts8891_write_all (SANE_Int devnum, SANE_Byte * regs, SANE_Int count) buffer[1] = 0xb4; buffer[2] = 0x00; buffer[3] = size; - for (i = 0; i < size; i++) - buffer[i + 4] = regs[0xb4 + i]; + j = 0; + for (i = 0; i < size; i++) { + buffer[i + 4 + j] = regs[0xb4 + i]; + if (buffer[i + 4 + j] == 0xaa) { + j++; + buffer[i + 4 + j] = 0x00; + } + } /* the USB block is size + 4 bytes of header long */ - size += 4; + size += 4 + j; if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) { DBG (DBG_error, @@ -368,6 +374,28 @@ rts8891_data_format (SANE_Int dpi, int sensor) break; } } + if (sensor == SENSOR_TYPE_UMAX) + { + switch (dpi) + { + case 100: /* emulated */ + case 200: + reg = 0x0b; + break; + case 150: + reg = 0x17; + break; + case 300: + reg = 0x17; + break; + case 600: + reg = 0x03; + break; + case 1200: + reg = 0x12; + break; + } + } return reg; } @@ -423,7 +451,12 @@ rts8891_move (struct Rts8891_Device *device, SANE_Byte * regs, /* prepare scan */ rts8891_set_default_regs (regs); - if (device->sensor != SENSOR_TYPE_4400 + if (device->sensor == SENSOR_TYPE_UMAX) + { + regs10 = 0x20; + regs11 = 0x3b; + } + else if (device->sensor != SENSOR_TYPE_4400 && device->sensor != SENSOR_TYPE_4400_BARE) { regs10 = 0x20; @@ -509,6 +542,29 @@ rts8891_move (struct Rts8891_Device *device, SANE_Byte * regs, regs[0xe5] = 0xf3; /* 0xf9 */ regs[0xe6] = 0x01; /* 0x00 */ } + if (device->sensor == SENSOR_TYPE_UMAX) + { + regs[0x14] = 0xf0; + regs[0x16] = 0x0f; + regs[0x23] = 0x00; + regs[0x40] = 0xa0; + /* regs[0x7a] = 0x02; */ + regs[0x80] = 0x83; + regs[0x81] = 0x01; + regs[0x82] = 0x84; + regs[0x83] = 0x01; + regs[0x85] = 0x10; + regs[0x86] = 0x14; + regs[0x87] = 0x20; + regs[0x88] = 0x22; + regs[0x89] = 0x85; + regs[0x8a] = 0x01; + regs[0x8d] = 0x4f; + regs[0xd9] = 0x2d; + regs[0xda] = 0x00; + regs[0xe5] = 0x1b; + regs[0xe6] = 0x01; + } /* disable CCD */ regs[0] = 0xf5; @@ -661,11 +717,13 @@ read_data (struct Rts8891_Session *session, SANE_Byte * dest, SANE_Int length) /* come yet */ if (session->non_blocking && count == 0) { - - dev->regs[LAMP_REG] = 0x8d; - sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, + if (dev->sensor != SENSOR_TYPE_UMAX) + { + dev->regs[LAMP_REG] = 0x8d; + sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); - DBG (DBG_io, "read_data: no data available\n"); + } + DBG (DBG_io, "read_data: no data vailable\n"); DBG (DBG_proc, "read_data: end\n"); return SANE_STATUS_DEVICE_BUSY; } diff --git a/backend/rts8891_low.h b/backend/rts8891_low.h index 453800c..a15b817 100644 --- a/backend/rts8891_low.h +++ b/backend/rts8891_low.h @@ -72,7 +72,8 @@ #define SENSOR_TYPE_XPA 1 /* sensor for hp4470 sold with XPA */ #define SENSOR_TYPE_4400 2 /* sensor for hp4400 */ #define SENSOR_TYPE_4400_BARE 3 /* sensor for hp4400 */ -#define SENSOR_TYPE_MAX 3 /* maximum sensor number value */ +#define SENSOR_TYPE_UMAX 4 /* sensor for Umax Astra 4400/4450 */ +#define SENSOR_TYPE_MAX 4 /* maximum sensor number value */ /* Forward typedefs */ typedef struct Rts8891_Device Rts8891_Device; @@ -130,6 +131,8 @@ typedef struct Rts8891_Model /* default sensor type */ SANE_Int sensor; + SANE_Int calibration_width; + /* default gamma table */ SANE_Word gamma[256]; SANE_Int buttons; /* number of buttons for the scanner */ @@ -173,6 +176,7 @@ struct Rts8891_Device SANE_Bool initialized; /* true if device has been initialized */ SANE_Bool needs_warming; /* true if device needs warming up */ SANE_Bool parking; /* true if device is parking head */ + SANE_Bool has_uta; /* true if UTA is connected */ /* values detected during find origin */ /* TODO these are currently unused after detection */ diff --git a/backend/sm3600.h b/backend/sm3600.h index 2ecbeb2..5d8a8d8 100644 --- a/backend/sm3600.h +++ b/backend/sm3600.h @@ -77,7 +77,11 @@ Start: 2.4.2001 /* ====================================================================== */ +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L typedef enum { false, true } TBool; +#else +typedef bool TBool; +#endif /* GCC < 15 */ typedef SANE_Status TState; diff --git a/backend/snapscan-usb.c b/backend/snapscan-usb.c index 49cca1a..6e6751f 100644 --- a/backend/snapscan-usb.c +++ b/backend/snapscan-usb.c @@ -457,7 +457,7 @@ static int enqueue_bq(int fd,const void *src, size_t src_size) return 0; } -static void dequeue_bq() +static void dequeue_bq(void) { static const char me[] = "dequeue_bq"; struct usb_busy_queue *tbqe; diff --git a/backend/test.c b/backend/test.c index 4663a16..bb2b643 100644 --- a/backend/test.c +++ b/backend/test.c @@ -1255,7 +1255,7 @@ fail: } static void -cleanup_initial_string_values () +cleanup_initial_string_values (void) { // Cleanup backing memory for initial values of string options. free (init_mode); diff --git a/backend/umax_pp_low.c b/backend/umax_pp_low.c index d1f3c16..6d80d43 100644 --- a/backend/umax_pp_low.c +++ b/backend/umax_pp_low.c @@ -1496,7 +1496,7 @@ ECPFifoMode (void) /* wait for ack bit */ /* return 1 on success, 0 on error */ static int -waitAck () +waitAck (void) { unsigned char breg = 0; int i = 0; diff --git a/backend/umax_pp_mid.c b/backend/umax_pp_mid.c index ef608ac..b5266b3 100644 --- a/backend/umax_pp_mid.c +++ b/backend/umax_pp_mid.c @@ -449,7 +449,7 @@ sanei_umax_pp_status (void) } int -sanei_umax_pp_close () +sanei_umax_pp_close (void) { #ifdef HAVE_LINUX_PPDEV_H int fd; diff --git a/backend/xerox_mfp-usb.c b/backend/xerox_mfp-usb.c index 519aba6..d083238 100644 --- a/backend/xerox_mfp-usb.c +++ b/backend/xerox_mfp-usb.c @@ -22,7 +22,7 @@ extern int sanei_debug_xerox_mfp; static int -xerox_need_clear_halt() +xerox_need_clear_halt(void) { char *env; int workaround = 0; diff --git a/backend/xerox_mfp.c b/backend/xerox_mfp.c index 0821754..48e1eca 100644 --- a/backend/xerox_mfp.c +++ b/backend/xerox_mfp.c @@ -212,6 +212,7 @@ static int isSupportedDevice(struct device __sane_unused__ *dev) /* blacklist malfunctioning device(s) */ if (!strncmp (dev->sane.model, "SCX-4500W", 9) || !strncmp (dev->sane.model, "C460", 4) + || !!strstr(dev->sane.model, "SCX-472") || !!strstr (dev->sane.model, "WorkCentre 3225") || !!strstr (dev->sane.model, "CLX-3170") || !!strstr (dev->sane.model, "4x24") @@ -502,7 +503,7 @@ static SANE_String_Const doc_sources[] = { }; static int doc_source_to_code[] = { - 0x40, 0x20, 0x80 + DOC_FLATBED, DOC_ADF, DOC_AUTO }; static SANE_String_Const scan_modes[] = { @@ -702,6 +703,14 @@ static void set_parameters(struct device *dev) } } +/* determine if document is to be sourced from ADF */ +static int sourcing_from_adf(struct device *dev) +{ + return (dev->doc_source == DOC_ADF || + (dev->doc_source == DOC_AUTO && dev->doc_loaded)); +} + + /* resolve all options related to scan window */ /* called after option changed and in set_window */ static int fix_window(struct device *dev) @@ -731,11 +740,10 @@ static int fix_window(struct device *dev) dev->doc_source = doc_source_to_code[string_match_index(doc_sources, dev->val[OPT_SOURCE].s)]; /* max window len is dependent of document source */ - if (dev->doc_source == DOC_FLATBED || - (dev->doc_source == DOC_AUTO && !dev->doc_loaded)) - dev->max_len = dev->max_len_fb; - else + if (sourcing_from_adf(dev)) dev->max_len = dev->max_len_adf; + else + dev->max_len = dev->max_len_fb; /* parameters */ dev->win_y_range.max = SANE_FIX((double)dev->max_len / PNT_PER_MM); @@ -879,8 +887,9 @@ dev_inquiry(struct device *dev) dev->res[0x3f]; dev->line_order = dev->res[0x31]; dev->compressionTypes = dev->res[0x32]; - dev->doc_loaded = (dev->res[0x35] == 0x02) && - (dev->res[0x26] & 0x03); + dev->has_adf = ((dev->res[0x26] & 0x03) != 0); + dev->doc_loaded = (dev->res[0x35] == 0x02) + && dev->has_adf; init_options(dev); reset_options(dev); @@ -891,6 +900,25 @@ dev_inquiry(struct device *dev) return SANE_STATUS_GOOD; } + +static SANE_Status +dev_inquiry_adf_status(struct device *dev) +{ + if (!dev_cmd(dev, CMD_INQUIRY)) + return SANE_STATUS_IO_ERROR; + + dev->has_adf = ((dev->res[0x26] & 0x03) != 0); + dev->doc_loaded = (dev->res[0x35] == 0x02) + && dev->has_adf; + + DBG(3, "%s: ADF present: %s, loaded: %s\n", __func__, + (dev->has_adf ? "true" : "false"), + (dev->doc_loaded ? "true" : "false")); + + return SANE_STATUS_GOOD; +} + + const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle h, SANE_Int opt) { @@ -1361,7 +1389,10 @@ sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp) remove(encTmpFileName); } /* that's all */ - dev_stop(dev); + /* finished receving the document; */ + /* stop and release the unit, unless sourcing from ADF */ + if (!sourcing_from_adf(dev)) + dev_stop(dev); return SANE_STATUS_EOF; } @@ -1465,7 +1496,6 @@ SANE_Status sane_start(SANE_Handle h) { struct device *dev = h; - DBG(3, "%s: %p\n", __func__, h); dev->cancel = 0; @@ -1476,22 +1506,24 @@ sane_start(SANE_Handle h) dev->blocks = 0; if (!dev->reserved) { + if (dev->has_adf + && (dev->doc_source == DOC_AUTO || dev->doc_source == DOC_ADF)) { + if (dev_inquiry_adf_status(dev) != SANE_STATUS_GOOD) + return dev_stop(dev); + } + if (!dev_cmd_wait(dev, CMD_RESERVE_UNIT)) return dev->state; dev->reserved++; - } - if (!dev_set_window(dev) || - (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY)) - return dev_stop(dev); + if (!dev_set_window(dev) || + (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY)) + return dev_stop(dev); + } if (!dev_cmd_wait(dev, CMD_OBJECT_POSITION)) return dev_stop(dev); - if (!dev_cmd(dev, CMD_READ) || - (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY)) - return dev_stop(dev); - dev->scanning = 1; dev->final_block = 0; dev->blocklen = 0; diff --git a/backend/xerox_mfp.conf.in b/backend/xerox_mfp.conf.in index d9deecc..4d1d934 100644 --- a/backend/xerox_mfp.conf.in +++ b/backend/xerox_mfp.conf.in @@ -169,6 +169,10 @@ usb 0x04e8 0x3450 #Samsung SCX-472x Series, Samsung SCX-4729FD usb 0x04e8 0x3453 +#Samsung SCX-4729FW, network mode +# tcp HOST_NAME_OR_IP PORT +#tcp scx4729fw 9400 + #Samsung CLX-6260 Series usb 0x04e8 0x3455 diff --git a/backend/xerox_mfp.h b/backend/xerox_mfp.h index 6aa83a4..ebd1b56 100644 --- a/backend/xerox_mfp.h +++ b/backend/xerox_mfp.h @@ -64,6 +64,7 @@ struct device { int state; /* current state */ int reserved; /* CMD_RESERVE_UNIT */ int reading; /* READ_IMAGE is sent */ + int has_adf; /* ADF is present */ SANE_Byte *data; /* postprocessing cyclic buffer 64k */ int datalen; /* how data in buffer */ |