diff options
Diffstat (limited to 'backend/pixma_bjnp.c')
-rw-r--r-- | backend/pixma_bjnp.c | 529 |
1 files changed, 332 insertions, 197 deletions
diff --git a/backend/pixma_bjnp.c b/backend/pixma_bjnp.c index 3046e9d..7d2d541 100644 --- a/backend/pixma_bjnp.c +++ b/backend/pixma_bjnp.c @@ -65,6 +65,9 @@ #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif /* * networking stuff @@ -99,6 +102,9 @@ #include "pixma.h" #include "pixma_common.h" +#ifndef SSIZE_MAX +# define SSIZE_MAX LONG_MAX +#endif /* static data */ static bjnp_device_t device[BJNP_NO_DEVICES]; @@ -130,11 +136,11 @@ static void u32tohex (uint32_t x, char *str) { uint8_t uint8[4]; - uint8[0]= (uint8_t) x >> 24; - uint8[1] = (uint8_t)x >> 16; - uint8[2] = (uint8_t)x >> 8; - uint8[3] = (uint8_t)x ; - u8tohex(str, uint8, 4); + uint8[0] = (uint8_t)(x >> 24); + uint8[1] = (uint8_t)(x >> 16); + uint8[2] = (uint8_t)(x >> 8); + uint8[3] = (uint8_t)x ; + u8tohex(str, uint8, 4); } static void @@ -284,7 +290,8 @@ parse_IEEE1284_to_model (char *scanner_id, char *model) char s[BJNP_IEEE1284_MAX]; char *tok; - strcpy (s, scanner_id); + strncpy (s, scanner_id, BJNP_IEEE1284_MAX); + s[BJNP_IEEE1284_MAX - 1] = '\0'; model[0] = '\0'; tok = strtok (s, ";"); @@ -294,7 +301,8 @@ parse_IEEE1284_to_model (char *scanner_id, char *model) if (strncmp (tok, "MDL:", 4) == 0) { - strcpy (model, tok + 4); + strncpy (model, tok + 4, BJNP_IEEE1284_MAX); + model[BJNP_IEEE1284_MAX -1] = '\0'; return 1; } tok = strtok (NULL, ";"); @@ -334,6 +342,34 @@ charTo2byte (char *d, const char *s, int len) return copied; } +static bjnp_protocol_defs_t *get_protocol_by_method( char *method) +{ + int i = 0; + while ( bjnp_protocol_defs[i].method_string != NULL) + { + if (strcmp(method, bjnp_protocol_defs[i].method_string) == 0) + { + return &bjnp_protocol_defs[i]; + } + i++; + } + return NULL; +} + +static bjnp_protocol_defs_t *get_protocol_by_proto_string( char *proto_string) +{ + int i = 0; + while ( bjnp_protocol_defs[i].proto_string != NULL) + { + if (strncmp(proto_string, bjnp_protocol_defs[i].proto_string, 4) == 0) + { + return &bjnp_protocol_defs[i]; + } + i++; + } + return NULL; +} + static char * getusername (void) { @@ -364,11 +400,13 @@ determine_scanner_serial (const char *hostname, const char * mac_address, char * /* if this is a FQDN, not an ip-address, remove domain part of the name */ if ((dot = strchr (copy, '.')) != NULL) { - *dot = '\0'; + *dot = '\0'; } else - strcpy(copy, mac_address); - break; + { + strcpy(copy, mac_address); + break; + } } strcpy( serial, copy ); return serial; @@ -389,7 +427,7 @@ bjnp_open_tcp (int devno) if ((sock = socket (get_protocol_family( addr ) , SOCK_STREAM, 0)) < 0) { - PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: Can not create socket: %s\n", + PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not create socket: %s\n", strerror (errno))); return -1; } @@ -422,7 +460,7 @@ bjnp_open_tcp (int devno) (sock, &(addr->addr), sa_size(device[devno].addr) )!= 0) { PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_open_tcp: Can not connect to scanner: %s\n", + (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not connect to scanner: %s\n", strerror (errno))); return -1; } @@ -439,7 +477,8 @@ split_uri (const char *devname, char *method, char *host, char *port, char next; int i; - strcpy (copy, devname); + strncpy (copy, devname, 1024); + copy[1023] = '\0'; start = copy; /* @@ -453,7 +492,7 @@ split_uri (const char *devname, char *method, char *host, char *port, if (((strncmp (start + i, "://", 3) != 0)) || (i > BJNP_METHOD_MAX -1 )) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find method in %s (offset %d)\n", + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find method in %s (offset %d)\n", devname, i)); return -1; } @@ -476,7 +515,7 @@ split_uri (const char *devname, char *method, char *host, char *port, ( (end_of_address[1] != ':') && (end_of_address[1] != '/' ) && (end_of_address[1] != '\0' )) || ( (end_of_address - start) >= BJNP_HOST_MAX ) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find hostname or address in %s\n", devname)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find hostname or address in %s\n", devname)); return -1; } next = end_of_address[1]; @@ -495,7 +534,7 @@ split_uri (const char *devname, char *method, char *host, char *port, start[i] = '\0'; if ((i == 0) || (i >= BJNP_HOST_MAX ) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find hostname or address in %s\n", devname)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find hostname or address in %s\n", devname)); return -1; } strcpy (host, start); @@ -523,7 +562,7 @@ split_uri (const char *devname, char *method, char *host, char *port, } if ((strlen(start) == 0) || (strlen(start) >= BJNP_PORT_MAX ) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Can not find port in %s (have \"%s\")\n", devname, start)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find port in %s (have \"%s\")\n", devname, start)); return -1; } strcpy(port, start); @@ -538,7 +577,7 @@ split_uri (const char *devname, char *method, char *host, char *port, i = strlen(start); if ( i >= BJNP_ARGS_MAX) { - PDBG (bjnp_dbg (LOG_NOTICE, "Argument string too long in %s\n", devname)); + PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Argument string too long in %s\n", devname)); } strcpy (args, start); } @@ -550,28 +589,40 @@ split_uri (const char *devname, char *method, char *host, char *port, static void -set_cmd (int devno, struct BJNP_command *cmd, char cmd_code, int payload_len) +set_cmd_from_string (char* protocol_string, struct BJNP_command *cmd, char cmd_code, int payload_len) { /* - * Set command buffer with command code, session_id and lenght of payload + * Set command buffer with command code, session_id and length of payload * Returns: sequence number of command */ - strncpy (cmd->BJNP_id, BJNP_STRING, sizeof (cmd->BJNP_id)); + + strncpy (cmd->BJNP_id, protocol_string, sizeof (cmd->BJNP_id)); cmd->dev_type = BJNP_CMD_SCAN; cmd->cmd_code = cmd_code; cmd->unknown1 = htons (0); - if (devno == -1) - { - /* device not yet opened, use 0 for serial and session) */ - cmd->seq_no = htons (0); - cmd->session_id = htons (0); - } - else - { - cmd->seq_no = htons (++(device[devno].serial)); - cmd->session_id = (cmd_code == CMD_UDP_POLL ) ? 0 : htons (device[devno].session_id); - device[devno].last_cmd = cmd_code; - } + + /* device not yet opened, use 0 for serial and session) */ + cmd->seq_no = htons (0); + cmd->session_id = htons (0); + cmd->payload_len = htonl (payload_len); +} + +static void +set_cmd_for_dev (int devno, struct BJNP_command *cmd, char cmd_code, int payload_len) +{ + /* + * 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)); + cmd->dev_type = BJNP_CMD_SCAN; + cmd->cmd_code = cmd_code; + cmd->unknown1 = htons (0); + cmd->seq_no = htons (++(device[devno].serial)); + cmd->session_id = (cmd_code == CMD_UDP_POLL ) ? 0 : htons (device[devno].session_id); + device[devno].last_cmd = cmd_code; cmd->payload_len = htonl (payload_len); } @@ -596,7 +647,7 @@ bjnp_setup_udp_socket ( const int dev_no ) if ((sockfd = socket (get_protocol_family( addr ), SOCK_DGRAM, IPPROTO_UDP)) == -1) { PDBG (bjnp_dbg - (LOG_CRIT, "setup_udp_socket: can not open socket - %s\n", + (LOG_CRIT, "setup_udp_socket: ERROR - can not open socket - %s\n", strerror (errno))); return -1; } @@ -605,7 +656,7 @@ bjnp_setup_udp_socket ( const int dev_no ) (sockfd, &(device[dev_no].addr->addr), sa_size(device[dev_no].addr) )!= 0) { PDBG (bjnp_dbg - (LOG_CRIT, "setup_udp_socket: connect failed- %s\n", + (LOG_CRIT, "setup_udp_socket: ERROR - connect failed- %s\n", strerror (errno))); close(sockfd); return -1; @@ -632,7 +683,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if ( (sockfd = bjnp_setup_udp_socket(dev_no) ) == -1 ) { - PDBG (bjnp_dbg( LOG_CRIT, "udp_command: Can not setup socket\n") ); + PDBG (bjnp_dbg( LOG_CRIT, "udp_command: ERROR - Can not setup socket\n") ); return -1; } @@ -641,7 +692,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if ((numbytes = send (sockfd, command, cmd_len, 0)) != cmd_len) { PDBG (bjnp_dbg - (LOG_NOTICE, "udp_command: Sent %d bytes, expected %d\n", + (LOG_NOTICE, "udp_command: ERROR - Sent %d bytes, expected %d\n", numbytes, cmd_len)); continue; } @@ -666,7 +717,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if (result <= 0) { PDBG (bjnp_dbg - (LOG_NOTICE, "udp_command: select failed: %s\n", + (LOG_NOTICE, "udp_command: ERROR - select failed: %s\n", result == 0 ? "timed out" : strerror (errno))); continue; } @@ -674,7 +725,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, if ((numbytes = recv (sockfd, response, resp_len, 0)) == -1) { PDBG (bjnp_dbg - (LOG_NOTICE, "udp_command: recv failed: %s", + (LOG_NOTICE, "udp_command: ERROR - recv failed: %s", strerror (errno))); continue; } @@ -686,7 +737,7 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response, close(sockfd); PDBG (bjnp_dbg - (LOG_CRIT, "udp_command: no data received\n" ) ); + (LOG_CRIT, "udp_command: ERROR - no data received\n" ) ); return -1; } @@ -710,36 +761,43 @@ get_scanner_id (const int dev_no, char *model) strcpy (model, "Unidentified scanner"); - set_cmd (dev_no, &cmd, CMD_UDP_GET_ID, 0); + set_cmd_for_dev (dev_no, &cmd, CMD_UDP_GET_ID, 0); - PDBG (bjnp_dbg (LOG_DEBUG2, "Get scanner identity\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "get_scanner_id: Get scanner identity\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &cmd, sizeof (struct BJNP_command))); if ( ( resp_len = udp_command (dev_no, (char *) &cmd, sizeof (struct BJNP_command), resp_buf, BJNP_RESP_MAX) ) < (int)sizeof(struct BJNP_command) ) { - PDBG (bjnp_dbg (LOG_DEBUG, "Failed to retrieve scanner identity:\n")); + PDBG (bjnp_dbg (LOG_DEBUG, "get_scanner_id: ERROR - Failed to retrieve scanner identity:\n")); return -1; } - PDBG (bjnp_dbg (LOG_DEBUG2, "scanner identity:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "get_scanner_id: scanner identity:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); id = (struct IDENTITY *) resp_buf; - /* truncate string to be safe */ - id_len = htons( id-> id_len ) - sizeof(id->id_len); - id->id[id_len] = '\0'; - strcpy (scanner_id, id->id); - - PDBG (bjnp_dbg (LOG_INFO, "Scanner identity string = %s - lenght = %d\n", scanner_id, id_len)); + if (device[dev_no].protocol == PROTOCOL_BJNP) + { + id_len = MIN(ntohl( id-> cmd.payload_len ) - sizeof(id-> payload.bjnp.id_len), BJNP_IEEE1284_MAX); + strncpy(scanner_id, id->payload.bjnp.id, id_len); + scanner_id[id_len] = '\0'; + } + else + { + id_len = MIN(ntohl( id-> cmd.payload_len ), BJNP_IEEE1284_MAX); + strncpy(scanner_id, id->payload.mfnp.id, id_len); + scanner_id[id_len] = '\0'; + } + PDBG (bjnp_dbg (LOG_INFO, "get_scanner_id: Scanner identity string = %s - length = %d\n", scanner_id, id_len)); /* get make&model from IEEE1284 id */ if (model != NULL) { parse_IEEE1284_to_model (scanner_id, model); - PDBG (bjnp_dbg (LOG_INFO, "Scanner model = %s\n", model)); + PDBG (bjnp_dbg (LOG_INFO, "get_scanner_id: Scanner model = %s\n", model)); } return 0; } @@ -776,7 +834,7 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) if( (error = getnameinfo( &(scanner_sa -> addr) , sa_size( scanner_sa), host, BJNP_HOST_MAX , NULL, 0, NI_NAMEREQD) ) != 0 ) { - PDBG (bjnp_dbg(LOG_INFO, "Name for %s not found : %s\n", + PDBG (bjnp_dbg(LOG_INFO, "get_scanner_name: Name for %s not found : %s\n", ip_address, gai_strerror(error) ) ); strcpy(host, ip_address); return level; @@ -797,7 +855,7 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) { /* found match, good */ PDBG (bjnp_dbg (LOG_INFO, - "Forward lookup for %s succeeded, using as hostname\n", host)); + "get_scanner_name: Forward lookup for %s succeeded, using as hostname\n", host)); match = 1; level = BJNP_ADDRESS_HAS_FQDN; break; @@ -809,7 +867,7 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) if (match != 1) { PDBG (bjnp_dbg (LOG_INFO, - "Forward lookup for %s succeeded, IP-address does not match, using IP-address %s instead\n", + "get_scanner_name: Forward lookup for %s succeeded, IP-address does not match, using IP-address %s instead\n", host, ip_address)); strcpy (host, ip_address); } @@ -817,13 +875,30 @@ get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) else { /* forward lookup failed, use ip-address */ - PDBG ( bjnp_dbg (LOG_INFO, "Forward lookup of %s failed, using IP-address", ip_address)); + PDBG ( bjnp_dbg (LOG_INFO, "get_scanner_name: Forward lookup of %s failed, using IP-address", ip_address)); strcpy (host, ip_address); } } return level; } +static int +get_port_from_sa(const bjnp_sockaddr_t scanner_sa) +{ +#ifdef ENABLE_IPV6 + if ( scanner_sa.addr.sa_family == AF_INET6 ) + { + return ntohs(scanner_sa.ipv6.sin6_port); + } + else +#endif + if ( scanner_sa.addr.sa_family == AF_INET ) + { + return ntohs(scanner_sa.ipv4.sin_port); + } + return -1; +} + static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { int sockfd = -1; @@ -834,7 +909,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) if ((sockfd = socket (local_addr-> addr.sa_family, SOCK_DGRAM, 0)) == -1) { PDBG (bjnp_dbg - (LOG_CRIT, "create_broadcast_socket: can not open socket - %s", + (LOG_CRIT, "create_broadcast_socket: ERROR - can not open socket - %s", strerror (errno))); return -1; } @@ -847,7 +922,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { PDBG (bjnp_dbg (LOG_CRIT, - "create_broadcast_socket: setting socket option SO_BROADCAST failed - %s", + "create_broadcast_socket: ERROR - setting socket option SO_BROADCAST failed - %s", strerror (errno))); close (sockfd); return -1; @@ -860,7 +935,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { PDBG (bjnp_dbg (LOG_CRIT, - "create_broadcast_socket: setting socket option IPV6_V6ONLY failed - %s", + "create_broadcast_socket: ERROR - setting socket option IPV6_V6ONLY failed - %s", strerror (errno))); close (sockfd); return -1; @@ -872,7 +947,7 @@ static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { PDBG (bjnp_dbg (LOG_CRIT, - "create_broadcast_socket: bind socket to local address failed - %s\n", + "create_broadcast_socket: ERROR - bind socket to local address failed - %s\n", strerror (errno))); close (sockfd); return -1; @@ -900,7 +975,7 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, if ( local_sa == NULL ) { PDBG (bjnp_dbg (LOG_DEBUG, - "%s is not a valid IPv4 interface, skipping...\n", + "prepare_socket: %s is not a valid IPv4 interface, skipping...\n", if_name)); return -1; } @@ -919,7 +994,7 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, /* not a valid interface */ PDBG (bjnp_dbg (LOG_DEBUG, - "%s is not a valid IPv4 interface, skipping...\n", + "prepare_socket: %s is not a valid IPv4 interface, skipping...\n", if_name)); return -1; } @@ -928,15 +1003,18 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, /* send broadcasts to the broadcast address of the interface */ memcpy(dest_sa, broadcast_sa, sa_size(dest_sa) ); - dest_sa -> ipv4.sin_port = htons(BJNP_PORT_SCAN); + + /* we fill port when we send the broadcast */ + dest_sa -> ipv4.sin_port = htons(0); + if ( (socket = create_broadcast_socket( &local_sa_copy) ) != -1) { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv4 capable, sending broadcast, socket = %d\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: %s is IPv4 capable, sending broadcast, socket = %d\n", if_name, socket)); } else { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv4 capable, but failed to create a socket.\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: ERROR - %s is IPv4 capable, but failed to create a socket.\n", if_name)); return -1; } @@ -952,23 +1030,26 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, /* not a valid interface */ PDBG (bjnp_dbg (LOG_DEBUG, - "%s is not a valid IPv6 interface, skipping...\n", + "prepare_socket: %s is not a valid IPv6 interface, skipping...\n", if_name)); return -1; } else { dest_sa -> ipv6.sin6_family = AF_INET6; - dest_sa -> ipv6.sin6_port = htons(BJNP_PORT_SCAN); + + /* We fill port when we send the broadcast */ + dest_sa -> ipv6.sin6_port = htons(0); + inet_pton(AF_INET6, "ff02::1", dest_sa -> ipv6.sin6_addr.s6_addr); if ( (socket = create_broadcast_socket( &local_sa_copy ) ) != -1) { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv6 capable, sending broadcast, socket = %d\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: %s is IPv6 capable, sending broadcast, socket = %d\n", if_name, socket)); } else { - PDBG (bjnp_dbg (LOG_INFO, "%s is IPv6 capable, but failed to create a socket.\n", + PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: ERROR - %s is IPv6 capable, but failed to create a socket.\n", if_name)); return -1; } @@ -984,20 +1065,33 @@ prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, } static int -bjnp_send_broadcast (int sockfd, const bjnp_sockaddr_t * broadcast_addr, +bjnp_send_broadcast (int sockfd, const bjnp_sockaddr_t * broadcast_addr, int port, struct BJNP_command cmd, int size) { int num_bytes; + bjnp_sockaddr_t dest_addr; - /* set address to send packet to */ - /* usebroadcast address of interface */ + /* set address to send packet to broadcast address of interface, */ + /* with port set to the destination port */ + + memcpy(&dest_addr, broadcast_addr, sizeof(dest_addr)); + if( dest_addr.addr.sa_family == AF_INET) + { + dest_addr.ipv4.sin_port = htons(port); + } +#ifdef ENABLE_IPV6 + if( dest_addr.addr.sa_family == AF_INET6) + { + dest_addr.ipv6.sin6_port = htons(port); + } +#endif if ((num_bytes = sendto (sockfd, &cmd, size, 0, - &(broadcast_addr->addr), + &(dest_addr.addr), sa_size( broadcast_addr)) ) != size) { PDBG (bjnp_dbg (LOG_INFO, - "bjnp_send_broadcast: Socket: %d: sent only %x = %d bytes of packet, error = %s\n", + "bjnp_send_broadcast: Socket: %d: ERROR - sent only %x = %d bytes of packet, error = %s\n", sockfd, num_bytes, num_bytes, strerror (errno))); /* not allowed, skip this interface */ @@ -1017,9 +1111,9 @@ bjnp_finish_job (int devno) int resp_len; struct BJNP_command cmd; - set_cmd (devno, &cmd, CMD_UDP_CLOSE, 0); + set_cmd_for_dev (devno, &cmd, CMD_UDP_CLOSE, 0); - PDBG (bjnp_dbg (LOG_DEBUG2, "Finish scanjob\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_finish_job: Finish scanjob\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &cmd, sizeof (struct BJNP_command))); resp_len = @@ -1030,11 +1124,11 @@ bjnp_finish_job (int devno) { PDBG (bjnp_dbg (LOG_INFO, - "Received %d characters on close scanjob command, expected %d\n", + "bjnp_finish_job: ERROR - Received %d characters on close scanjob command, expected %d\n", resp_len, (int) sizeof (struct BJNP_command))); return; } - PDBG (bjnp_dbg (LOG_DEBUG2, "Finish scanjob response\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_finish_job: Finish scanjob response\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); } @@ -1101,11 +1195,11 @@ bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *s return -1; }; /* we can only now set the header as we now know the length of the payload */ - set_cmd (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_POLL, + set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_POLL, len); buf_len = len + sizeof(struct BJNP_command); - PDBG (bjnp_dbg (LOG_DEBUG2, "Poll details (type %d)\n", type)); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_poll_scanner: Poll details (type %d)\n", type)); PDBG (bjnp_hexdump (LOG_DEBUG2, cmd_buf, buf_len)); @@ -1113,7 +1207,7 @@ bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *s if (resp_len > 0) { - PDBG (bjnp_dbg (LOG_DEBUG2, "Poll details response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_poll_scanner: Poll details response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); response = (struct POLL_RESPONSE *) resp_buf; @@ -1126,7 +1220,7 @@ bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *s if ( (response -> result[2] & 0x80) != 0) { memcpy( status, response->status, size); - PDBG( bjnp_dbg(LOG_INFO, "received button status!\n")); + PDBG( bjnp_dbg(LOG_INFO, "bjnp_poll_scanner: received button status!\n")); PDBG (bjnp_hexdump( LOG_DEBUG2, status, size )); device[devno].status_key = ntohl( response -> key ); return size; @@ -1151,7 +1245,7 @@ bjnp_send_job_details (int devno, char *hostname, char *user, char *title) /* send job details command */ - set_cmd (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_JOB_DETAILS, + set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_JOB_DETAILS, sizeof (*job) - sizeof (struct BJNP_command)); /* create payload */ @@ -1162,7 +1256,7 @@ bjnp_send_job_details (int devno, char *hostname, char *user, char *title) charTo2byte (job->username, user, sizeof (job->username)); charTo2byte (job->jobtitle, title, sizeof (job->jobtitle)); - PDBG (bjnp_dbg (LOG_DEBUG2, "Job details\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_send_job_details: Job details\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, cmd_buf, (sizeof (struct BJNP_command) + sizeof (*job)))); @@ -1172,7 +1266,7 @@ bjnp_send_job_details (int devno, char *hostname, char *user, char *title) if (resp_len > 0) { - PDBG (bjnp_dbg (LOG_DEBUG2, "Job details response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_send_job_details: Job details response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); resp = (struct BJNP_command *) resp_buf; device[devno].session_id = ntohs (resp->session_id); @@ -1193,14 +1287,14 @@ bjnp_get_scanner_mac_address ( int devno, char *mac_address ) /* send job details command */ - set_cmd (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_DISCOVER, 0); + set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_DISCOVER, 0); resp_len = udp_command (devno, cmd_buf, sizeof (struct BJNP_command), resp_buf, BJNP_RESP_MAX); if (resp_len > 0) { - PDBG (bjnp_dbg (LOG_DEBUG2, "Discover response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_get_scanner_mac_address: Discover response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); u8tohex( mac_address, resp -> mac_addr, sizeof( resp -> mac_addr ) ); return 0; @@ -1212,7 +1306,7 @@ static int bjnp_write (int devno, const SANE_Byte * buf, size_t count) { /* - * This function writes scandata to the scanner. + * This function writes TCP data to the scanner. * Returns: number of bytes written to the scanner */ int sent_bytes; @@ -1220,14 +1314,15 @@ bjnp_write (int devno, const SANE_Byte * buf, size_t count) struct SCAN_BUF bjnp_buf; if (device[devno].scanner_data_left) - PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_write: ERROR: scanner data left = 0x%lx = %ld\n", - (unsigned long) device[devno].scanner_data_left, - (unsigned long) device[devno].scanner_data_left)); - + { + PDBG (bjnp_dbg + (LOG_CRIT, "bjnp_write: ERROR - scanner data left = 0x%lx = %ld\n", + (unsigned long) device[devno].scanner_data_left, + (unsigned long) device[devno].scanner_data_left)); + } /* set BJNP command header */ - set_cmd (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_SEND, count); + set_cmd_for_dev (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_SEND, count); memcpy (bjnp_buf.scan_data, buf, count); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_write: sending 0x%lx = %ld bytes\n", (unsigned long) count, (unsigned long) count); @@ -1241,7 +1336,7 @@ bjnp_write (int devno, const SANE_Byte * buf, size_t count) { /* return result from write */ terrno = errno; - PDBG (bjnp_dbg (LOG_CRIT, "bjnp_write: Could not send data!\n")); + PDBG (bjnp_dbg (LOG_CRIT, "bjnp_write: ERROR - Could not send data!\n")); errno = terrno; return sent_bytes; } @@ -1270,13 +1365,13 @@ bjnp_send_read_request (int devno) if (device[devno].scanner_data_left) PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_send_read_request: ERROR scanner data left = 0x%lx = %ld\n", + "bjnp_send_read_request: ERROR - scanner data left = 0x%lx = %ld\n", (unsigned long) device[devno].scanner_data_left, (unsigned long) device[devno].scanner_data_left)); /* set BJNP command header */ - set_cmd (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_REQ, 0); + set_cmd_for_dev (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_REQ, 0); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_send_read_req sending command\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &bjnp_buf, @@ -1289,7 +1384,7 @@ bjnp_send_read_request (int devno) /* return result from write */ terrno = errno; PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_send_read_request: Could not send data!\n")); + (LOG_CRIT, "bjnp_send_read_request: ERROR - Could not send data!\n")); errno = terrno; return -1; } @@ -1338,7 +1433,7 @@ bjnp_recv_header (int devno, size_t *payload_size ) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header: could not read response header (select): %s!\n", + "bjnp_recv_header: ERROR - could not read response header (select): %s!\n", strerror (terrno))); errno = terrno; return SANE_STATUS_IO_ERROR; @@ -1347,7 +1442,7 @@ bjnp_recv_header (int devno, size_t *payload_size ) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header: could not read response header (select timed out)!\n" ) ); + "bjnp_recv_header: ERROR - could not read response header (select timed out)!\n" ) ); errno = terrno; return SANE_STATUS_IO_ERROR; } @@ -1360,12 +1455,18 @@ bjnp_recv_header (int devno, size_t *payload_size ) 0)) != sizeof (struct BJNP_command)) { terrno = errno; - PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header: (recv) could not read response header, received %d bytes!\n", + if (recv_bytes == 0) + { + PDBG (bjnp_dbg (LOG_CRIT, + "bjnp_recv_header: ERROR - (recv) Scanner closed the TCP-connection!\n")); + } else { + PDBG (bjnp_dbg (LOG_CRIT, + "bjnp_recv_header: ERROR - (recv) could not read response header, received %d bytes!\n", recv_bytes)); - PDBG (bjnp_dbg - (LOG_CRIT, "bjnp_recv_header: (recv) error: %s!\n", - strerror (terrno))); + PDBG (bjnp_dbg + (LOG_CRIT, "bjnp_recv_header: ERROR - (recv) error: %s!\n", + strerror (terrno))); + } errno = terrno; return SANE_STATUS_IO_ERROR; } @@ -1374,7 +1475,7 @@ bjnp_recv_header (int devno, size_t *payload_size ) { PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header:ERROR, Received response has cmd code %d, expected %d\n", + "bjnp_recv_header: ERROR - Received response has cmd code %d, expected %d\n", resp_buf.cmd_code, device[devno].last_cmd)); return SANE_STATUS_IO_ERROR; } @@ -1383,17 +1484,17 @@ bjnp_recv_header (int devno, size_t *payload_size ) { PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_header:ERROR, Received response has serial %d, expected %d\n", + "bjnp_recv_header: ERROR - Received response has serial %d, expected %d\n", (int) ntohs (resp_buf.seq_no), (int) device[devno].serial)); return SANE_STATUS_IO_ERROR; } - /* got response header back, retrieve length of scanner data */ + /* got response header back, retrieve length of payload */ *payload_size = ntohl (resp_buf.payload_len); PDBG (bjnp_dbg - (LOG_DEBUG, "TCP response header(scanner data = %ld bytes):\n", + (LOG_DEBUG, "bjnp_recv_header: TCP response header(payload data = %ld bytes):\n", *payload_size) ); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &resp_buf, sizeof (struct BJNP_command))); @@ -1401,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_init_device_structure(int dn, bjnp_sockaddr_t *sa, bjnp_protocol_defs_t *protocol_defs) { /* initialize device structure */ @@ -1413,6 +1514,8 @@ bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa ) device[dn].dialog = 0; device[dn].status_key = 0; #endif + device[dn].protocol = protocol_defs->protocol_version; + device[dn].protocol_string = protocol_defs->proto_string; device[dn].tcp_socket = -1; device[dn].addr = (bjnp_sockaddr_t *) malloc(sizeof ( bjnp_sockaddr_t) ); @@ -1424,14 +1527,14 @@ bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa ) device[dn].bjnp_timeout = 0; device[dn].scanner_data_left = 0; device[dn].last_cmd = 0; - device[dn].blocksize = 2048; /* safe assumption, we start low */ + device[dn].blocksize = BJNP_BLOCKSIZE_START; device[dn].last_block = 0; /* fill mac_address */ if (bjnp_get_scanner_mac_address(dn, device[dn].mac_address) != 0 ) { PDBG (bjnp_dbg - (LOG_CRIT, "Cannot read mac address, skipping this scanner\n" ) ); + (LOG_CRIT, "bjnp_init_device_structure: Cannot read mac address, skipping this scanner\n" ) ); return -1; } return 0; @@ -1449,11 +1552,12 @@ bjnp_free_device_structure( int dn) } static SANE_Status -bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) +bjnp_recv_data (int devno, SANE_Byte * buffer, size_t start_pos, size_t * len) { /* - * This function receives the responses to the write commands. + * This function receives the payload data. * NOTE: len may not exceed SSIZE_MAX (as that is max for recv) + * len will be restricted to SSIZE_MAX to be sure * Returns: number of bytes of payload received from device */ @@ -1465,13 +1569,28 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) int fd; int attempt; - PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_recv_data: receiving response data\n")); - fd = device[devno].tcp_socket; - PDBG (bjnp_dbg - (LOG_DEBUG, "bjnp_recv_data: read response payload (%ld bytes max)\n", - (unsigned long) *len)); + (LOG_DEBUG, "bjnp_recv_data: read response payload (0x%lx bytes max), buffer: 0x%lx, start_pos: 0x%lx\n", + (long) *len, (long) buffer, (long) start_pos)); + + if (*len == 0) + { + /* nothing to do */ + PDBG (bjnp_dbg + (LOG_DEBUG, "bjnp_recv_data: Nothing to do (%ld bytes requested)\n", + (long) *len)); + return SANE_STATUS_GOOD; + } + else if ( *len > SSIZE_MAX ) + { + PDBG (bjnp_dbg + (LOG_DEBUG, "bjnp_recv_data: WARNING - requested block size (%ld) exceeds maximum, setting to maximum %ld\n", + (long)*len, SSIZE_MAX)); + *len = SSIZE_MAX; + } + + fd = device[devno].tcp_socket; attempt = 0; do { @@ -1488,7 +1607,7 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_data: could not read response payload (select): %s!\n", + "bjnp_recv_data: ERROR - could not read response payload (select failed): %s!\n", strerror (errno))); errno = terrno; *len = 0; @@ -1498,24 +1617,23 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_data: could not read response payload (select timed out): %s!\n", - strerror (terrno))); + "bjnp_recv_data: ERROR - could not read response payload (select timed out)!\n") ); errno = terrno; *len = 0; return SANE_STATUS_IO_ERROR; } - if ((recv_bytes = recv (fd, buffer, *len, 0)) < 0) + if ((recv_bytes = recv (fd, buffer + start_pos, *len, 0)) < 0) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, - "bjnp_recv_data: could not read response payload (recv): %s!\n", - strerror (errno))); + "bjnp_recv_data: ERROR - could not read response payload (%ld + %ld = %ld) (recv): %s!\n", + (long) buffer, (long) start_pos, (long) buffer + start_pos, strerror (errno))); errno = terrno; *len = 0; return SANE_STATUS_IO_ERROR; } - PDBG (bjnp_dbg (LOG_DEBUG2, "Received TCP response payload (%ld bytes):\n", + PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_recv_data: Received TCP response payload (%ld bytes):\n", (unsigned long) recv_bytes)); PDBG (bjnp_hexdump (LOG_DEBUG2, buffer, recv_bytes)); @@ -1531,6 +1649,7 @@ bjnp_allocate_device (SANE_String_Const devname, char host[BJNP_HOST_MAX]; char port[BJNP_PORT_MAX] = ""; char args[BJNP_ARGS_MAX]; + bjnp_protocol_defs_t *protocol_defs; struct addrinfo *res, *cur; struct addrinfo hints; int result; @@ -1547,22 +1666,22 @@ bjnp_allocate_device (SANE_String_Const devname, { PDBG (bjnp_dbg (LOG_CRIT, - "URI may not contain userid, password or aguments: %s\n", + "bjnp_allocate_device: ERROR - URI may not contain userid, password or aguments: %s\n", devname)); return BJNP_STATUS_INVAL; } - if (strcmp (method, BJNP_METHOD) != 0) + if ( (protocol_defs = get_protocol_by_method(method)) == NULL) { PDBG (bjnp_dbg - (LOG_CRIT, "URI %s contains invalid method: %s\n", devname, + (LOG_CRIT, "bjnp_allocate_device: ERROR - URI %s contains invalid method: %s\n", devname, method)); return BJNP_STATUS_INVAL; } if (strlen(port) == 0) { - sprintf( port, "%d", BJNP_PORT_SCAN ); + sprintf( port, "%d", protocol_defs->default_port ); } hints.ai_flags = 0; @@ -1581,7 +1700,7 @@ bjnp_allocate_device (SANE_String_Const devname, result = getaddrinfo (host, port, &hints, &res ); if (result != 0 ) { - PDBG (bjnp_dbg (LOG_CRIT, "Cannot resolve host: %s port %s\n", host, port)); + PDBG (bjnp_dbg (LOG_CRIT, "bjnp_allocate_device: ERROR - Cannot resolve host: %s port %s\n", host, port)); return SANE_STATUS_INVAL; } @@ -1596,12 +1715,13 @@ bjnp_allocate_device (SANE_String_Const devname, { PDBG (bjnp_dbg (LOG_CRIT, - "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, can not add %s\n", devname)); freeaddrinfo(res); return BJNP_STATUS_INVAL; } - if (bjnp_init_device_structure( bjnp_no_devices, (bjnp_sockaddr_t *)cur -> ai_addr) != 0) + if (bjnp_init_device_structure( bjnp_no_devices, (bjnp_sockaddr_t *)cur -> ai_addr, + protocol_defs) != 0) { /* giving up on this address, try next one if any */ break; @@ -1632,7 +1752,7 @@ bjnp_allocate_device (SANE_String_Const devname, } freeaddrinfo(res); - PDBG (bjnp_dbg (LOG_INFO, "Scanner not yet in our list, added it: %s:%s\n", host, port)); + 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 */ @@ -1670,7 +1790,7 @@ static void add_scanner(SANE_Int *dev_no, case BJNP_STATUS_GOOD: if (get_scanner_id (*dev_no, makemodel) != 0) { - PDBG (bjnp_dbg (LOG_CRIT, "Cannot read scanner make & model: %s\n", + PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: ERROR - Cannot read scanner make & model: %s\n", uri)); } else @@ -1682,15 +1802,17 @@ 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)); } break; case BJNP_STATUS_ALREADY_ALLOCATED: - PDBG (bjnp_dbg (LOG_NOTICE, "Scanner at %s was added before, good!\n", + PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: Scanner at %s was added before, good!\n", uri)); break; case BJNP_STATUS_INVAL: - PDBG (bjnp_dbg (LOG_NOTICE, "Scanner at %s can not be added\n", + PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: Scanner at %s can not be added\n", uri)); break; } @@ -1738,6 +1860,7 @@ sanei_bjnp_find_devices (const char **conf_devices, int socket_fd[BJNP_SOCK_MAX]; int no_sockets; int i; + int j; int attempt; int last_socketfd = 0; fd_set fdset; @@ -1746,13 +1869,16 @@ sanei_bjnp_find_devices (const char **conf_devices, char scanner_host[256]; char uri[256]; int dev_no; + int port; bjnp_sockaddr_t broadcast_addr[BJNP_SOCK_MAX]; bjnp_sockaddr_t scanner_sa; socklen_t socklen; + bjnp_protocol_defs_t *protocol_defs; memset( broadcast_addr, 0, sizeof( broadcast_addr) ); memset( &scanner_sa, 0 ,sizeof( scanner_sa ) ); - PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_find_devices:\n")); + PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_find_devices, pixma backend version: %d.%d.%d\n", + PIXMA_VERSION_MAJOR, PIXMA_VERSION_MINOR, PIXMA_VERSION_BUILD)); bjnp_no_devices = 0; for (i=0; i < BJNP_SOCK_MAX; i++) @@ -1762,24 +1888,23 @@ sanei_bjnp_find_devices (const char **conf_devices, /* First add devices from config file */ if (conf_devices[0] == NULL) - PDBG (bjnp_dbg( LOG_DEBUG, "No devices specified in configuration file.\n" ) ); + PDBG (bjnp_dbg( LOG_DEBUG, "sanei_bjnp_find_devices: No devices specified in configuration file.\n" ) ); for (i = 0; conf_devices[i] != NULL; i++) { PDBG (bjnp_dbg - (LOG_DEBUG, "Adding scanner from pixma.conf: %s\n", conf_devices[i])); + (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); } PDBG (bjnp_dbg (LOG_DEBUG, - "Added all configured scanners, now do auto detection...\n")); + "sanei_bjnp_find_devices: Added all configured scanners, now do auto detection...\n")); /* * Send UDP DISCOVER to discover scanners and return the list of scanners found */ FD_ZERO (&fdset); - set_cmd (-1, &cmd, CMD_UDP_DISCOVER, 0); no_sockets = 0; #ifdef HAVE_IFADDRS_H @@ -1824,7 +1949,7 @@ sanei_bjnp_find_devices (const char **conf_devices, local.ipv4.sin_addr.s_addr = htonl (INADDR_ANY); bc_addr.ipv4.sin_family = AF_INET; - bc_addr.ipv4.sin_port = htons(BJNP_PORT_SCAN); + bc_addr.ipv4.sin_port = htons(0); bc_addr.ipv4.sin_addr.s_addr = htonl (INADDR_BROADCAST); socket_fd[no_sockets] = prepare_socket( "any_interface", @@ -1866,7 +1991,14 @@ sanei_bjnp_find_devices (const char **conf_devices, { for ( i=0; i < no_sockets; i++) { - bjnp_send_broadcast ( socket_fd[i], &broadcast_addr[i], cmd, sizeof (cmd)); + j = 0; + while(bjnp_protocol_defs[j].protocol_version != PROTOCOL_NONE) + { + set_cmd_from_string (bjnp_protocol_defs[j].proto_string, &cmd, CMD_UDP_DISCOVER, 0); + bjnp_send_broadcast ( socket_fd[i], &broadcast_addr[i], + bjnp_protocol_defs[j].default_port, cmd, sizeof (cmd)); + j++; + } } /* wait for some time between broadcast packets */ usleep (BJNP_BROADCAST_INTERVAL * BJNP_USLEEP_MS); @@ -1882,7 +2014,7 @@ sanei_bjnp_find_devices (const char **conf_devices, while (select (last_socketfd + 1, &active_fdset, NULL, NULL, &timeout) > 0) { - PDBG (bjnp_dbg (LOG_DEBUG, "Select returned, time left %d.%d....\n", + PDBG (bjnp_dbg (LOG_DEBUG, "sanei_bjnp_find_devices: Select returned, time left %d.%d....\n", (int) timeout.tv_sec, (int) timeout.tv_usec)); for (i = 0; i < no_sockets; i++) { @@ -1894,17 +2026,18 @@ sanei_bjnp_find_devices (const char **conf_devices, &(scanner_sa.addr), &socklen ) ) == -1) { PDBG (bjnp_dbg - (LOG_INFO, "find_devices: no data received")); + (LOG_INFO, "sanei_find_devices: no data received")); break; } else { - PDBG (bjnp_dbg (LOG_DEBUG2, "Discover response:\n")); + PDBG (bjnp_dbg (LOG_DEBUG2, "sanei_find_devices: Discover response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, &resp_buf, numbytes)); /* check if something sensible is returned */ + protocol_defs = get_protocol_by_proto_string(disc_resp-> response.BJNP_id); if ( (numbytes < (int)sizeof (struct BJNP_command)) || - (strncmp ("BJNP", disc_resp-> response.BJNP_id, 4) != 0)) + (protocol_defs == NULL)) { /* not a valid response, assume not a scanner */ @@ -1912,11 +2045,11 @@ sanei_bjnp_find_devices (const char **conf_devices, strncpy(bjnp_id, disc_resp-> response.BJNP_id, 4); bjnp_id[4] = '\0'; PDBG (bjnp_dbg (LOG_INFO, - "Invalid discover response! Length = %d, Id = %s\n", + "sanei_find_devices: Invalid discover response! Length = %d, Id = %s\n", numbytes, bjnp_id ) ); break; } - if ( ! ((disc_resp -> response.dev_type) & 0x80) ) + if ( !(disc_resp -> response.dev_type & 0x80) ) { /* not a response, a command from somebody else or */ /* a discover command that we generated */ @@ -1924,12 +2057,13 @@ sanei_bjnp_find_devices (const char **conf_devices, } }; + port = get_port_from_sa(scanner_sa); /* scanner found, get IP-address or hostname */ get_scanner_name( &scanner_sa, scanner_host); /* construct URI */ - sprintf (uri, "%s://%s:%d", BJNP_METHOD, scanner_host, - BJNP_PORT_SCAN); + sprintf (uri, "%s://%s:%d", protocol_defs->method_string, scanner_host, + port); add_scanner( &dev_no, uri, attach_bjnp, pixma_devices); @@ -1939,7 +2073,7 @@ sanei_bjnp_find_devices (const char **conf_devices, timeout.tv_sec = 0; timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * BJNP_USLEEP_MS; } - PDBG (bjnp_dbg (LOG_DEBUG, "scanner discovery finished...\n")); + PDBG (bjnp_dbg (LOG_DEBUG, "sanei_find_devices: scanner discovery finished...\n")); for (i = 0; i < no_sockets; i++) close (socket_fd[i]); @@ -1977,10 +2111,10 @@ sanei_bjnp_open (SANE_String_Const devname, SANE_Int * dn) PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_open(%s, %d):\n", devname, *dn)); result = bjnp_allocate_device (devname, dn, NULL); - if ( (result != BJNP_STATUS_GOOD) && (result != BJNP_STATUS_ALREADY_ALLOCATED ) ) + if ( (result != BJNP_STATUS_GOOD) && (result != BJNP_STATUS_ALREADY_ALLOCATED ) ) { return SANE_STATUS_INVAL; - - return sanei_bjnp_activate( *dn);; + } + return SANE_STATUS_GOOD; } /** Close a BJNP device. @@ -1992,8 +2126,9 @@ void sanei_bjnp_close (SANE_Int dn) { PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_close(%d):\n", dn)); - sanei_bjnp_deactivate(dn); + device[dn].open = 0; + sanei_bjnp_deactivate(dn); } /** Activate BJNP device connection @@ -2008,7 +2143,6 @@ sanei_bjnp_activate (SANE_Int dn) char pid_str[64]; PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_activate (%d)\n", dn)); - gethostname (hostname, 256); hostname[255] = '\0'; sprintf (pid_str, "Process ID = %d", getpid ()); @@ -2032,11 +2166,9 @@ SANE_Status sanei_bjnp_deactivate (SANE_Int dn) { PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_deactivate (%d)\n", dn)); - - bjnp_finish_job (dn); - if ( device[dn].tcp_socket != -1) { + bjnp_finish_job (dn); close (device[dn].tcp_socket); device[dn].tcp_socket = -1; } @@ -2079,12 +2211,13 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) SANE_Status result; SANE_Status error; size_t recvd; - size_t more; + size_t read_size; + size_t read_size_max; size_t requested; PDBG (bjnp_dbg - (LOG_INFO, "bjnp_read_bulk(%d, bufferptr, 0x%lx = %ld)\n", dn, - (unsigned long) *size, (unsigned long) *size)); + (LOG_INFO, "bjnp_read_bulk(dn=%d, bufferptr=%lx, 0x%lx = %ld)\n", dn, + (long) buffer, (unsigned long) *size, (unsigned long) *size)); recvd = 0; requested = *size; @@ -2095,20 +2228,21 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) (unsigned long) device[dn].scanner_data_left ) ); while ( (recvd < requested) && !( device[dn].last_block && (device[dn].scanner_data_left == 0)) ) - { PDBG (bjnp_dbg (LOG_DEBUG, - "Received 0x%lx = %ld bytes, backend requested 0x%lx = %ld bytes\n", + "bjnp_read_bulk: Already received 0x%lx = %ld bytes, backend requested 0x%lx = %ld bytes\n", (unsigned long) recvd, (unsigned long) recvd, (unsigned long) requested, (unsigned long)requested )); + /* Check first if there is data in flight from the scanner */ + if (device[dn].scanner_data_left == 0) { - /* send new read request */ + /* There is no data in flight from the scanner, send new read request */ PDBG (bjnp_dbg (LOG_DEBUG, - "No (more) scanner data available, requesting more( blocksize = %ld =%lx\n", + "bjnp_read_bulk: No (more) scanner data available, requesting more( blocksize = %ld = %lx\n", (long int) device[dn].blocksize, (long int) device[dn].blocksize )); if ((error = bjnp_send_read_request (dn)) != SANE_STATUS_GOOD) @@ -2133,43 +2267,40 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) device[dn].last_block = 1; } - if ( device[dn].scanner_data_left == 0 ) - { - break; - } } - PDBG (bjnp_dbg (LOG_DEBUG, "Scanner reports 0x%lx = %ld bytes available\n", + PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: In flight: 0x%lx = %ld bytes available\n", (unsigned long) device[dn].scanner_data_left, (unsigned long) device[dn].scanner_data_left)); - /* read as many bytes as needed and available */ + /* read as many bytes as needed and available */ - more = MIN( device[dn].scanner_data_left, (requested - recvd) ); + read_size_max = MIN( device[dn].scanner_data_left, (requested - recvd) ); + read_size = read_size_max; PDBG (bjnp_dbg (LOG_DEBUG, - "reading 0x%lx = %ld (of max 0x%lx = %ld) bytes\n", - (unsigned long) more, - (unsigned long) more, + "bjnp_read_bulk: Try to read 0x%lx = %ld (of max 0x%lx = %ld) bytes\n", + (unsigned long) read_size_max, + (unsigned long) read_size_max, (unsigned long) device[dn].scanner_data_left, (unsigned long) device[dn].scanner_data_left) ); - result = bjnp_recv_data (dn, buffer + recvd, &more); + result = bjnp_recv_data (dn, buffer , recvd, &read_size); if (result != SANE_STATUS_GOOD) { *size = recvd; return SANE_STATUS_IO_ERROR; } - PDBG (bjnp_dbg (LOG_DEBUG, "Requested %ld bytes, received: %ld\n", - MIN( device[dn].scanner_data_left, (requested - recvd) ), more) ); + PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: Expected at most %ld bytes, received this time: %ld\n", + read_size_max, read_size) ); - device[dn].scanner_data_left = device[dn].scanner_data_left - more; - recvd = recvd + more; + device[dn].scanner_data_left = device[dn].scanner_data_left - read_size; + recvd = recvd + read_size; } - PDBG (bjnp_dbg (LOG_DEBUG, "returning %ld bytes, backend expexts %ld\n", - recvd, *size ) ); + PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: %s: Returning %ld bytes, backend expexts %ld\n", + (recvd == *size)? "OK": "NOTICE",recvd, *size ) ); *size = recvd; if ( *size == 0 ) return SANE_STATUS_EOF; @@ -2199,51 +2330,50 @@ sanei_bjnp_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) uint32_t buf; size_t payload_size; - PDBG (bjnp_dbg - (LOG_INFO, "bjnp_write_bulk(%d, bufferptr, 0x%lx = %ld)\n", dn, - (unsigned long) *size, (unsigned long) *size)); + /* Write received data to scanner */ + sent = bjnp_write (dn, buffer, *size); if (sent < 0) return SANE_STATUS_IO_ERROR; if (sent != (int) *size) { PDBG (bjnp_dbg - (LOG_CRIT, "Sent only %ld bytes to scanner, expected %ld!!\n", + (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Sent only %ld bytes to scanner, expected %ld!!\n", (unsigned long) sent, (unsigned long) *size)); return SANE_STATUS_IO_ERROR; } if (bjnp_recv_header (dn, &payload_size) != SANE_STATUS_GOOD) { - PDBG (bjnp_dbg (LOG_CRIT, "Could not read response to command!\n")); + PDBG (bjnp_dbg (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Could not read response to command!\n")); return SANE_STATUS_IO_ERROR; } if (payload_size != 4) { PDBG (bjnp_dbg (LOG_CRIT, - "Scanner length of write confirmation = 0x%lx bytes = %ld, expected %d!!\n", + "sanei_bjnp_write_bulk: ERROR - Scanner length of write confirmation = 0x%lx bytes = %ld, expected %d!!\n", (unsigned long) payload_size, (unsigned long) payload_size, 4)); return SANE_STATUS_IO_ERROR; } recvd = payload_size; - if ((bjnp_recv_data (dn, (unsigned char *) &buf, &recvd) != + if ((bjnp_recv_data (dn, (unsigned char *) &buf, 0, &recvd) != SANE_STATUS_GOOD) || (recvd != payload_size)) { PDBG (bjnp_dbg (LOG_CRIT, - "Could not read length of data confirmed by device\n")); + "sanei_bjnp_write_bulk: ERROR - Could not read length of data confirmed by device\n")); return SANE_STATUS_IO_ERROR; } recvd = ntohl (buf); if (recvd != *size) { PDBG (bjnp_dbg - (LOG_CRIT, "Scanner confirmed %ld bytes, expected %ld!!\n", + (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Scanner confirmed %ld bytes, expected %ld!!\n", (unsigned long) recvd, (unsigned long) *size)); return SANE_STATUS_IO_ERROR; } - /* we can expect data from the scanner again */ + /* we can expect data from the scanner */ device[dn].last_block = 0; @@ -2304,13 +2434,15 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) if ( (bjnp_poll_scanner (dn, 0, hostname, getusername (), buffer, *size ) != 0) || (bjnp_poll_scanner (dn, 1, hostname, getusername (), buffer, *size ) != 0) ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Failed to setup read_intr dialog with device!\n")); + PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: WARNING - Failed to setup read_intr dialog with device!\n")); device[dn].dialog = 0; device[dn].status_key = 0; return SANE_STATUS_IO_ERROR; } device[dn].polling_status = BJNP_POLL_STARTED; + /* fall through to BJNP_POLL_STARTED */ + case BJNP_POLL_STARTED: /* we use only seonds accuracy between poll attempts */ timeout = device[dn].bjnp_timeout /1000; @@ -2319,7 +2451,7 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) { if ( (resp_len = bjnp_poll_scanner (dn, 2, hostname, getusername (), buffer, *size ) ) < 0 ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Restarting polling dialog!\n")); + PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: Restarting polling dialog!\n")); device[dn].polling_status = BJNP_POLL_STOPPED; *size = 0; return SANE_STATUS_EOF; @@ -2332,8 +2464,11 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) /* 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; } @@ -2345,7 +2480,7 @@ sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) case BJNP_POLL_STATUS_RECEIVED: if ( (resp_len = bjnp_poll_scanner (dn, 5, hostname, getusername (), buffer, *size ) ) < 0 ) { - PDBG (bjnp_dbg (LOG_NOTICE, "Restarting polling dialog!\n")); + PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: Restarting polling dialog!\n")); device[dn].polling_status = BJNP_POLL_STOPPED; *size = 0; break; |