diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-07-15 11:29:05 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-07-15 11:29:05 +0200 | 
| commit | 324a8a71bb7d9e4f8bc49b6bc47efaf9fb58282e (patch) | |
| tree | bd2d48a139bfbe869f4f49359b63097931a45e7b /backend/pixma_bjnp.c | |
| parent | 2ca8a81bd0d99fe4d75c229d0e988d8ef710285f (diff) | |
| parent | 1edb02101a9306fc711cd422ed507d18165b1691 (diff) | |
Merge branch 'release/experimental/1.0.27-1_experimental1'experimental/1.0.27-1_experimental1
Diffstat (limited to 'backend/pixma_bjnp.c')
| -rw-r--r-- | backend/pixma_bjnp.c | 183 | 
1 files changed, 125 insertions, 58 deletions
diff --git a/backend/pixma_bjnp.c b/backend/pixma_bjnp.c index 7d2d541..fc4c501 100644 --- a/backend/pixma_bjnp.c +++ b/backend/pixma_bjnp.c @@ -85,7 +85,7 @@  #ifdef HAVE_IFADDRS_H  #include <ifaddrs.h>  #endif -#ifdef HAVE_SYS_SELSECT_H +#ifdef HAVE_SYS_SELECT_H  #include <sys/select.h>  #endif  #ifdef HAVE_PWD_H @@ -395,18 +395,19 @@ determine_scanner_serial (const char *hostname, const char * mac_address, char *    /* if we only have a literal ipv6 address, we use the mac-address */    strcpy(copy, hostname); -  while (strlen (copy) >= SHORT_HOSTNAME_MAX) +  if (strlen (copy) >= SERIAL_MAX)      { +      /* make the string fit into the serial */        /* if this is a FQDN, not an ip-address, remove domain part of the name */        if ((dot = strchr (copy, '.')) != NULL)          {            *dot = '\0';          } -      else -        { -          strcpy(copy, mac_address); -          break; -        } +    } +  /* check if name is still to long. If so use the mac-address */ +  if (strlen(copy) >= SERIAL_MAX) +    { +      strcpy(copy, mac_address);      }    strcpy( serial, copy );    return serial; @@ -566,6 +567,7 @@ split_uri (const char *devname, char *method, char *host, char *port,            return -1;          }        strcpy(port, start); +      start = end_of_port + 1;      }  /* @@ -613,7 +615,6 @@ set_cmd_for_dev (int devno, struct BJNP_command *cmd, char cmd_code, int payload    /*     * Set command buffer with command code, session_id and length of payload     * Returns: sequence number of command -   * If devno < 0, then use devno as negativ index into bjnp_protocol_defs     */    strncpy (cmd->BJNP_id, device[devno].protocol_string, sizeof (cmd->BJNP_id)); @@ -706,8 +707,8 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response,  	  FD_ZERO (&fdset);  	  FD_SET (sockfd, &fdset); -	  timeout.tv_sec = BJNP_TIMEOUT_UDP; -	  timeout.tv_usec = 0;  +	  timeout.tv_sec = device[dev_no].bjnp_timeout /1000; +	  timeout.tv_usec = device[dev_no].bjnp_timeout %1000;  	}        while (((result =  	       select (sockfd + 1, &fdset, NULL, NULL, &timeout)) <= 0) @@ -737,7 +738,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response,    close(sockfd);    PDBG (bjnp_dbg -        (LOG_CRIT, "udp_command: ERROR - no data received\n" ) ); +        (LOG_CRIT, "udp_command: ERROR - no data received (timeout = %d)\n", device[dev_no].bjnp_timeout ) );    return -1;  } @@ -807,7 +808,7 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host)  {    /*     * Parse identify command responses to ip-address -   * and hostname +   * and hostname. Return qulity of the address     */    struct addrinfo *results; @@ -1423,8 +1424,8 @@ bjnp_recv_header (int devno, size_t *payload_size )        FD_ZERO (&input);        FD_SET (fd, &input); -      timeout.tv_sec = BJNP_TIMEOUT_TCP; -      timeout.tv_usec = 0; +      timeout.tv_sec = device[devno].bjnp_timeout /1000; +      timeout.tv_usec = device[devno].bjnp_timeout %1000;      }    while ( ( (result = select (fd + 1, &input, NULL, NULL, &timeout)) <= 0) &&  	 (errno == EINTR) && (attempt++ < BJNP_MAX_SELECT_ATTEMPTS)); @@ -1442,7 +1443,8 @@ 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 after %d ms)!\n",  +		device[devno].bjnp_timeout ) );        errno = terrno;        return SANE_STATUS_IO_ERROR;      } @@ -1502,7 +1504,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 +1526,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 = 0; +  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;	 @@ -1597,8 +1600,8 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t start_pos, size_t * len)        /* wait for data to be received, retry on a signal being received */        FD_ZERO (&input);        FD_SET (fd, &input); -      timeout.tv_sec = BJNP_TIMEOUT_TCP; -      timeout.tv_usec = 0; +      timeout.tv_sec = device[devno].bjnp_timeout /1000; +      timeout.tv_usec = device[devno].bjnp_timeout %1000;      }    while (((result = select (fd + 1, &input, NULL, NULL, &timeout)) <= 0) &&  	 (errno == EINTR) && (attempt++ < BJNP_MAX_SELECT_ATTEMPTS)); @@ -1617,7 +1620,8 @@ 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 after %d ms)!\n",  +		device[devno].bjnp_timeout) );        errno = terrno;        *len = 0;        return SANE_STATUS_IO_ERROR; @@ -1643,7 +1647,7 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t start_pos, size_t * len)  static BJNP_Status  bjnp_allocate_device (SANE_String_Const devname,  -                      SANE_Int * dn, char *res_host) +                      SANE_Int * dn, char *resulting_host)  {    char method[BJNP_METHOD_MAX];     char host[BJNP_HOST_MAX]; @@ -1654,6 +1658,7 @@ bjnp_allocate_device (SANE_String_Const devname,    struct addrinfo hints;    int result;    int i; +  int min_timeout = BJNP_TIMEOUT_DEFAULT;    PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_allocate_device(%s) %d\n", devname, bjnp_no_devices)); @@ -1662,20 +1667,29 @@ bjnp_allocate_device (SANE_String_Const devname,        return BJNP_STATUS_INVAL;      } -  if (strlen (args) != 0) +  if (strlen (args) > 0)      { -      PDBG (bjnp_dbg -	    (LOG_CRIT, -	     "bjnp_allocate_device: ERROR - URI may not contain userid, password or aguments: %s\n", -	     devname)); +      /* get device specific timeout if any */ + +      if (strncmp(args, "timeout=", strlen("timeout=")) == 0) +        { +          min_timeout = atoi(args + strlen("timeout=")); +          if (min_timeout < BJNP_TIMEOUT_DEFAULT) +            min_timeout = BJNP_TIMEOUT_DEFAULT; +        } else { +		PDBG (bjnp_dbg +	    		(LOG_CRIT, +				"bjnp_allocate_device: ERROR - Unrecognized argument: %s\n", +	     			devname));        return BJNP_STATUS_INVAL; +        }      }    if ( (protocol_defs = get_protocol_by_method(method)) == NULL)      {        PDBG (bjnp_dbg -	    (LOG_CRIT, "bjnp_allocate_device: ERROR - URI %s contains invalid method: %s\n", devname, -	     method)); +		(LOG_CRIT, "bjnp_allocate_device: ERROR - URI %s contains invalid method: %s\n", +		 devname, method));        return BJNP_STATUS_INVAL;      } @@ -1715,24 +1729,26 @@ bjnp_allocate_device (SANE_String_Const devname,          {            PDBG (bjnp_dbg      	    (LOG_CRIT, -    	     "bjnp_allocate_device: WARNING - Too many devices, ran out of device structures, can not add %s\n", +    	     "bjnp_allocate_device: WARNING - Too many devices, ran out of device structures, cannot add %s\n",      	     devname));            freeaddrinfo(res);            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;          }        for (i = 0; i < bjnp_no_devices; i++)          { -          /* we check for matching addresses as wel as matching mac_addresses as */ -          /* an IPv6 host can have multiple adresses */ -          if ( (sa_is_equal( device[i].addr, (bjnp_sockaddr_t *)cur -> ai_addr) ) || -               ( strcmp( device[i].mac_address, device[bjnp_no_devices].mac_address ) == 0 ) ) +          /* Check if found the scanner before, if so we use the best address  +	   * but still make sure the scanner is listed only once. +	   * We check for matching addresses as wel as matching mac_addresses as  +           * an IPv6 host can have multiple adresses */ + +          if ( strcmp( device[i].mac_address, device[bjnp_no_devices].mac_address ) == 0 )              {                if ( device[i].address_level < device[bjnp_no_devices].address_level )                   { @@ -1742,6 +1758,16 @@ bjnp_allocate_device (SANE_String_Const devname,                    device[bjnp_no_devices].addr = NULL;                    device[i].address_level = device[bjnp_no_devices].address_level;                  } + +	      /* check if new timeout value was defined (e.g. from sanei_bjnp_device_open) +	       * if so, use new timout value */ + +              if (device[i].bjnp_min_timeout < device[bjnp_no_devices].bjnp_min_timeout) +                { +                  /* use the longer timeout as requested */ +                  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); @@ -1754,17 +1780,17 @@ bjnp_allocate_device (SANE_String_Const devname,    PDBG (bjnp_dbg (LOG_INFO, "bjnp_allocate_device: Scanner not yet in our list, added it: %s:%s\n", host, port)); -  /* return hostname if required */ +  /* Commit new device structure */ -  if (res_host != NULL) -    { -      strcpy (res_host, host); -    }    *dn = bjnp_no_devices; +  bjnp_no_devices++; -  /* Commit new device structure */ +  /* return hostname if required */ -  bjnp_no_devices++; +  if (resulting_host != NULL) +    { +      strcpy (resulting_host, host); +    }    return BJNP_STATUS_GOOD;  } @@ -1800,10 +1826,11 @@ static void add_scanner(SANE_Int *dev_no,             */             determine_scanner_serial (scanner_host, device[*dev_no].mac_address, serial); +             attach_bjnp (uri, makemodel,                          serial, pixma_devices); -           PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: New scanner at %s added!\n", -	                 uri)); +           PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: New scanner added: %s, serial %s, mac addres: %s.\n", +	                 uri, serial, device[*dev_no].mac_address));            }          break;        case BJNP_STATUS_ALREADY_ALLOCATED: @@ -1818,6 +1845,34 @@ static void add_scanner(SANE_Int *dev_no,      }  } +int rewrite_uri(char *uri, int timeout, int max_len) +{ +  char method[BJNP_METHOD_MAX]; +  char host[BJNP_HOST_MAX]; +  char port_str[BJNP_PORT_MAX]; +  char args[BJNP_HOST_MAX]; +  int port; + +  if (split_uri(uri, method, host, port_str, args ) != 0) +    { +      return -1; +    } + +  port = atoi(port_str); +  if (port == 0) +    { +      port = 8612; +    } + +  if (strstr(args, "timeout=") == NULL) +    { +      sprintf(args, "timeout=%d", timeout); +    } + +  snprintf(uri, max_len -1, "bjnp://%s:%d/%s", host, port, args); +  return 0; +} +  /*   * Public functions @@ -1870,6 +1925,7 @@ sanei_bjnp_find_devices (const char **conf_devices,    char uri[256];    int dev_no;    int port; +  int timeout_default = BJNP_TIMEOUT_DEFAULT;    bjnp_sockaddr_t broadcast_addr[BJNP_SOCK_MAX];    bjnp_sockaddr_t scanner_sa;     socklen_t socklen; @@ -1885,16 +1941,30 @@ sanei_bjnp_find_devices (const char **conf_devices,      {        socket_fd[i] = -1;      } -  /* First add devices from config file */ + +  /* Add devices from config file */    if (conf_devices[0] == NULL)      PDBG (bjnp_dbg( LOG_DEBUG, "sanei_bjnp_find_devices: No devices specified in configuration file.\n" ) );    for (i = 0; conf_devices[i] != NULL; i++)      { +      if (strncmp(conf_devices[i], "bjnp-timeout=", strlen("bjnp-timeout="))== 0) +        { +	  timeout_default = atoi(conf_devices[i] + strlen("bjnp-timeout=") ); +          if (timeout_default < BJNP_TIMEOUT_DEFAULT) +	    { +	      timeout_default = BJNP_TIMEOUT_DEFAULT;	     +	    } +	  PDBG ( bjnp_dbg +                  (LOG_DEBUG, "Set new default timeout value: %d ms.", timeout_default)); +	  continue; +	}        PDBG (bjnp_dbg  	    (LOG_DEBUG, "sanei_bjnp_find_devices: Adding scanner from pixma.conf: %s\n", conf_devices[i])); -      add_scanner(&dev_no, conf_devices[i], attach_bjnp, pixma_devices); +      strncpy(uri, conf_devices[i], sizeof(uri)); +      rewrite_uri(uri, timeout_default, sizeof(uri)); +      add_scanner(&dev_no, uri, attach_bjnp, pixma_devices);      }    PDBG (bjnp_dbg  	(LOG_DEBUG, @@ -2062,8 +2132,8 @@ sanei_bjnp_find_devices (const char **conf_devices,                get_scanner_name( &scanner_sa, scanner_host);  	      /* construct URI */ -	      sprintf (uri, "%s://%s:%d", protocol_defs->method_string, scanner_host, -		       port); +	      sprintf (uri, "%s://%s:%d/timeout=%d", protocol_defs->method_string, scanner_host, +		           port, timeout_default);                add_scanner( &dev_no, uri, attach_bjnp, pixma_devices);  @@ -2182,8 +2252,15 @@ sanei_bjnp_deactivate (SANE_Int dn)  extern void  sanei_bjnp_set_timeout (SANE_Int devno, SANE_Int timeout)  { -  PDBG (bjnp_dbg (LOG_INFO, "bjnp_set_timeout to %d\n", +  if (timeout < device[devno].bjnp_min_timeout) +    { +      PDBG (bjnp_dbg (LOG_INFO, "bjnp_set_timeout to %d, but using minimum value %d\n", +        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)); +    }    device[devno].bjnp_timeout = timeout;  } @@ -2460,16 +2537,6 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size)            if ( resp_len > 0 )              {                device[dn].polling_status = BJNP_POLL_STATUS_RECEIVED; - -              /* this is a bit of a hack, but the scanner does not like */ -              /* us to continue using the existing tcp socket */ - -              /* No longer required? Does not work anymore now we moved code from sanei_bjnp_activate/sanei_bjnp_deactivate -                 to the isanei_bjnp_open and sanei_bjnp_close -              sanei_bjnp_deactivate(dn); -              sanei_bjnp_activate(dn); -              */  -                return SANE_STATUS_GOOD;              }            seconds = timeout > 2 ? 2 : timeout;  | 
