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 */ | 
