[sane-devel] Allow users to specify the timeout of network operations (PIXMA)

Frederick Zhang frederick888 at tsundere.moe
Tue Dec 27 21:15:54 UTC 2016


Hi SANE developers,

I'm using SANE to drive my Canon MG5765 and it is great except the 
"select timed out" issue occurs quite often. My router is fairly 
outdated and actually the machine itself lags a lot when scanning with 
high DPI. I've created a simple patch (and tested) to allow specifying 
the timeout limit in configuration file, not sure whether it would help 
or not :)

diff --git a/backend/pixma.conf.in b/backend/pixma.conf.in
index a275b033..c60e4a07 100644
--- a/backend/pixma.conf.in
+++ b/backend/pixma.conf.in
@@ -11,4 +11,5 @@
  # Example:
  # bjnp://myscanner.my.domain:8612
  # bjnp://printer-1.pheasant.org
+# bjnp://scanner.bad-network.org/timeout=1500
  #
diff --git a/backend/pixma_bjnp.c b/backend/pixma_bjnp.c
index c62bd71a..9a1e698f 100644
--- a/backend/pixma_bjnp.c
+++ b/backend/pixma_bjnp.c
@@ -1412,7 +1412,7 @@ bjnp_recv_header (int devno, size_t *payload_size )
    int attempt;

    PDBG (bjnp_dbg
-    (LOG_DEBUG, "bjnp_recv_header: receiving response header\n") );
+  (LOG_DEBUG, "bjnp_recv_header: receiving response header\n") );
    fd = device[devno].tcp_socket;

    *payload_size = 0;
