diff options
Diffstat (limited to 'backend/canon_dr.c')
| -rw-r--r-- | backend/canon_dr.c | 203 | 
1 files changed, 137 insertions, 66 deletions
| diff --git a/backend/canon_dr.c b/backend/canon_dr.c index de7ed7e..95799e7 100644 --- a/backend/canon_dr.c +++ b/backend/canon_dr.c @@ -3,7 +3,7 @@     This file is part of the SANE package, and implements a SANE backend     for various Canon DR-series scanners. -   Copyright (C) 2008-2020 m. allan noah +   Copyright (C) 2008-2021 m. allan noah     Yabarana Corp. www.yabarana.com provided significant funding     EvriChart, Inc. www.evrichart.com provided funding and loaned equipment @@ -346,6 +346,15 @@           - add new gray and color interlacing options for DR-C120           - initial support for DR-C120 and C130           - enable fine calibration for P-208 (per @sashacmc in !546) +      v61 2021-02-13, MAN +         - treat DR-P208 like P-208 (#356) +         - treat DR-P215 like P-215 (#356) +         - adjust wait_scanner to try one TUR with a long timeout (#142) +      v62 2021-02-13, MAN +         - allow config file to set inq and vpd lengths for DR-M1060 (#263) +         - rewrite do_cmd() timeout handling +         - remove long timeout TUR from v61 (did not help) +         - allow config file to set initial tur timeout for DR-X10C (#142)     SANE FLOW DIAGRAM @@ -384,6 +393,7 @@  #include <math.h> /*tan*/  #include <unistd.h> /*usleep*/  #include <sys/time.h> /*gettimeofday*/ +#include <stdlib.h> /*strtol*/  #include "../include/sane/sanei_backend.h"  #include "../include/sane/sanei_scsi.h" @@ -396,7 +406,7 @@  #include "canon_dr.h"  #define DEBUG 1 -#define BUILD 60 +#define BUILD 62  /* values for SANE_DEBUG_CANON_DR env var:   - errors           5 @@ -448,6 +458,10 @@ static int global_extra_status;  static int global_extra_status_default = 0;  static int global_duplex_offset;  static int global_duplex_offset_default = 0; +static int global_inquiry_length; +static int global_vpd_length; +static int global_tur_timeout; +static int global_tur_timeout_default = USB_PACKET_TIMEOUT/60; /* half second */  static char global_vendor_name[9];  static char global_model_name[17];  static char global_version_name[5]; @@ -486,10 +500,10 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)    DBG (10, "sane_init: start\n");    if (version_code) -    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); +    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);    DBG (5, "sane_init: canon_dr backend %d.%d.%d, from %s\n", -    SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); +    SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);    DBG (10, "sane_init: finish\n"); @@ -675,6 +689,84 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)                    global_duplex_offset = buf;                } +              /* INQUIRY_LENGTH: <= 0x30 */ +              else if (!strncmp (lp, "inquiry-length", 14) && isspace (lp[14])) { + +                  int buf; +                  lp += 14; +                  lp = sanei_config_skip_whitespace (lp); +                  buf = (int) strtol (lp,NULL,16); + +                  if (buf > INQUIRY_std_max_len) { +                    DBG (5, "sane_get_devices: config option \"inquiry-length\" " +                      "(%#04x) is > %#04x, ignoring!\n", buf, INQUIRY_std_max_len); +                    continue; +                  } + +                  if (buf < 0) { +                    DBG (5, "sane_get_devices: config option \"inquiry-length\" " +                      "(%#04x) is < 0, ignoring!\n", buf); +                    continue; +                  } + +                  DBG (15, "sane_get_devices: setting \"inquiry-length\" to %#04x\n", +                    buf); + +                  global_inquiry_length = buf; +              } + +              /* VPD_LENGTH: <= 0x30 */ +              else if (!strncmp (lp, "vpd-length", 10) && isspace (lp[10])) { + +                  int buf; +                  lp += 10; +                  lp = sanei_config_skip_whitespace (lp); +                  buf = (int) strtol (lp,NULL,16); + +                  if (buf > INQUIRY_vpd_max_len) { +                    DBG (5, "sane_get_devices: config option \"vpd-length\" " +                      "(%#04x) is > %#04x, ignoring!\n", buf, INQUIRY_vpd_max_len); +                    continue; +                  } + +                  if (buf < 0) { +                    DBG (5, "sane_get_devices: config option \"vpd-length\" " +                      "(%#04x) is < 0, ignoring!\n", buf); +                    continue; +                  } + +                  DBG (15, "sane_get_devices: setting \"vpd-length\" to %#04x\n", +                    buf); + +                  global_vpd_length = buf; +              } + +              /* TUR_TIMEOUT <= 60000 */ +              else if (!strncmp (lp, "tur-timeout", 11) && isspace (lp[11])) { + +                  int buf; +                  lp += 11; +                  lp = sanei_config_skip_whitespace (lp); +                  buf = atoi (lp); + +                  if (buf > 60000) { +                    DBG (5, "sane_get_devices: config option \"tur-timeout\" " +                      "(%d) is > 60000, ignoring!\n", buf); +                    continue; +                  } + +                  if (buf < 0) { +                    DBG (5, "sane_get_devices: config option \"tur-timeout\" " +                      "(%d) is < 0, ignoring!\n", buf); +                    continue; +                  } + +                  DBG (15, "sane_get_devices: setting \"tur-timeout\" to %d\n", +                    buf); + +                  global_tur_timeout = buf; +              } +                /* VENDOR: we ingest up to 8 bytes */                else if (!strncmp (lp, "vendor-name", 11) && isspace (lp[11])) { @@ -841,6 +933,9 @@ attach_one (const char *device_name, int connType)    s->padded_read = global_padded_read;    s->extra_status = global_extra_status;    s->duplex_offset = global_duplex_offset; +  s->inquiry_length = global_inquiry_length; +  s->vpd_length = global_vpd_length; +  s->tur_timeout = global_tur_timeout;    /* copy the device name */    strcpy (s->device_name, device_name); @@ -1017,8 +1112,8 @@ init_inquire (struct scanner *s)    unsigned char cmd[INQUIRY_len];    size_t cmdLen = INQUIRY_len; -  unsigned char in[INQUIRY_std_len]; -  size_t inLen = INQUIRY_std_len; +  unsigned char in[INQUIRY_std_max_len]; +  size_t inLen = s->inquiry_length;    DBG (10, "init_inquire: start\n"); @@ -1099,8 +1194,8 @@ init_vpd (struct scanner *s)    unsigned char cmd[INQUIRY_len];    size_t cmdLen = INQUIRY_len; -  unsigned char in[INQUIRY_vpd_len]; -  size_t inLen = INQUIRY_vpd_len; +  unsigned char in[INQUIRY_vpd_max_len]; +  size_t inLen = s->vpd_length;    DBG (10, "init_vpd: start\n"); @@ -1491,7 +1586,8 @@ init_model (struct scanner *s)      s->has_card = 1;    } -  else if (strstr (s->model_name, "P-208")) { +  else if (strstr (s->model_name, "P-208") +   || strstr (s->model_name,"DR-P208")){      s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB;      s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_rRgGbB;      s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG; @@ -1508,7 +1604,8 @@ init_model (struct scanner *s)      s->can_read_sensors = 1;    } -  else if (strstr (s->model_name, "P-215")) { +  else if (strstr (s->model_name, "P-215") +   || strstr (s->model_name,"DR-P215")){      s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_rRgGbB;      s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB;      s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_gG; @@ -7079,6 +7176,9 @@ default_globals(void)    global_padded_read = global_padded_read_default;    global_extra_status = global_extra_status_default;    global_duplex_offset = global_duplex_offset_default; +  global_inquiry_length = INQUIRY_std_typ_len; +  global_vpd_length = INQUIRY_vpd_typ_len; +  global_tur_timeout = global_tur_timeout_default;    global_vendor_name[0] = 0;    global_model_name[0] = 0;    global_version_name[0] = 0; @@ -7332,21 +7432,21 @@ sense_handler (int fd, unsigned char * sensed_data, void *arg)   * take a bunch of pointers, send commands to scanner   */  static SANE_Status -do_cmd(struct scanner *s, int runRS, int shortTime, +do_cmd(struct scanner *s, int runRS, int timeout,   unsigned char * cmdBuff, size_t cmdLen,   unsigned char * outBuff, size_t outLen,   unsigned char * inBuff, size_t * inLen  )  {      if (s->connection == CONNECTION_SCSI) { -        return do_scsi_cmd(s, runRS, shortTime, +        return do_scsi_cmd(s, runRS, timeout,                   cmdBuff, cmdLen,                   outBuff, outLen,                   inBuff, inLen          );      }      if (s->connection == CONNECTION_USB) { -        return do_usb_cmd(s, runRS, shortTime, +        return do_usb_cmd(s, runRS, timeout,                   cmdBuff, cmdLen,                   outBuff, outLen,                   inBuff, inLen @@ -7356,7 +7456,7 @@ do_cmd(struct scanner *s, int runRS, int shortTime,  }  static SANE_Status -do_scsi_cmd(struct scanner *s, int runRS, int shortTime, +do_scsi_cmd(struct scanner *s, int runRS, int timeout,   unsigned char * cmdBuff, size_t cmdLen,   unsigned char * outBuff, size_t outLen,   unsigned char * inBuff, size_t * inLen @@ -7366,7 +7466,7 @@ do_scsi_cmd(struct scanner *s, int runRS, int shortTime,    /*shut up compiler*/    runRS=runRS; -  shortTime=shortTime; +  timeout=timeout;    DBG(10, "do_scsi_cmd: start\n"); @@ -7404,7 +7504,7 @@ do_scsi_cmd(struct scanner *s, int runRS, int shortTime,  }  static SANE_Status -do_usb_cmd(struct scanner *s, int runRS, int shortTime, +do_usb_cmd(struct scanner *s, int runRS, int timeout,   unsigned char * cmdBuff, size_t cmdLen,   unsigned char * outBuff, size_t outLen,   unsigned char * inBuff, size_t * inLen @@ -7414,21 +7514,19 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,      size_t cmdLength = 0;      size_t cmdActual = 0;      unsigned char * cmdBuffer = NULL; -    int cmdTimeout = 0;      size_t outOffset = 0;      size_t outLength = 0;      size_t outActual = 0;      unsigned char * outBuffer = NULL; -    int outTimeout = 0;      size_t inOffset = 0;      size_t inLength = 0;      size_t inActual = 0;      unsigned char * inBuffer = NULL; -    int inTimeout = 0;      size_t extraLength = 0; +    int actTimeout = timeout ? timeout : USB_PACKET_TIMEOUT;      int ret = 0;      int ret2 = 0; @@ -7438,18 +7536,15 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,      DBG (10, "do_usb_cmd: start %lu %lu\n", (long unsigned int)timer.tv_sec, (long unsigned int)timer.tv_usec); +    /* change timeout */ +    sanei_usb_set_timeout(actTimeout); +      /****************************************************************/      /* the command stage */      {        cmdOffset = USB_HEADER_LEN;        cmdLength = cmdOffset+USB_COMMAND_LEN;        cmdActual = cmdLength; -      cmdTimeout = USB_COMMAND_TIME; - -      /* change timeout */ -      if(shortTime) -        cmdTimeout/=60; -      sanei_usb_set_timeout(cmdTimeout);        /* build buffer */        cmdBuffer = calloc(cmdLength,1); @@ -7465,7 +7560,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,        memcpy(cmdBuffer+cmdOffset,cmdBuff,cmdLen);        /* write the command out */ -      DBG(25, "cmd: writing %d bytes, timeout %d\n", (int)cmdLength, cmdTimeout); +      DBG(25, "cmd: writing %d bytes, timeout %d\n", (int)cmdLength, actTimeout);        hexdump(30, "cmd: >>", cmdBuffer, cmdLength);        ret = sanei_usb_write_bulk(s->fd, cmdBuffer, &cmdActual);        DBG(25, "cmd: wrote %d bytes, retVal %d\n", (int)cmdActual, ret); @@ -7488,7 +7583,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,      /* this is like the regular status block, with an additional    */      /* length component at the end */      if(s->extra_status){ -      ret2 = do_usb_status(s,runRS,shortTime,&extraLength); +      ret2 = do_usb_status(s,runRS,timeout,&extraLength);        /* bail out on bad RS status */        if(ret2){ @@ -7504,12 +7599,6 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,        outOffset = USB_HEADER_LEN;        outLength = outOffset+outLen;        outActual = outLength; -      outTimeout = USB_DATA_TIME; - -      /* change timeout */ -      if(shortTime) -        outTimeout/=60; -      sanei_usb_set_timeout(outTimeout);        /* build outBuffer */        outBuffer = calloc(outLength,1); @@ -7525,7 +7614,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,        memcpy(outBuffer+outOffset,outBuff,outLen);        /* write the command out */ -      DBG(25, "out: writing %d bytes, timeout %d\n", (int)outLength, outTimeout); +      DBG(25, "out: writing %d bytes, timeout %d\n", (int)outLength, actTimeout);        hexdump(30, "out: >>", outBuffer, outLength);        ret = sanei_usb_write_bulk(s->fd, outBuffer, &outActual);        DBG(25, "out: wrote %d bytes, retVal %d\n", (int)outActual, ret); @@ -7563,13 +7652,6 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,        /*blast caller's copy in case we error out*/        *inLen = 0; -      inTimeout = USB_DATA_TIME; - -      /* change timeout */ -      if(shortTime) -        inTimeout/=60; -      sanei_usb_set_timeout(inTimeout); -        /* build inBuffer */        inBuffer = calloc(inActual,1);        if(!inBuffer){ @@ -7577,7 +7659,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,          return SANE_STATUS_NO_MEM;        } -      DBG(25, "in: reading %d bytes, timeout %d\n", (int)inActual, inTimeout); +      DBG(25, "in: reading %d bytes, timeout %d\n", (int)inActual, actTimeout);        ret = sanei_usb_read_bulk(s->fd, inBuffer, &inActual);        DBG(25, "in: read %d bytes, retval %d\n", (int)inActual, ret);        hexdump(31, "in: <<", inBuffer, inActual); @@ -7603,7 +7685,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,      /****************************************************************/      /* the normal status stage */ -    ret2 = do_usb_status(s,runRS,shortTime,&extraLength); +    ret2 = do_usb_status(s,runRS,timeout,&extraLength);      /* if status said EOF, adjust input with remainder count */      if(ret2 == SANE_STATUS_EOF && inBuffer){ @@ -7651,7 +7733,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,  }  static SANE_Status -do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength) +do_usb_status(struct scanner *s, int runRS, int timeout, size_t * extraLength)  {  #define EXTRA_READ_len 4 @@ -7661,7 +7743,8 @@ do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength)      size_t statLength = 0;      size_t statActual = 0;      unsigned char * statBuffer = NULL; -    int statTimeout = 0; + +    int actTimeout = timeout ? timeout : USB_PACKET_TIMEOUT;      int ret = 0; @@ -7675,12 +7758,9 @@ do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength)        statLength += EXTRA_READ_len;      statActual = statLength; -    statTimeout = USB_STATUS_TIME;      /* change timeout */ -    if(shortTime) -      statTimeout/=60; -    sanei_usb_set_timeout(statTimeout); +    sanei_usb_set_timeout(timeout ? timeout : USB_PACKET_TIMEOUT);      /* build statBuffer */      statBuffer = calloc(statLength,1); @@ -7689,7 +7769,7 @@ do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength)        return SANE_STATUS_NO_MEM;      } -    DBG(25, "stat: reading %d bytes, timeout %d\n", (int)statLength, statTimeout); +    DBG(25, "stat: reading %d bytes, timeout %d\n", (int)statLength, actTimeout);      ret = sanei_usb_read_bulk(s->fd, statBuffer, &statActual);      DBG(25, "stat: read %d bytes, retval %d\n", (int)statActual, ret);      hexdump(30, "stat: <<", statBuffer, statActual); @@ -7754,7 +7834,7 @@ do_usb_clear(struct scanner *s, int clear, int runRS)          DBG(25,"rs sub call >>\n");          ret2 = do_cmd( -          s,0,0, +          s, 0, 0,            rs_cmd, rs_cmdLen,            NULL,0,            rs_in, &rs_inLen @@ -7796,7 +7876,7 @@ wait_scanner(struct scanner *s)    set_SCSI_opcode(cmd,TEST_UNIT_READY_code);    ret = do_cmd ( -    s, 0, 1, +    s, 0, s->tur_timeout,      cmd, cmdLen,      NULL, 0,      NULL, NULL @@ -7805,7 +7885,7 @@ wait_scanner(struct scanner *s)    if (ret != SANE_STATUS_GOOD) {      DBG(5,"WARNING: Brain-dead scanner. Hitting with stick.\n");      ret = do_cmd ( -      s, 0, 1, +      s, 0, s->tur_timeout,        cmd, cmdLen,        NULL, 0,        NULL, NULL @@ -7814,7 +7894,7 @@ wait_scanner(struct scanner *s)    if (ret != SANE_STATUS_GOOD) {      DBG(5,"WARNING: Brain-dead scanner. Hitting with stick again.\n");      ret = do_cmd ( -      s, 0, 1, +      s, 0, s->tur_timeout,        cmd, cmdLen,        NULL, 0,        NULL, NULL @@ -7823,18 +7903,9 @@ wait_scanner(struct scanner *s)    // some scanners (such as DR-F120) are OK but will not respond to commands    // when in sleep mode. By checking the sense it wakes them up.    if (ret != SANE_STATUS_GOOD) { -    DBG(5,"WARNING: Brain-dead scanner. Hitting with request sense.\n"); -    ret = do_cmd ( -      s, 1, 1, -      cmd, cmdLen, -      NULL, 0, -      NULL, NULL -    ); -  } -  if (ret != SANE_STATUS_GOOD) { -    DBG(5,"WARNING: Brain-dead scanner. Hitting with stick a third time.\n"); +    DBG(5,"WARNING: Brain-dead scanner. Hitting with stick and request sense.\n");      ret = do_cmd ( -      s, 0, 1, +      s, 1, s->tur_timeout,        cmd, cmdLen,        NULL, 0,        NULL, NULL @@ -7843,7 +7914,7 @@ wait_scanner(struct scanner *s)    if (ret != SANE_STATUS_GOOD) {      DBG(5,"WARNING: Brain-dead scanner. Hitting with stick a fourth time.\n");      ret = do_cmd ( -      s, 0, 1, +      s, 0, s->tur_timeout,        cmd, cmdLen,        NULL, 0,        NULL, NULL | 
