diff options
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; |