@@ -1442,7 +1442,7 @@ bjnp_recv_header (int devno, size_t *payload_size )
      {
        terrno = errno;
        PDBG (bjnp_dbg (LOG_CRIT,
-               "bjnp_recv_header: ERROR - could not read response 
header (select timed out)!\n" ) );
+               "bjnp_recv_header: ERROR - could not read response 
header (select timed out, limit: %d)!\n", device[devno].bjnp_timeout ) );
        errno = terrno;
        return SANE_STATUS_IO_ERROR;
      }
@@ -1502,7 +1502,7 @@ bjnp_recv_header (int devno, size_t *payload_size )
  }

  static int
-bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa, 
bjnp_protocol_defs_t *protocol_defs)
+bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa, 
bjnp_protocol_defs_t *protocol_defs, int min_timeout)
  {
    /* initialize device structure */

@@ -1524,7 +1524,8 @@ bjnp_init_device_structure(int dn, bjnp_sockaddr_t 
*sa, bjnp_protocol_defs_t *pr
    device[dn].address_level = get_scanner_name(sa, name);
    device[dn].session_id = 0;
    device[dn].serial = -1;
-  device[dn].bjnp_timeout = 1000;
+  device[dn].bjnp_timeout = min_timeout;
+  device[dn].bjnp_min_timeout = min_timeout;
    device[dn].scanner_data_left = 0;
    device[dn].last_cmd = 0;
    device[dn].blocksize = BJNP_BLOCKSIZE_START;
@@ -1617,7 +1618,7 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, 
size_t start_pos, size_t * len)
      {
        terrno = errno;
        PDBG (bjnp_dbg (LOG_CRIT,
-               "bjnp_recv_data: ERROR - could not read response payload 
(select timed out)!\n") );
+               "bjnp_recv_data: ERROR - could not read response payload 
(select timed out, limit: %d)!\n", device[devno].bjnp_timeout) );
        errno = terrno;
        *len = 0;
        return SANE_STATUS_IO_ERROR;
@@ -1654,6 +1655,7 @@ bjnp_allocate_device (SANE_String_Const devname,
    struct addrinfo hints;
    int result;
    int i;
+  int min_timeout = BJNP_TIMEOUT_MIN;

    PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_allocate_device(%s) %d\n", devname, 
bjnp_no_devices));

@@ -1664,12 +1666,19 @@ bjnp_allocate_device (SANE_String_Const devname,

    if (strlen (args) != 0)
      {
-      PDBG (bjnp_dbg
-        (LOG_CRIT,
-         "bjnp_allocate_device: ERROR - URI may not contain userid, 
password or aguments: %s\n",
-         devname));
+      if (strlen(args) > 8 && strncmp(args, "timeout=", 8) == 0)
+        {
+          min_timeout = atoi(args + 8);
+          if (min_timeout < BJNP_TIMEOUT_MIN)
+            min_timeout = BJNP_TIMEOUT_MIN;
+        } else {
+          PDBG (bjnp_dbg
+            (LOG_CRIT,
+            "bjnp_allocate_device: ERROR - URI may not contain userid, 
password or aguments except timtout: %s\n",
+            devname));

-      return BJNP_STATUS_INVAL;
+          return BJNP_STATUS_INVAL;
+        }
      }
    if ( (protocol_defs = get_protocol_by_method(method)) == NULL)
      {
@@ -1721,7 +1730,7 @@ bjnp_allocate_device (SANE_String_Const devname,
            return BJNP_STATUS_INVAL;
          }
        if (bjnp_init_device_structure( bjnp_no_devices, 
(bjnp_sockaddr_t *)cur -> ai_addr,
-                                      protocol_defs) != 0)
+                                      protocol_defs, min_timeout) != 0)
          {
            /* giving up on this address, try next one if any */
            break;
@@ -1742,6 +1751,12 @@ bjnp_allocate_device (SANE_String_Const devname,
                    device[bjnp_no_devices].addr = NULL;
                    device[i].address_level = 
device[bjnp_no_devices].address_level;
                  }
+              if (device[i].bjnp_min_timeout < 
device[bjnp_no_devices].bjnp_min_timeout)
+                {
+                  /* use the longer timeout as user wants */
+                  device[i].bjnp_timeout = 
device[bjnp_no_devices].bjnp_min_timeout;
+                  device[i].bjnp_min_timeout = 
device[bjnp_no_devices].bjnp_min_timeout;
+                }
                freeaddrinfo(res);
                *dn = i;
                bjnp_free_device_structure( bjnp_no_devices);
@@ -2182,11 +2197,11 @@ sanei_bjnp_deactivate (SANE_Int dn)
  extern void
  sanei_bjnp_set_timeout (SANE_Int devno, SANE_Int timeout)
  {
-  if (timeout < BJNP_TIMEOUT_MIN)
+  if (timeout < device[devno].bjnp_min_timeout)
      {
        PDBG (bjnp_dbg (LOG_INFO, "bjnp_set_timeout to %d, but using 
minimum value %d\n",
-           timeout, BJNP_TIMEOUT_MIN));
-      timeout = BJNP_TIMEOUT_MIN;
+           timeout, device[devno].bjnp_min_timeout));
+      timeout = device[devno].bjnp_min_timeout;
      } else {
        PDBG (bjnp_dbg (LOG_INFO, "bjnp_set_timeout to %d\n",
             timeout));
diff --git a/backend/pixma_bjnp_private.h b/backend/pixma_bjnp_private.h
index a7870c68..50d215d8 100644
--- a/backend/pixma_bjnp_private.h
+++ b/backend/pixma_bjnp_private.h
@@ -370,6 +370,7 @@ typedef struct device_s
    bjnp_sockaddr_t * addr;    /* ip-address of the scanner */
    int address_level;        /* link local, public or has a FQDN */
    int bjnp_timeout;        /* timeout (msec) for next poll command */
+  int bjnp_min_timeout;    /* device specific min timeout */

  #ifdef PIXMA_BJNP_USE_STATUS
    /* polling state information */

-- 
Best Regards,
Frederick Zhang

Home Page:  https://onee3.org/
Email:      Frederick888 at Tsundere.moe




More information about the sane-devel mailing list