From 2832e4ef9f3abd143b0d624324494da3f70a15ee Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 2 Apr 2020 14:14:25 +0200 Subject: [PATCH 01/21] pixma: move lookup_scanner back to pixma_io_sanei.c Move lookup_scanner from pixma_bjnp.c back to pixma_io_sanei.c as it will be required by Axis support. This partially reverts bd2d5f5e7d6dc2047448e5e027d94d753dc7baef --- backend/pixma/pixma_bjnp.c | 61 +++++---------------------- backend/pixma/pixma_bjnp.h | 10 +++-- backend/pixma/pixma_io_sanei.c | 76 +++++++++++++++++++++++++++------- 3 files changed, 76 insertions(+), 71 deletions(-) diff --git a/backend/pixma/pixma_bjnp.c b/backend/pixma/pixma_bjnp.c index 34ba918f2..2c3fc09d1 100644 --- a/backend/pixma/pixma_bjnp.c +++ b/backend/pixma/pixma_bjnp.c @@ -118,40 +118,6 @@ static int bjnp_no_devices = 0; * Private functions */ -static const struct pixma_config_t *lookup_scanner(const char *makemodel, - const struct pixma_config_t *const pixma_devices[]) -{ - int i; - const struct pixma_config_t *cfg; - char *match; - - for (i = 0; pixma_devices[i]; i++) - { - /* loop through the device classes (mp150, mp730 etc) */ - for (cfg = pixma_devices[i]; cfg->name; cfg++) - { - /* loop through devices in class */ - PDBG( bjnp_dbg( LOG_DEBUG3, "lookup_scanner: Checking for %s in %s\n", makemodel, cfg->model)); - if ((match = strcasestr (makemodel, cfg->model)) != NULL) - { - /* possible match found, make sure it is not a partial match */ - /* MP600 and MP600R are different models! */ - /* some models contain ranges, so check for a '-' too */ - - if ((match[strlen(cfg->model)] == ' ') || - (match[strlen(cfg->model)] == '\0') || - (match[strlen(cfg->model)] == '-')) - { - PDBG( bjnp_dbg (LOG_DEBUG, "lookup_scanner: Scanner model found: Name %s(%s) matches %s\n", cfg->model, cfg->name, makemodel)); - return cfg; - } - } - } - } - PDBG( bjnp_dbg (LOG_DEBUG, "lookup_scanner: Scanner model %s not found, giving up!\n", makemodel)); - return NULL; -} - static void u8tohex (char *string, const uint8_t *value, int len ) { @@ -1846,15 +1812,16 @@ static void add_scanner(SANE_Int *dev_no, const char *uri, SANE_Status (*attach_bjnp) (SANE_String_Const devname, + SANE_String_Const makemodel, SANE_String_Const serial, - const struct pixma_config_t *cfg), - const struct pixma_config_t *const pixma_devices[]) + const struct pixma_config_t * + const pixma_devices[]), + const struct pixma_config_t *const pixma_devices[]) { char scanner_host[BJNP_HOST_MAX]; char serial[BJNP_SERIAL_MAX]; char makemodel[BJNP_MODEL_MAX]; - const struct pixma_config_t *cfg = NULL; /* Allocate device structure for scanner */ switch (bjnp_allocate_device (uri, dev_no, scanner_host)) @@ -1867,22 +1834,12 @@ static void add_scanner(SANE_Int *dev_no, } else { - /* - * fetch scanner configuration - */ - if ((cfg = lookup_scanner(makemodel, pixma_devices)) == (struct pixma_config_t *)NULL) - { - PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: Scanner %s is not supported, model is unknown! Please report upstream\n", makemodel)); - break; - } - /* * inform caller of found scanner */ - determine_scanner_serial (scanner_host, device[*dev_no].mac_address, serial); - switch (attach_bjnp (uri, serial, cfg)) + switch (attach_bjnp (uri, makemodel, serial, pixma_devices)) { case SANE_STATUS_GOOD: PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: New scanner added: %s, serial %s, mac address: %s.\n", @@ -1972,9 +1929,11 @@ sanei_bjnp_init (void) extern SANE_Status sanei_bjnp_find_devices (const char **conf_devices, SANE_Status (*attach_bjnp) - (SANE_String_Const devname, - SANE_String_Const serial, - const struct pixma_config_t *cfg), + (SANE_String_Const devname, + SANE_String_Const makemodel, + SANE_String_Const serial, + const struct pixma_config_t * + const pixma_devices[]), const struct pixma_config_t *const pixma_devices[]) { int numbytes = 0; diff --git a/backend/pixma/pixma_bjnp.h b/backend/pixma/pixma_bjnp.h index 79e084eb9..a27082c87 100644 --- a/backend/pixma/pixma_bjnp.h +++ b/backend/pixma/pixma_bjnp.h @@ -81,10 +81,12 @@ extern void sanei_bjnp_init (void); extern SANE_Status sanei_bjnp_find_devices (const char **conf_devices, SANE_Status (*attach_bjnp) - (SANE_String_Const devname, - SANE_String_Const serial, - const struct pixma_config_t *cfg), - const struct pixma_config_t *const pixma_devices[]); + (SANE_String_Const devname, + SANE_String_Const makemodel, + SANE_String_Const serial, + const struct pixma_config_t * + const pixma_devices[]), + const struct pixma_config_t *const pixma_devices[]); /** Open a BJNP device. * diff --git a/backend/pixma/pixma_io_sanei.c b/backend/pixma/pixma_io_sanei.c index 2a0ff2340..9f31dbe72 100644 --- a/backend/pixma/pixma_io_sanei.c +++ b/backend/pixma/pixma_io_sanei.c @@ -109,6 +109,40 @@ get_scanner_info (unsigned devnr) return si; } +static const struct pixma_config_t *lookup_scanner(const char *makemodel, + const struct pixma_config_t *const pixma_devices[]) +{ + int i; + const struct pixma_config_t *cfg; + char *match; + + for (i = 0; pixma_devices[i]; i++) + { + /* loop through the device classes (mp150, mp730 etc) */ + for (cfg = pixma_devices[i]; cfg->name; cfg++) + { + /* loop through devices in class */ + pixma_dbg( 5, "lookup_scanner: Checking for %s in %s\n", makemodel, cfg->model); + if ((match = strcasestr (makemodel, cfg->model)) != NULL) + { + /* possible match found, make sure it is not a partial match */ + /* MP600 and MP600R are different models! */ + /* some models contain ranges, so check for a '-' too */ + + if ((match[strlen(cfg->model)] == ' ') || + (match[strlen(cfg->model)] == '\0') || + (match[strlen(cfg->model)] == '-')) + { + pixma_dbg (3, "lookup_scanner: Scanner model found: Name %s(%s) matches %s\n", cfg->model, cfg->name, makemodel); + return cfg; + } + } + } + } + pixma_dbg (3, "lookup_scanner: Scanner model %s not found, giving up!\n", makemodel); + return NULL; +} + static SANE_Status attach (SANE_String_Const devname) { @@ -129,11 +163,13 @@ attach (SANE_String_Const devname) static SANE_Status -attach_net (SANE_String_Const devname, +attach_net (SANE_String_Const devname, SANE_String_Const makemodel, SANE_String_Const serial, - const struct pixma_config_t *cfg, int interface) + const struct pixma_config_t *const pixma_devices[],int interface) { scanner_info_t *si; + const pixma_config_t *cfg; + SANE_Status error; si = (scanner_info_t *) calloc (1, sizeof (*si)); if (!si) @@ -141,30 +177,38 @@ attach_net (SANE_String_Const devname, si->devname = strdup (devname); if (!si->devname) return SANE_STATUS_NO_MEM; - - si->cfg = cfg; - sprintf(si->serial, "%s_%s", cfg->model, serial); - si -> interface = interface; - si->next = first_scanner; - first_scanner = si; - nscanners++; - return SANE_STATUS_GOOD; + if ((cfg = lookup_scanner(makemodel, pixma_devices)) == (struct pixma_config_t *)NULL) + { + pixma_dbg (0, "attach_net: Scanner %s is not supported, model is unknown! Please report upstream\n", makemodel); + error = SANE_STATUS_INVAL; + } + else + { + si->cfg = cfg; + sprintf(si->serial, "%s_%s", cfg->model, serial); + si -> interface = interface; + si->next = first_scanner; + first_scanner = si; + nscanners++; + error = SANE_STATUS_GOOD; + } + return error; } static SANE_Status -attach_bjnp (SANE_String_Const devname, +attach_bjnp (SANE_String_Const devname, SANE_String_Const makemodel, SANE_String_Const serial, - const struct pixma_config_t *cfg) + const struct pixma_config_t *const pixma_devices[]) { - return attach_net(devname, serial, cfg, INT_BJNP); + return attach_net(devname, makemodel, serial, pixma_devices, INT_BJNP); } static SANE_Status -attach_axis (SANE_String_Const devname, +attach_axis (SANE_String_Const devname, SANE_String_Const makemodel, SANE_String_Const serial, - const struct pixma_config_t *cfg) + const struct pixma_config_t *const pixma_devices[]) { - return attach_net(devname, serial, cfg, INT_AXIS); + return attach_net(devname, makemodel, serial, pixma_devices, INT_AXIS); } static void From 4577e340802fca139beb687508b554cdc22ebfcb Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 7 Apr 2020 11:09:58 +0200 Subject: [PATCH 02/21] pixma: make AXIS support really work Add support for long transfers, timeout, ignore 0x24 bytes and fix warnings Scanning works now! --- backend/pixma/pixma_axis.c | 82 ++++++++++++++++++++---------- backend/pixma/pixma_axis_private.h | 1 - 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index e90a8bb19..e6ff11ac7 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -251,6 +251,7 @@ static int get_device_name(int udp_socket, uint32_t addr, uint16_t remote_port, DBG(LOG_INFO, "name=%s\n", buf); strncpy(devname, buf, devname_len); + devname[devname_len - 1] = '\0'; return 0; } @@ -332,32 +333,54 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { return 0; } -int axis_recv(SANE_Int dn, void *data, size_t *len) { +int axis_recv(SANE_Int dn, SANE_Byte *data, size_t *len) { uint8_t packet[MAX_PACKET_DATA_SIZE]; + uint8_t *data_pos; struct axis_header *header = (void *)packet; struct axis_reply *reply = (void *)packet; - ssize_t ret; + ssize_t ret, remaining; int i; retry: + /* AXIS sends 0x24 byte 15 seconds after end of scan, then repeats 3 more times each 5 seconds - the purpose is unknown, get rid of that */ + ret = recv(device[dn].tcp_socket, packet, 4, MSG_PEEK); + if (ret < 0) + return -1; + int count = 0; + for (int i = 0; i < ret; i++) + if (packet[i] == 0x24) + count++; + else + break; + if (count) { + fprintf(stderr, "discarded %d 0x24 bytes\n", count); + recv(device[dn].tcp_socket, packet, count, 0); + } ret = recv(device[dn].tcp_socket, packet, sizeof(struct axis_header), 0); - fprintf(stderr, "got1: "); - for (i = 0; i < ret; i++) { - fprintf(stderr, "%02x ", packet[i]); + if (ret < sizeof(struct axis_header)) { + perror("recv error!!!"); + return -1; } + fprintf(stderr, "got1: "); + for (unsigned int i = 0; i < sizeof(struct axis_header); i++) + fprintf(stderr, "%02x ", packet[i]); fprintf(stderr, "\n"); if (header->type != AXIS_HDR_REPLY) { - fprintf(stderr, "not reply!\n"); + fprintf(stderr, "not a reply!:"); + for (i = 0; i < ret; i++) + fprintf(stderr, "%02x ", packet[i]); + fprintf(stderr, "\n"); return -1; } *len = le16_to_cpu(header->len); - fprintf(stderr, "len=0x%x\n", *len); + fprintf(stderr, "len=0x%lx\n", *len); ret = recv(device[dn].tcp_socket, packet, *len, 0); - fprintf(stderr, "got2: "); - for (i = 0; i < ret; i++) { - fprintf(stderr, "%02x ", packet[i]); + if (ret < 512) { + fprintf(stderr, "got2: "); + for (i = 0; i < ret; i++) + fprintf(stderr, "%02x ", packet[i]); } fprintf(stderr, "\n"); *len = le16_to_cpu(reply->len); @@ -367,12 +390,21 @@ retry: device[dn].int_size = *len; goto retry; } - memcpy(data, packet + sizeof(struct axis_reply), *len); + memcpy(data, packet + sizeof(struct axis_reply), ret - sizeof(struct axis_reply)); if (reply->status != 0) { fprintf(stderr, "status=0x%x\n", le16_to_cpu(reply->status)); return SANE_STATUS_IO_ERROR; } + remaining = *len - (ret - sizeof(struct axis_reply)); + data_pos = data + ret - sizeof(struct axis_reply); + while (remaining > 0) { + fprintf(stderr, "remaining bytes: %ld\n", remaining); + ret = recv(device[dn].tcp_socket, data_pos, remaining, 0); + remaining -= ret; + data_pos += ret; + } + return 0; } @@ -497,7 +529,7 @@ sanei_axis_open (SANE_String_Const devname, SANE_Int * dn) username = getusername(); axis_send_cmd(tcp_socket, AXIS_CMD_CONNECT, username, strlen(username) + 1); - const SANE_Byte *dummy_buf[MAX_PACKET_DATA_SIZE]; + SANE_Byte dummy_buf[MAX_PACKET_DATA_SIZE]; size_t dummy_len; axis_recv(i, dummy_buf, &dummy_len); @@ -524,23 +556,25 @@ extern void sanei_axis_set_timeout (SANE_Int dn, SANE_Int timeout) { DBG(LOG_INFO, "%s(%d, %d)\n", __func__, dn, timeout); - device[dn].axis_timeout = timeout; + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = timeout % 1000; + setsockopt(device[dn].tcp_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); } extern SANE_Status sanei_axis_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) { - int i; - DBG(LOG_INFO, "%s(%d, %p, %d)\n", __func__, dn, buffer, *size); + DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); // uint8_t buf_read[] = { 0x40, 0x00 }; uint16_t read_size = cpu_to_le16(*size); // axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_READ, buf_read, sizeof(buf_read)); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_READ, &read_size, sizeof(read_size)); axis_recv(dn, buffer, size); ////FIXME fprintf(stderr, "sanei_axis_read_bulk: "); - for (i = 0; i < *size; i++) { - fprintf(stderr, "%02x ", buffer[i]); - } + if (*size < 512) + for (unsigned int i = 0; i < *size; i++) + fprintf(stderr, "%02x ", buffer[i]); fprintf(stderr, "\n"); return SANE_STATUS_GOOD; } @@ -548,16 +582,12 @@ sanei_axis_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) extern SANE_Status sanei_axis_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) { - const SANE_Byte *dummy_buf[MAX_PACKET_DATA_SIZE]; + SANE_Byte dummy_buf[MAX_PACKET_DATA_SIZE]; size_t dummy_len; - int i; - DBG(LOG_INFO, "%s(%d, %p, %d)\n", __func__, dn, buffer, *size); + DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); fprintf(stderr, "sanei_axis_write_bulk: "); - for (i = 0; i < *size; i++) { - fprintf(stderr, "%02x ", buffer[i]); - } fprintf(stderr, "\n"); - axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_WRITE, buffer, *size); + axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_WRITE, (void *) buffer, *size); axis_recv(dn, dummy_buf, &dummy_len); ////FIXME return SANE_STATUS_GOOD; } @@ -565,7 +595,7 @@ sanei_axis_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) extern SANE_Status sanei_axis_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) { - DBG(LOG_INFO, "%s(%d, %p, %d)\n", __func__, dn, buffer, *size); + DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); if (!device[dn].int_size) return SANE_STATUS_EOF; memcpy(buffer, device[dn].int_data, device[dn].int_size); diff --git a/backend/pixma/pixma_axis_private.h b/backend/pixma/pixma_axis_private.h index 96f18ca90..de4edba19 100644 --- a/backend/pixma/pixma_axis_private.h +++ b/backend/pixma/pixma_axis_private.h @@ -83,7 +83,6 @@ typedef struct device_s int tcp_socket; /* open tcp socket for communcation to scannner */ /* device information */ struct in_addr addr; /* IP address of the scanner */ - int axis_timeout; /* timeout (msec) for next poll command */ int int_size; /* size of interrupt data */ uint8_t int_data[16]; /* interrupt data */ } axis_device_t; From 7de193c9a4d923194716f77d8b7a7ac66eb8a002 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 7 Apr 2020 13:57:04 +0200 Subject: [PATCH 03/21] pixma: honor local_only for AXIS devices Don't search for AXIS devices if local_only flag is set --- backend/pixma/pixma_io_sanei.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/pixma/pixma_io_sanei.c b/backend/pixma/pixma_io_sanei.c index 9f31dbe72..dd5051ef1 100644 --- a/backend/pixma/pixma_io_sanei.c +++ b/backend/pixma/pixma_io_sanei.c @@ -410,7 +410,8 @@ pixma_collect_devices (const char **conf_devices, j++; } - sanei_axis_find_devices(conf_devices, attach_axis, pixma_devices); + if (! local_only) + sanei_axis_find_devices(conf_devices, attach_axis, pixma_devices); si = first_scanner; while (j < nscanners) { @@ -634,7 +635,7 @@ pixma_wait_interrupt (pixma_io_t * io, void *buf, unsigned size, int timeout) } if (error == PIXMA_EIO || (io->interface == INT_BJNP && error == PIXMA_EOF) || /* EOF is a bjnp timeout error! */ - (io->interface == INT_AXIS && error == PIXMA_EOF)) /* EOF is a bjnp timeout error! */ + (io->interface == INT_AXIS && error == PIXMA_EOF)) /* EOF is an axis timeout error! */ error = PIXMA_ETIMEDOUT; /* FIXME: SANE doesn't have ETIMEDOUT!! */ if (error == 0) error = count; From 92e2ef62707985d665a4c080113b5bcf631987e0 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 9 Apr 2020 10:59:42 +0200 Subject: [PATCH 04/21] pixma: add AXIS pixma.conf support Support reading configuration from pixma conf. Also fix some debug messages. --- backend/pixma/pixma_axis.c | 177 ++++++++++++++++++++++++++----------- 1 file changed, 123 insertions(+), 54 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index e6ff11ac7..46685eb12 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -98,13 +98,13 @@ static ssize_t receive_packet(int socket, void *packet, size_t len, struct socka case 0: return 0; case -1: - DBG(LOG_CRIT, "select() failed"); + DBG(LOG_CRIT, "select() failed\n"); return 0; default: received = recvfrom(socket, packet, len, 0, (struct sockaddr *)from, &from_len); if (received < 0) { - DBG(LOG_CRIT, "Error receiving packet"); - exit(2); + DBG(LOG_CRIT, "Error receiving packet\n"); + return 0; } /*#ifdef DEBUG int i; @@ -127,7 +127,7 @@ static ssize_t axis_send_wimp(int udp_socket, uint8_t cmd, void *data, uint16_t memcpy(packet + sizeof(struct axis_wimp_header), data, len); ret = sendto(udp_socket, packet, sizeof(struct axis_wimp_header) + len, 0, addr, addrlen); if (ret != (int)sizeof(struct axis_wimp_header) + len) { - DBG(LOG_CRIT, "Unable to send UDP packet"); + DBG(LOG_CRIT, "Unable to send UDP packet\n"); return ret; } @@ -174,12 +174,12 @@ static int create_udp_socket(uint32_t addr, uint16_t *source_port) { udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if (udp_socket < 0) { - DBG(LOG_CRIT, "Unable to create UDP socket"); + DBG(LOG_CRIT, "Unable to create UDP socket\n"); return -1; } if (setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable))) { - DBG(LOG_CRIT, "Unable to enable broadcast"); + DBG(LOG_CRIT, "Unable to enable broadcast\n"); return -1; } @@ -187,7 +187,7 @@ static int create_udp_socket(uint32_t addr, uint16_t *source_port) { address.sin_port = 0; /* random */ address.sin_addr.s_addr = addr; if (bind(udp_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { - DBG(LOG_CRIT, "Unable to bind UDP socket"); + DBG(LOG_CRIT, "Unable to bind UDP socket\n"); return -1; } @@ -210,7 +210,7 @@ static int get_server_status(int udp_socket, uint32_t addr, uint16_t remote_port /* connect the socket to this print server only */ if (connect(udp_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { - DBG(LOG_CRIT, "Unable to connect UDP socket"); + DBG(LOG_CRIT, "Unable to connect UDP socket\n"); return -1; } @@ -241,13 +241,17 @@ static int get_device_name(int udp_socket, uint32_t addr, uint16_t remote_port, /* connect the socket to this print server only */ if (connect(udp_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { - DBG(LOG_CRIT, "Unable to connect UDP socket"); + DBG(LOG_CRIT, "Unable to connect UDP socket\n"); return -1; } + buf[0] = '\0'; /* get device name */ if (axis_wimp_get(udp_socket, remote_port, WIMP_GET_NAME, 1, buf, sizeof(buf))) - DBG(LOG_NOTICE, "Error getting device name\n"); + { + DBG(LOG_NOTICE, "Error getting device name\n"); + return -1; + } DBG(LOG_INFO, "name=%s\n", buf); strncpy(devname, buf, devname_len); @@ -270,7 +274,7 @@ static int send_discover(int udp_socket, uint32_t addr, uint16_t source_port) { ret = axis_send_wimp(udp_socket, WIMP_SERVER_INFO, get_info, sizeof(get_info), (struct sockaddr *)&address, sizeof(address)); if (ret) - DBG(LOG_CRIT, "Unable to send discover packet"); + DBG(LOG_CRIT, "Unable to send discover packet\n"); return ret; } @@ -280,7 +284,7 @@ static int send_broadcasts(int udp_socket, uint16_t source_port) { int num_sent = 0; if (getifaddrs(&ifaddr) == -1) { - DBG(LOG_CRIT, "Unable to obtain network interface list"); + DBG(LOG_CRIT, "Unable to obtain network interface list\n"); return -1; } @@ -313,7 +317,7 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { fprintf(stderr, "%02x ", packet[i]); fprintf(stderr, "\n"); if (ret < 0) { - perror("Error sending packet"); + DBG(LOG_NOTICE, "Error sending packet\n"); return ret; } @@ -326,7 +330,7 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { fprintf(stderr, "%02x ", packet[i]); fprintf(stderr, "\n"); if (ret < 0) { - perror("Error sending packet"); + DBG(LOG_NOTICE, "Error sending packet\n"); return ret; } @@ -408,6 +412,55 @@ retry: return 0; } +static int +parse_uri(const char *uri, struct sockaddr_in *address) +{ + const char *uri_host, *uri_port; + char host[256]; + size_t host_len; + int port; + + if (strncmp(uri, "axis://", 7)) + { + DBG(LOG_INFO, "Invalid protocol in uri\n"); + return -1; + } + uri_host = uri + 7; + + port = AXIS_SCAN_PORT; + uri_port = strchr(uri_host, ':'); + if (uri_port) + { + sscanf(uri_port, ":%d", &port); + host_len = uri_port - uri_host; + } + else + host_len = strlen(uri_host); + if (host_len > 255) + host_len = 255; + strncpy(host, uri_host, host_len); + host[host_len] = '\0'; + + /* resolve host */ + struct addrinfo *result; + struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP }; + int err = getaddrinfo(host, NULL, &hints, &result); + if (err) + { + DBG(LOG_INFO, "getaddrinfo failed: %s\n", gai_strerror(err)); + return -1; + } + struct sockaddr_in *addr = (struct sockaddr_in *) result->ai_addr; + DBG(LOG_DEBUG, "host=%s, ip=%s, port=%d\n", host, inet_ntoa(addr->sin_addr), port); + address->sin_family = AF_INET; + address->sin_port = htons(port); + address->sin_addr = addr->sin_addr; + + freeaddrinfo(result); + + return 0; +} + /** * Find AXIS printservers with Canon support @@ -432,13 +485,61 @@ sanei_axis_find_devices (const char **conf_devices, char uri[256]; uint8_t packet[MAX_PACKET_DATA_SIZE]; struct sockaddr_in from; - uint16_t source_port, remote_port; + uint16_t source_port; int udp_socket, num_ifaces; + int auto_detect = 1, i; + + /* parse config file */ + if (conf_devices[0] != NULL) + { + if (strcmp(conf_devices[0], "networking=no") == 0) + { + /* networking=no may only occur on the first non-commented line */ + DBG(LOG_DEBUG, "sanei_axis_find_devices: networking disabled in configuration file\n"); + return SANE_STATUS_GOOD; + } + for (i = 0; conf_devices[i] != NULL; i++) + { + if (!strcmp(conf_devices[i], "auto_detection=no")) + { + auto_detect = 0; + DBG(LOG_DEBUG, "sanei_axis_find_devices: auto detection of network scanners disabled in configuration file\n"); + continue; + } + else + { + DBG(LOG_DEBUG, "sanei_axis_find_devices: Adding scanner from pixma.conf: %s\n", conf_devices[i]); + strncpy(uri, conf_devices[i], sizeof(uri) - 1); + uri[sizeof(uri) - 1] = '\0'; + if (axis_no_devices >= AXIS_NO_DEVICES) + { + DBG(LOG_INFO, "sanei_axis_find_devices: device limit %d reached\n", AXIS_NO_DEVICES); + return SANE_STATUS_NO_MEM; + } + + struct sockaddr_in addr; + if (parse_uri(uri, &addr)) + continue; + udp_socket = create_udp_socket(htonl(INADDR_ANY), &source_port); + if (udp_socket < 0) + return SANE_STATUS_IO_ERROR; + if (get_device_name(udp_socket, addr.sin_addr.s_addr, AXIS_WIMP_PORT, devname, sizeof(devname)) == 0) + { + device[axis_no_devices++].addr = addr.sin_addr; + attach_axis(uri, devname, inet_ntoa(addr.sin_addr), pixma_devices); + } + close(udp_socket); + } + } + } + + if (!auto_detect) + return SANE_STATUS_GOOD; udp_socket = create_udp_socket(htonl(INADDR_ANY), &source_port); if (udp_socket < 0) return SANE_STATUS_IO_ERROR; - DBG(LOG_INFO, "source port=%d\n", source_port); + DBG(LOG_DEBUG, "source port=%d\n", source_port); /* send broadcast discover packets to all interfaces */ num_ifaces = send_broadcasts(udp_socket, source_port); @@ -450,21 +551,18 @@ sanei_axis_find_devices (const char **conf_devices, // struct axis_wimp_server_info *s_info = (void *)(packet + sizeof(struct axis_wimp_header)); DBG(LOG_INFO, "got reply from %s\n", inet_ntoa(from.sin_addr)); - /* get remote port */ - remote_port = ntohs(from.sin_port); - DBG(LOG_INFO, "remote port=%d\n", remote_port); if (header->type != (WIMP_SERVER_INFO | WIMP_REPLY)) { DBG(LOG_NOTICE, "Received invalid reply\n"); continue; } - get_device_name(udp_socket, from.sin_addr.s_addr, remote_port, devname, sizeof(devname)); - /* construct URI */ - sprintf (uri, "%s://%s:%d", "axis", inet_ntoa(from.sin_addr), AXIS_SCAN_PORT); + get_device_name(udp_socket, from.sin_addr.s_addr, ntohs(from.sin_port), devname, sizeof(devname)); + sprintf(uri, "axis://%s", inet_ntoa(from.sin_addr)); device[axis_no_devices++].addr = from.sin_addr; attach_axis(uri, devname, inet_ntoa(from.sin_addr), pixma_devices); } + close(udp_socket); return SANE_STATUS_GOOD; } @@ -472,41 +570,16 @@ sanei_axis_find_devices (const char **conf_devices, extern SANE_Status sanei_axis_open (SANE_String_Const devname, SANE_Int * dn) { - const char *uri_ip, *uri_port; - char ip[16]; - size_t ip_len; - int port = AXIS_SCAN_PORT; - struct in_addr addr; int i; char *username; struct sockaddr_in address; DBG(LOG_INFO, "%s(%s, %d)\n", __func__, devname, *dn); - if (strncmp(devname, "axis://", 7)) { - DBG(LOG_CRIT, "Invalid protocol in devname"); + if (parse_uri(devname, &address)) return SANE_STATUS_INVAL; - } - uri_ip = devname + 7; - - uri_port = strchr(uri_ip, ':'); - if (uri_port) { - sscanf(uri_port, ":%d", &port); - ip_len = uri_port - uri_ip; - } else - ip_len = strlen(uri_ip); - if (ip_len > sizeof(ip)) - ip_len = sizeof(ip); - strncpy(ip, uri_ip, ip_len); - ip[ip_len] = '\0'; - - if (inet_aton(ip, &addr) == 0) { - DBG(LOG_CRIT, "Invalid IP address in devname"); - return SANE_STATUS_INVAL; - } - DBG(LOG_INFO, "ip=%s, port=%d\n", inet_ntoa(addr), port); for (i = 0; i < axis_no_devices; i++) - if (device[i].addr.s_addr == addr.s_addr) { + if (device[i].addr.s_addr == address.sin_addr.s_addr) { DBG(LOG_INFO, "found device at position %d\n", i); *dn = i; /* connect */ @@ -515,10 +588,6 @@ sanei_axis_open (SANE_String_Const devname, SANE_Int * dn) perror("Unable to create TCP socket"); return SANE_STATUS_IO_ERROR; } - address.sin_family = AF_INET; - /* set TCP destination port and address */ - address.sin_port = htons(AXIS_SCAN_PORT); - address.sin_addr.s_addr = addr.s_addr; if (connect(tcp_socket, (struct sockaddr *) &address, sizeof(address)) < 0) { perror("Unable to connect"); return SANE_STATUS_IO_ERROR; @@ -542,7 +611,7 @@ sanei_axis_open (SANE_String_Const devname, SANE_Int * dn) return SANE_STATUS_GOOD; } -/*FIXME: add to table */ + return SANE_STATUS_INVAL; } From 94aa7b5057e49080297d89a10e7847cabbecaa01 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 9 Apr 2020 11:57:09 +0200 Subject: [PATCH 05/21] pixma: cleanup AXIS udp_socket handling Don't call connect() on UDP socket, use sendto() and recvfrom() properly --- backend/pixma/pixma_axis.c | 74 ++++++++++++++------------------------ 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 46685eb12..8da0690e9 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -116,7 +116,7 @@ static ssize_t receive_packet(int socket, void *packet, size_t len, struct socka } } -static ssize_t axis_send_wimp(int udp_socket, uint8_t cmd, void *data, uint16_t len, struct sockaddr *addr, socklen_t addrlen) { +static ssize_t axis_send_wimp(int udp_socket, struct sockaddr_in *addr, uint8_t cmd, void *data, uint16_t len) { uint8_t packet[MAX_PACKET_DATA_SIZE]; struct axis_wimp_header *header = (void *)packet; ssize_t ret; @@ -125,7 +125,7 @@ static ssize_t axis_send_wimp(int udp_socket, uint8_t cmd, void *data, uint16_t header->magic = 0x03; header->zero = 0x00; memcpy(packet + sizeof(struct axis_wimp_header), data, len); - ret = sendto(udp_socket, packet, sizeof(struct axis_wimp_header) + len, 0, addr, addrlen); + ret = sendto(udp_socket, packet, sizeof(struct axis_wimp_header) + len, 0, addr, sizeof(struct sockaddr_in)); if (ret != (int)sizeof(struct axis_wimp_header) + len) { DBG(LOG_CRIT, "Unable to send UDP packet\n"); return ret; @@ -134,23 +134,23 @@ static ssize_t axis_send_wimp(int udp_socket, uint8_t cmd, void *data, uint16_t return 0; } -static ssize_t axis_wimp_get(int udp_socket, uint16_t remote_port, uint8_t cmd, uint8_t idx, char *data_out, uint16_t len_out) { +static ssize_t axis_wimp_get(int udp_socket, struct sockaddr_in *addr, uint8_t cmd, uint8_t idx, char *data_out, uint16_t len_out) { ssize_t ret; uint16_t len; struct axis_wimp_get wimp_get; struct axis_wimp_header *reply = (void *)data_out; struct axis_wimp_get_reply *str = (void *)(data_out + sizeof(struct axis_wimp_header)); - wimp_get.port = cpu_to_le16(remote_port), + wimp_get.port = addr->sin_port, wimp_get.magic = 0x02, wimp_get.zero = 0; wimp_get.cmd = cmd, wimp_get.idx = idx, - ret = axis_send_wimp(udp_socket, WIMP_SERVER_STATUS, &wimp_get, sizeof(wimp_get), NULL, 0); + ret = axis_send_wimp(udp_socket, addr, WIMP_SERVER_STATUS, &wimp_get, sizeof(wimp_get)); if (ret) return ret; - ret = receive_packet(udp_socket, data_out, len_out, NULL); + ret = receive_packet(udp_socket, data_out, len_out, addr); if (ret < (int)sizeof(struct axis_wimp_header)) { DBG(LOG_NOTICE, "Received packet is too short\n"); return -1; @@ -199,29 +199,17 @@ static int create_udp_socket(uint32_t addr, uint16_t *source_port) { return udp_socket; } -static int get_server_status(int udp_socket, uint32_t addr, uint16_t remote_port) { +static int get_server_status(int udp_socket, struct sockaddr_in *addr) { char buf[MAX_PACKET_DATA_SIZE]; - struct sockaddr_in address; - - address.sin_family = AF_INET; - address.sin_port = htons(AXIS_WIMP_PORT); - address.sin_addr.s_addr = addr; - - /* connect the socket to this print server only */ - - if (connect(udp_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { - DBG(LOG_CRIT, "Unable to connect UDP socket\n"); - return -1; - } /* get device status (IDLE/BUSY) */ - if (axis_wimp_get(udp_socket, remote_port, WIMP_GET_STATUS, 1, buf, sizeof(buf))) + if (axis_wimp_get(udp_socket, addr, WIMP_GET_STATUS, 1, buf, sizeof(buf))) DBG(LOG_NOTICE, "Error getting device status\n"); DBG(LOG_INFO, "device status=%s\n", buf); /* get username if BUSY */ if (!strcmp((char *)buf, "BUSY_TXT")) { - if (axis_wimp_get(udp_socket, remote_port, WIMP_GET_STATUS, 2, buf, sizeof(buf))) + if (axis_wimp_get(udp_socket, addr, WIMP_GET_STATUS, 2, buf, sizeof(buf))) DBG(LOG_NOTICE, "Error getting user name\n"); DBG(LOG_INFO, "username=%s\n", buf); return 1; @@ -230,24 +218,12 @@ static int get_server_status(int udp_socket, uint32_t addr, uint16_t remote_port return 0; } -static int get_device_name(int udp_socket, uint32_t addr, uint16_t remote_port, char *devname, int devname_len) { +static int get_device_name(int udp_socket, struct sockaddr_in *addr, char *devname, int devname_len) { char buf[MAX_PACKET_DATA_SIZE]; - struct sockaddr_in address; - - address.sin_family = AF_INET; - address.sin_port = htons(AXIS_WIMP_PORT); - address.sin_addr.s_addr = addr; - - /* connect the socket to this print server only */ - - if (connect(udp_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { - DBG(LOG_CRIT, "Unable to connect UDP socket\n"); - return -1; - } buf[0] = '\0'; /* get device name */ - if (axis_wimp_get(udp_socket, remote_port, WIMP_GET_NAME, 1, buf, sizeof(buf))) + if (axis_wimp_get(udp_socket, addr, WIMP_GET_NAME, 1, buf, sizeof(buf))) { DBG(LOG_NOTICE, "Error getting device name\n"); return -1; @@ -272,7 +248,7 @@ static int send_discover(int udp_socket, uint32_t addr, uint16_t source_port) { get_info[0] = source_port & 0xff; get_info[1] = source_port >> 8; - ret = axis_send_wimp(udp_socket, WIMP_SERVER_INFO, get_info, sizeof(get_info), (struct sockaddr *)&address, sizeof(address)); + ret = axis_send_wimp(udp_socket, &address, WIMP_SERVER_INFO, get_info, sizeof(get_info)); if (ret) DBG(LOG_CRIT, "Unable to send discover packet\n"); @@ -489,6 +465,11 @@ sanei_axis_find_devices (const char **conf_devices, int udp_socket, num_ifaces; int auto_detect = 1, i; + udp_socket = create_udp_socket(htonl(INADDR_ANY), &source_port); + if (udp_socket < 0) + return SANE_STATUS_IO_ERROR; + DBG(LOG_DEBUG, "source port=%d\n", source_port); + /* parse config file */ if (conf_devices[0] != NULL) { @@ -496,6 +477,7 @@ sanei_axis_find_devices (const char **conf_devices, { /* networking=no may only occur on the first non-commented line */ DBG(LOG_DEBUG, "sanei_axis_find_devices: networking disabled in configuration file\n"); + close(udp_socket); return SANE_STATUS_GOOD; } for (i = 0; conf_devices[i] != NULL; i++) @@ -514,32 +496,28 @@ sanei_axis_find_devices (const char **conf_devices, if (axis_no_devices >= AXIS_NO_DEVICES) { DBG(LOG_INFO, "sanei_axis_find_devices: device limit %d reached\n", AXIS_NO_DEVICES); + close(udp_socket); return SANE_STATUS_NO_MEM; } struct sockaddr_in addr; if (parse_uri(uri, &addr)) continue; - udp_socket = create_udp_socket(htonl(INADDR_ANY), &source_port); - if (udp_socket < 0) - return SANE_STATUS_IO_ERROR; - if (get_device_name(udp_socket, addr.sin_addr.s_addr, AXIS_WIMP_PORT, devname, sizeof(devname)) == 0) + addr.sin_port = htons(AXIS_WIMP_PORT); + if (get_device_name(udp_socket, &addr, devname, sizeof(devname)) == 0) { device[axis_no_devices++].addr = addr.sin_addr; attach_axis(uri, devname, inet_ntoa(addr.sin_addr), pixma_devices); } - close(udp_socket); } } } if (!auto_detect) - return SANE_STATUS_GOOD; - - udp_socket = create_udp_socket(htonl(INADDR_ANY), &source_port); - if (udp_socket < 0) - return SANE_STATUS_IO_ERROR; - DBG(LOG_DEBUG, "source port=%d\n", source_port); + { + close(udp_socket); + return SANE_STATUS_GOOD; + } /* send broadcast discover packets to all interfaces */ num_ifaces = send_broadcasts(udp_socket, source_port); @@ -556,7 +534,7 @@ sanei_axis_find_devices (const char **conf_devices, continue; } - get_device_name(udp_socket, from.sin_addr.s_addr, ntohs(from.sin_port), devname, sizeof(devname)); + get_device_name(udp_socket, &from, devname, sizeof(devname)); sprintf(uri, "axis://%s", inet_ntoa(from.sin_addr)); device[axis_no_devices++].addr = from.sin_addr; From 3e96f8ccc19e49aa24209c692f2049f04e431ba4 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 9 Apr 2020 12:54:19 +0200 Subject: [PATCH 06/21] pixma: cleanup AXIS debug output --- backend/pixma/pixma_axis.c | 106 ++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 8da0690e9..2ae3f0105 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -64,6 +64,25 @@ static axis_device_t device[AXIS_NO_DEVICES]; static int axis_no_devices = 0; +static void +dbg_hexdump(int level, const SANE_Byte *data, size_t len) +{ +#define HEXDUMP_LINE 16 + char line[HEXDUMP_LINE * 3 + 1], *lp = line; + + if (level > DBG_LEVEL) + return; + + for (size_t i = 0; i < len; i++) + { + lp += sprintf(lp, "%02hhx ", data[i]); + if (i > 0 && i % (HEXDUMP_LINE - 1) == 0) + DBG(level, "%s\n", lp = line); + } + if (lp > line) + DBG(level, "%s\n", line); +} + extern void sanei_axis_init (void) { @@ -103,15 +122,9 @@ static ssize_t receive_packet(int socket, void *packet, size_t len, struct socka default: received = recvfrom(socket, packet, len, 0, (struct sockaddr *)from, &from_len); if (received < 0) { - DBG(LOG_CRIT, "Error receiving packet\n"); + DBG(LOG_NOTICE, "Error receiving packet\n"); return 0; } -/*#ifdef DEBUG - int i; - for (i = 0; i < received; i++) - fprintf(stderr, "%.2hhX ",((char *)packet)[i]); - fprintf(stderr, "\n"); -#endif*/ return received; } } @@ -127,7 +140,7 @@ static ssize_t axis_send_wimp(int udp_socket, struct sockaddr_in *addr, uint8_t memcpy(packet + sizeof(struct axis_wimp_header), data, len); ret = sendto(udp_socket, packet, sizeof(struct axis_wimp_header) + len, 0, addr, sizeof(struct sockaddr_in)); if (ret != (int)sizeof(struct axis_wimp_header) + len) { - DBG(LOG_CRIT, "Unable to send UDP packet\n"); + DBG(LOG_NOTICE, "Unable to send UDP packet\n"); return ret; } @@ -174,12 +187,12 @@ static int create_udp_socket(uint32_t addr, uint16_t *source_port) { udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if (udp_socket < 0) { - DBG(LOG_CRIT, "Unable to create UDP socket\n"); + DBG(LOG_NOTICE, "Unable to create UDP socket\n"); return -1; } if (setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable))) { - DBG(LOG_CRIT, "Unable to enable broadcast\n"); + DBG(LOG_NOTICE, "Unable to enable broadcast\n"); return -1; } @@ -187,7 +200,7 @@ static int create_udp_socket(uint32_t addr, uint16_t *source_port) { address.sin_port = 0; /* random */ address.sin_addr.s_addr = addr; if (bind(udp_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { - DBG(LOG_CRIT, "Unable to bind UDP socket\n"); + DBG(LOG_NOTICE, "Unable to bind UDP socket\n"); return -1; } @@ -250,7 +263,7 @@ static int send_discover(int udp_socket, uint32_t addr, uint16_t source_port) { ret = axis_send_wimp(udp_socket, &address, WIMP_SERVER_INFO, get_info, sizeof(get_info)); if (ret) - DBG(LOG_CRIT, "Unable to send discover packet\n"); + DBG(LOG_NOTICE, "Unable to send discover packet\n"); return ret; } @@ -260,7 +273,7 @@ static int send_broadcasts(int udp_socket, uint16_t source_port) { int num_sent = 0; if (getifaddrs(&ifaddr) == -1) { - DBG(LOG_CRIT, "Unable to obtain network interface list\n"); + DBG(LOG_NOTICE, "Unable to obtain network interface list\n"); return -1; } @@ -289,9 +302,7 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { header->type = AXIS_HDR_REQUEST; header->len = cpu_to_le16(len + sizeof(struct axis_cmd)); ret = send(tcp_socket, packet, sizeof(struct axis_header), 0); - for (int i = 0; i < ret; i++) - fprintf(stderr, "%02x ", packet[i]); - fprintf(stderr, "\n"); + dbg_hexdump(LOG_DEBUG2, packet, ret); if (ret < 0) { DBG(LOG_NOTICE, "Error sending packet\n"); return ret; @@ -302,9 +313,7 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { command->len = cpu_to_le16(len); memcpy(packet + sizeof(struct axis_cmd), data, len); ret = send(tcp_socket, packet, sizeof(struct axis_cmd) + len, 0); - for (int i = 0; i < ret; i++) - fprintf(stderr, "%02x ", packet[i]); - fprintf(stderr, "\n"); + dbg_hexdump(LOG_DEBUG2, packet, ret); if (ret < 0) { DBG(LOG_NOTICE, "Error sending packet\n"); return ret; @@ -319,7 +328,6 @@ int axis_recv(SANE_Int dn, SANE_Byte *data, size_t *len) { struct axis_header *header = (void *)packet; struct axis_reply *reply = (void *)packet; ssize_t ret, remaining; - int i; retry: /* AXIS sends 0x24 byte 15 seconds after end of scan, then repeats 3 more times each 5 seconds - the purpose is unknown, get rid of that */ @@ -333,53 +341,48 @@ retry: else break; if (count) { - fprintf(stderr, "discarded %d 0x24 bytes\n", count); + DBG(LOG_DEBUG, "discarded %d 0x24 bytes\n", count); recv(device[dn].tcp_socket, packet, count, 0); } ret = recv(device[dn].tcp_socket, packet, sizeof(struct axis_header), 0); if (ret < sizeof(struct axis_header)) { - perror("recv error!!!"); + DBG(LOG_NOTICE, "recv error\n"); return -1; } - fprintf(stderr, "got1: "); - for (unsigned int i = 0; i < sizeof(struct axis_header); i++) - fprintf(stderr, "%02x ", packet[i]); - fprintf(stderr, "\n"); + + DBG(LOG_DEBUG2, "got1:\n"); + dbg_hexdump(LOG_DEBUG2, packet, sizeof(struct axis_header)); if (header->type != AXIS_HDR_REPLY) { - fprintf(stderr, "not a reply!:"); - for (i = 0; i < ret; i++) - fprintf(stderr, "%02x ", packet[i]); - fprintf(stderr, "\n"); + DBG(LOG_CRIT, "not a reply!:"); + dbg_hexdump(LOG_CRIT, packet, ret); return -1; } *len = le16_to_cpu(header->len); - fprintf(stderr, "len=0x%lx\n", *len); + DBG(LOG_DEBUG, "len=0x%lx\n", *len); ret = recv(device[dn].tcp_socket, packet, *len, 0); if (ret < 512) { - fprintf(stderr, "got2: "); - for (i = 0; i < ret; i++) - fprintf(stderr, "%02x ", packet[i]); + DBG(LOG_DEBUG2, "got2:\n"); + dbg_hexdump(LOG_DEBUG2, packet, ret); } - fprintf(stderr, "\n"); *len = le16_to_cpu(reply->len); - if (reply->cmd == AXIS_CMD_UNKNOWN2) { /// interrupt??? - fprintf(stderr, "interrupt?????\n"); + if (reply->cmd == AXIS_CMD_UNKNOWN2) { + DBG(LOG_DEBUG, "interrupt\n"); memcpy(device[dn].int_data, packet + sizeof(struct axis_reply), *len); device[dn].int_size = *len; goto retry; } memcpy(data, packet + sizeof(struct axis_reply), ret - sizeof(struct axis_reply)); if (reply->status != 0) { - fprintf(stderr, "status=0x%x\n", le16_to_cpu(reply->status)); + DBG(LOG_CRIT, "status=0x%x\n", le16_to_cpu(reply->status)); return SANE_STATUS_IO_ERROR; } remaining = *len - (ret - sizeof(struct axis_reply)); data_pos = data + ret - sizeof(struct axis_reply); while (remaining > 0) { - fprintf(stderr, "remaining bytes: %ld\n", remaining); + DBG(LOG_DEBUG, "remaining bytes: %ld\n", remaining); ret = recv(device[dn].tcp_socket, data_pos, remaining, 0); remaining -= ret; data_pos += ret; @@ -423,7 +426,7 @@ parse_uri(const char *uri, struct sockaddr_in *address) int err = getaddrinfo(host, NULL, &hints, &result); if (err) { - DBG(LOG_INFO, "getaddrinfo failed: %s\n", gai_strerror(err)); + DBG(LOG_CRIT, "cannot resolve %s: %s\n", host, gai_strerror(err)); return -1; } struct sockaddr_in *addr = (struct sockaddr_in *) result->ai_addr; @@ -476,7 +479,7 @@ sanei_axis_find_devices (const char **conf_devices, if (strcmp(conf_devices[0], "networking=no") == 0) { /* networking=no may only occur on the first non-commented line */ - DBG(LOG_DEBUG, "sanei_axis_find_devices: networking disabled in configuration file\n"); + DBG(LOG_DEBUG, "%s: networking disabled in configuration file\n", __func__); close(udp_socket); return SANE_STATUS_GOOD; } @@ -485,17 +488,17 @@ sanei_axis_find_devices (const char **conf_devices, if (!strcmp(conf_devices[i], "auto_detection=no")) { auto_detect = 0; - DBG(LOG_DEBUG, "sanei_axis_find_devices: auto detection of network scanners disabled in configuration file\n"); + DBG(LOG_DEBUG, "%s: auto detection of network scanners disabled in configuration file\n", __func__); continue; } else { - DBG(LOG_DEBUG, "sanei_axis_find_devices: Adding scanner from pixma.conf: %s\n", conf_devices[i]); + DBG(LOG_DEBUG, "%s: Adding scanner from pixma.conf: %s\n", __func__, conf_devices[i]); strncpy(uri, conf_devices[i], sizeof(uri) - 1); uri[sizeof(uri) - 1] = '\0'; if (axis_no_devices >= AXIS_NO_DEVICES) { - DBG(LOG_INFO, "sanei_axis_find_devices: device limit %d reached\n", AXIS_NO_DEVICES); + DBG(LOG_INFO, "%s: device limit %d reached\n", __func__, AXIS_NO_DEVICES); close(udp_socket); return SANE_STATUS_NO_MEM; } @@ -563,11 +566,11 @@ sanei_axis_open (SANE_String_Const devname, SANE_Int * dn) /* connect */ int tcp_socket = socket(AF_INET, SOCK_STREAM, 0); if (tcp_socket < 0) { - perror("Unable to create TCP socket"); + DBG(LOG_NOTICE, "Unable to create TCP socket: %s\n", strerror(errno)); return SANE_STATUS_IO_ERROR; } if (connect(tcp_socket, (struct sockaddr *) &address, sizeof(address)) < 0) { - perror("Unable to connect"); + DBG(LOG_NOTICE, "Unable to connect: %s\n", strerror(errno)); return SANE_STATUS_IO_ERROR; } DBG(LOG_INFO, "connected\n"); @@ -613,16 +616,12 @@ extern SANE_Status sanei_axis_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) { DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); -// uint8_t buf_read[] = { 0x40, 0x00 }; uint16_t read_size = cpu_to_le16(*size); -// axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_READ, buf_read, sizeof(buf_read)); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_READ, &read_size, sizeof(read_size)); axis_recv(dn, buffer, size); ////FIXME - fprintf(stderr, "sanei_axis_read_bulk: "); + DBG(LOG_DEBUG2, "sanei_axis_read_bulk:\n"); if (*size < 512) - for (unsigned int i = 0; i < *size; i++) - fprintf(stderr, "%02x ", buffer[i]); - fprintf(stderr, "\n"); + dbg_hexdump(LOG_DEBUG2, buffer, *size); return SANE_STATUS_GOOD; } @@ -632,8 +631,6 @@ sanei_axis_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) SANE_Byte dummy_buf[MAX_PACKET_DATA_SIZE]; size_t dummy_len; DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); - fprintf(stderr, "sanei_axis_write_bulk: "); - fprintf(stderr, "\n"); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_WRITE, (void *) buffer, *size); axis_recv(dn, dummy_buf, &dummy_len); ////FIXME return SANE_STATUS_GOOD; @@ -649,5 +646,4 @@ sanei_axis_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) *size = device[dn].int_size; device[dn].int_size = 0; return SANE_STATUS_GOOD; -// return SANE_STATUS_EOF; } From 43eb737cdca3795603fe3fb473a62d3b8a01b64b Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 9 Apr 2020 15:35:52 +0200 Subject: [PATCH 07/21] pixma: fix signedness warning --- backend/pixma/pixma_axis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 2ae3f0105..5c02b4540 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -346,7 +346,7 @@ retry: } ret = recv(device[dn].tcp_socket, packet, sizeof(struct axis_header), 0); - if (ret < sizeof(struct axis_header)) { + if (ret < (ssize_t) sizeof(struct axis_header)) { DBG(LOG_NOTICE, "recv error\n"); return -1; } From 72f01d9bb6b25fbe0291ffe39a5ffa51bab09e64 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Wed, 15 Apr 2020 15:27:56 +0200 Subject: [PATCH 08/21] pixma: prevent buffer overflow Prevent buffer overflow when serial is too long --- backend/pixma/pixma_io_sanei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pixma/pixma_io_sanei.c b/backend/pixma/pixma_io_sanei.c index dd5051ef1..5238f91ef 100644 --- a/backend/pixma/pixma_io_sanei.c +++ b/backend/pixma/pixma_io_sanei.c @@ -185,7 +185,7 @@ attach_net (SANE_String_Const devname, SANE_String_Const makemodel, else { si->cfg = cfg; - sprintf(si->serial, "%s_%s", cfg->model, serial); + snprintf(si->serial, sizeof(si->serial), "%s_%s", cfg->model, serial); si -> interface = interface; si->next = first_scanner; first_scanner = si; From b765b16989a44c28cedbdc607279bf547706a39c Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 20 Apr 2020 12:06:01 +0200 Subject: [PATCH 09/21] pixma: mark busy AXIS device When an AXIS device is in BUSY state, add "BUSY username" to serial number. Haven't found any better way to do this in SANE. --- backend/pixma/pixma_axis.c | 102 +++++++++++++++++++---------- backend/pixma/pixma_axis_private.h | 3 + 2 files changed, 70 insertions(+), 35 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 5c02b4540..543d77c42 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -176,7 +176,7 @@ static ssize_t axis_wimp_get(int udp_socket, struct sockaddr_in *addr, uint8_t c memmove(data_out, data_out + sizeof(struct axis_wimp_header) + sizeof(struct axis_wimp_get_reply), len); data_out[len] = '\0'; - return 0; + return len; } static int create_udp_socket(uint32_t addr, uint16_t *source_port) { @@ -212,23 +212,36 @@ static int create_udp_socket(uint32_t addr, uint16_t *source_port) { return udp_socket; } -static int get_server_status(int udp_socket, struct sockaddr_in *addr) { +static int get_server_status(int udp_socket, struct sockaddr_in *addr, char *user) { char buf[MAX_PACKET_DATA_SIZE]; /* get device status (IDLE/BUSY) */ - if (axis_wimp_get(udp_socket, addr, WIMP_GET_STATUS, 1, buf, sizeof(buf))) - DBG(LOG_NOTICE, "Error getting device status\n"); + if (axis_wimp_get(udp_socket, addr, WIMP_GET_STATUS, 1, buf, sizeof(buf)) < 0) + { + DBG(LOG_NOTICE, "Error getting device status\n"); + return -1; + } DBG(LOG_INFO, "device status=%s\n", buf); + if (!strncmp(buf, "IDLE_TXT", 8)) + return 0; /* get username if BUSY */ - if (!strcmp((char *)buf, "BUSY_TXT")) { - if (axis_wimp_get(udp_socket, addr, WIMP_GET_STATUS, 2, buf, sizeof(buf))) - DBG(LOG_NOTICE, "Error getting user name\n"); - DBG(LOG_INFO, "username=%s\n", buf); - return 1; - } + if (!strcmp(buf, "BUSY_TXT")) + { + if (axis_wimp_get(udp_socket, addr, WIMP_GET_STATUS, 2, buf, sizeof(buf)) < 0) + { + DBG(LOG_NOTICE, "Error getting user name\n"); + return -1; + } + DBG(LOG_INFO, "username=%s\n", buf); + strncpy(user, buf, AXIS_USERNAME_LEN); + buf[AXIS_USERNAME_LEN - 1] = '\0'; + return 1; + } - return 0; + DBG(LOG_CRIT, "Invalid server status: %s\n", buf); + + return -1; } static int get_device_name(int udp_socket, struct sockaddr_in *addr, char *devname, int devname_len) { @@ -236,7 +249,7 @@ static int get_device_name(int udp_socket, struct sockaddr_in *addr, char *devna buf[0] = '\0'; /* get device name */ - if (axis_wimp_get(udp_socket, addr, WIMP_GET_NAME, 1, buf, sizeof(buf))) + if (axis_wimp_get(udp_socket, addr, WIMP_GET_NAME, 1, buf, sizeof(buf)) < 0) { DBG(LOG_NOTICE, "Error getting device name\n"); return -1; @@ -440,6 +453,46 @@ parse_uri(const char *uri, struct sockaddr_in *address) return 0; } +SANE_Status +add_scanner(int udp_socket, const char *uri, + SANE_Status (*attach_axis) + (SANE_String_Const devname, + SANE_String_Const makemodel, + SANE_String_Const serial, + const struct pixma_config_t * + const pixma_devices[]), + const struct pixma_config_t *const pixma_devices[]) +{ + char devname[256]; + char serial[AXIS_SERIAL_LEN]; + char user[AXIS_USERNAME_LEN]; + + if (axis_no_devices >= AXIS_NO_DEVICES) + { + DBG(LOG_INFO, "%s: device limit %d reached\n", __func__, AXIS_NO_DEVICES); + return SANE_STATUS_NO_MEM; + } + + struct sockaddr_in addr; + if (parse_uri(uri, &addr)) + return -1; + + addr.sin_port = htons(AXIS_WIMP_PORT); + if (get_device_name(udp_socket, &addr, devname, sizeof(devname)) == 0) + { + strcpy(serial, inet_ntoa(addr.sin_addr)); + int status = get_server_status(udp_socket, &addr, user); + if (status < 0) + return -1; + if (status == 1) + snprintf(serial, sizeof(serial), "%s BUSY %s", inet_ntoa(addr.sin_addr), user); + device[axis_no_devices++].addr = addr.sin_addr; + attach_axis(uri, devname, serial, pixma_devices); + } + + return 0; +} + /** * Find AXIS printservers with Canon support @@ -460,7 +513,6 @@ sanei_axis_find_devices (const char **conf_devices, const pixma_devices[]), const struct pixma_config_t *const pixma_devices[]) { - char devname[256]; char uri[256]; uint8_t packet[MAX_PACKET_DATA_SIZE]; struct sockaddr_in from; @@ -494,24 +546,7 @@ sanei_axis_find_devices (const char **conf_devices, else { DBG(LOG_DEBUG, "%s: Adding scanner from pixma.conf: %s\n", __func__, conf_devices[i]); - strncpy(uri, conf_devices[i], sizeof(uri) - 1); - uri[sizeof(uri) - 1] = '\0'; - if (axis_no_devices >= AXIS_NO_DEVICES) - { - DBG(LOG_INFO, "%s: device limit %d reached\n", __func__, AXIS_NO_DEVICES); - close(udp_socket); - return SANE_STATUS_NO_MEM; - } - - struct sockaddr_in addr; - if (parse_uri(uri, &addr)) - continue; - addr.sin_port = htons(AXIS_WIMP_PORT); - if (get_device_name(udp_socket, &addr, devname, sizeof(devname)) == 0) - { - device[axis_no_devices++].addr = addr.sin_addr; - attach_axis(uri, devname, inet_ntoa(addr.sin_addr), pixma_devices); - } + add_scanner(udp_socket, conf_devices[i], attach_axis, pixma_devices); } } } @@ -537,11 +572,8 @@ sanei_axis_find_devices (const char **conf_devices, continue; } - get_device_name(udp_socket, &from, devname, sizeof(devname)); sprintf(uri, "axis://%s", inet_ntoa(from.sin_addr)); - - device[axis_no_devices++].addr = from.sin_addr; - attach_axis(uri, devname, inet_ntoa(from.sin_addr), pixma_devices); + add_scanner(udp_socket, uri, attach_axis, pixma_devices); } close(udp_socket); diff --git a/backend/pixma/pixma_axis_private.h b/backend/pixma/pixma_axis_private.h index de4edba19..1f606ac2a 100644 --- a/backend/pixma/pixma_axis_private.h +++ b/backend/pixma/pixma_axis_private.h @@ -44,6 +44,9 @@ struct axis_wimp_get_reply { uint16_t unknown; } __attribute__((__packed__)); +#define AXIS_SERIAL_LEN 32 /* arbitrary limit */ +#define AXIS_USERNAME_LEN 32 /* arbitrary limit */ + #define AXIS_SCAN_PORT 49152 /* TCP port for scan data */ #define AXIS_HDR_REQUEST 0x27 From d1cdf7a25d29b69f6f4d084cdc6e200bd29ec7f0 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 20 Apr 2020 13:08:07 +0200 Subject: [PATCH 10/21] pixma: honor BUSY status of AXIS devices during open Check device status before connecting to a device and abort if BUSY. --- backend/pixma/pixma_axis.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 543d77c42..38aec5511 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -207,7 +207,8 @@ static int create_udp_socket(uint32_t addr, uint16_t *source_port) { /* get assigned source port */ sock_len = sizeof(address); getsockname(udp_socket, (struct sockaddr *)&address, &sock_len); - *source_port = ntohs(address.sin_port); + if (source_port) + *source_port = ntohs(address.sin_port); return udp_socket; } @@ -464,8 +465,8 @@ add_scanner(int udp_socket, const char *uri, const struct pixma_config_t *const pixma_devices[]) { char devname[256]; - char serial[AXIS_SERIAL_LEN]; - char user[AXIS_USERNAME_LEN]; + char serial[AXIS_SERIAL_LEN + 1]; + char user[AXIS_USERNAME_LEN + 1]; if (axis_no_devices >= AXIS_NO_DEVICES) { @@ -595,6 +596,22 @@ sanei_axis_open (SANE_String_Const devname, SANE_Int * dn) if (device[i].addr.s_addr == address.sin_addr.s_addr) { DBG(LOG_INFO, "found device at position %d\n", i); *dn = i; + /* check status first to make sure the device is not BUSY */ + int udp_socket = create_udp_socket(htonl(INADDR_ANY), NULL); + if (udp_socket < 0) + return SANE_STATUS_IO_ERROR; + struct sockaddr_in addr = address; + addr.sin_port = htons(AXIS_WIMP_PORT); + char user[AXIS_USERNAME_LEN + 1]; + int status = get_server_status(udp_socket, &addr, user); + close(udp_socket); + if (status < 0) + return SANE_STATUS_IO_ERROR; + if (status == 1) + { + DBG(LOG_CRIT, "Device is BUSY, user %s\n", user); + return SANE_STATUS_IO_ERROR; + } /* connect */ int tcp_socket = socket(AF_INET, SOCK_STREAM, 0); if (tcp_socket < 0) { From 91a7b84aa4d0775c14f95d806a87924971fefdb1 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 28 Apr 2020 11:37:10 +0200 Subject: [PATCH 11/21] pixma: fix AXIS endian conversions Tested on big-endian MIPS in QEMU --- backend/pixma/pixma_axis.c | 22 ++++++++++------------ backend/pixma/pixma_axis_private.h | 3 --- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 38aec5511..e509a1058 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -154,7 +154,7 @@ static ssize_t axis_wimp_get(int udp_socket, struct sockaddr_in *addr, uint8_t c struct axis_wimp_header *reply = (void *)data_out; struct axis_wimp_get_reply *str = (void *)(data_out + sizeof(struct axis_wimp_header)); - wimp_get.port = addr->sin_port, + wimp_get.port = htole16(ntohs(addr->sin_port)), /* network order -> LE */ wimp_get.magic = 0x02, wimp_get.zero = 0; wimp_get.cmd = cmd, @@ -172,7 +172,7 @@ static ssize_t axis_wimp_get(int udp_socket, struct sockaddr_in *addr, uint8_t c DBG(LOG_NOTICE, "Received invalid reply\n"); return -1; } - len = le16_to_cpu(str->len) - 2; + len = le16toh(str->len) - 2; memmove(data_out, data_out + sizeof(struct axis_wimp_header) + sizeof(struct axis_wimp_get_reply), len); data_out[len] = '\0'; @@ -266,16 +266,14 @@ static int get_device_name(int udp_socket, struct sockaddr_in *addr, char *devna static int send_discover(int udp_socket, uint32_t addr, uint16_t source_port) { int ret; struct sockaddr_in address; - uint8_t get_info[2]; address.sin_family = AF_INET; address.sin_port = htons(AXIS_WIMP_PORT); address.sin_addr.s_addr = addr; - get_info[0] = source_port & 0xff; - get_info[1] = source_port >> 8; + source_port = htole16(source_port); - ret = axis_send_wimp(udp_socket, &address, WIMP_SERVER_INFO, get_info, sizeof(get_info)); + ret = axis_send_wimp(udp_socket, &address, WIMP_SERVER_INFO, &source_port, sizeof(source_port)); if (ret) DBG(LOG_NOTICE, "Unable to send discover packet\n"); @@ -314,7 +312,7 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { DBG(LOG_INFO, "%s(0x%02x, %d)\n", __func__, cmd, len); header->type = AXIS_HDR_REQUEST; - header->len = cpu_to_le16(len + sizeof(struct axis_cmd)); + header->len = htole32(len + sizeof(struct axis_cmd)); ret = send(tcp_socket, packet, sizeof(struct axis_header), 0); dbg_hexdump(LOG_DEBUG2, packet, ret); if (ret < 0) { @@ -324,7 +322,7 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { struct axis_cmd *command = (void *)packet; command->cmd = cmd; - command->len = cpu_to_le16(len); + command->len = htole32(len); memcpy(packet + sizeof(struct axis_cmd), data, len); ret = send(tcp_socket, packet, sizeof(struct axis_cmd) + len, 0); dbg_hexdump(LOG_DEBUG2, packet, ret); @@ -373,14 +371,14 @@ retry: dbg_hexdump(LOG_CRIT, packet, ret); return -1; } - *len = le16_to_cpu(header->len); + *len = le32toh(header->len); DBG(LOG_DEBUG, "len=0x%lx\n", *len); ret = recv(device[dn].tcp_socket, packet, *len, 0); if (ret < 512) { DBG(LOG_DEBUG2, "got2:\n"); dbg_hexdump(LOG_DEBUG2, packet, ret); } - *len = le16_to_cpu(reply->len); + *len = le32toh(reply->len); if (reply->cmd == AXIS_CMD_UNKNOWN2) { DBG(LOG_DEBUG, "interrupt\n"); memcpy(device[dn].int_data, packet + sizeof(struct axis_reply), *len); @@ -389,7 +387,7 @@ retry: } memcpy(data, packet + sizeof(struct axis_reply), ret - sizeof(struct axis_reply)); if (reply->status != 0) { - DBG(LOG_CRIT, "status=0x%x\n", le16_to_cpu(reply->status)); + DBG(LOG_CRIT, "status=0x%x\n", le32toh(reply->status)); return SANE_STATUS_IO_ERROR; } @@ -665,7 +663,7 @@ extern SANE_Status sanei_axis_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) { DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); - uint16_t read_size = cpu_to_le16(*size); + uint16_t read_size = htole16(*size); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_READ, &read_size, sizeof(read_size)); axis_recv(dn, buffer, size); ////FIXME DBG(LOG_DEBUG2, "sanei_axis_read_bulk:\n"); diff --git a/backend/pixma/pixma_axis_private.h b/backend/pixma/pixma_axis_private.h index 1f606ac2a..ab24b2a2f 100644 --- a/backend/pixma/pixma_axis_private.h +++ b/backend/pixma/pixma_axis_private.h @@ -10,9 +10,6 @@ #define AXIS_WIMP_PORT 10260 /* UDP port for discovery */ -#define cpu_to_le16(x) (x) -#define le16_to_cpu(x) (x) - #define WIMP_SERVER_INFO 0x24 #define WIMP_SERVER_STATUS 0x30 #define WIMP_REPLY (1 << 0) From 040f6a60e04f0718145e2c5e29abf1b0c968f59e Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 4 May 2020 15:05:58 +0200 Subject: [PATCH 12/21] pixma: print size_t portably in AXIS Use %z to print size_t variables --- backend/pixma/pixma_axis.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index e509a1058..b469889e9 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -372,7 +372,7 @@ retry: return -1; } *len = le32toh(header->len); - DBG(LOG_DEBUG, "len=0x%lx\n", *len); + DBG(LOG_DEBUG, "len=0x%zx\n", *len); ret = recv(device[dn].tcp_socket, packet, *len, 0); if (ret < 512) { DBG(LOG_DEBUG2, "got2:\n"); @@ -394,7 +394,7 @@ retry: remaining = *len - (ret - sizeof(struct axis_reply)); data_pos = data + ret - sizeof(struct axis_reply); while (remaining > 0) { - DBG(LOG_DEBUG, "remaining bytes: %ld\n", remaining); + DBG(LOG_DEBUG, "remaining bytes: %zd\n", remaining); ret = recv(device[dn].tcp_socket, data_pos, remaining, 0); remaining -= ret; data_pos += ret; @@ -662,7 +662,7 @@ sanei_axis_set_timeout (SANE_Int dn, SANE_Int timeout) extern SANE_Status sanei_axis_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) { - DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); + DBG(LOG_INFO, "%s(%d, %p, %zd)\n", __func__, dn, buffer, *size); uint16_t read_size = htole16(*size); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_READ, &read_size, sizeof(read_size)); axis_recv(dn, buffer, size); ////FIXME @@ -677,7 +677,7 @@ sanei_axis_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) { SANE_Byte dummy_buf[MAX_PACKET_DATA_SIZE]; size_t dummy_len; - DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); + DBG(LOG_INFO, "%s(%d, %p, %zd)\n", __func__, dn, buffer, *size); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_WRITE, (void *) buffer, *size); axis_recv(dn, dummy_buf, &dummy_len); ////FIXME return SANE_STATUS_GOOD; @@ -686,7 +686,7 @@ sanei_axis_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) extern SANE_Status sanei_axis_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) { - DBG(LOG_INFO, "%s(%d, %p, %ld)\n", __func__, dn, buffer, *size); + DBG(LOG_INFO, "%s(%d, %p, %zd)\n", __func__, dn, buffer, *size); if (!device[dn].int_size) return SANE_STATUS_EOF; memcpy(buffer, device[dn].int_data, device[dn].int_size); From e2e8893ab77bfd979c3548db410e7984e8d9c4a8 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 4 May 2020 15:53:11 +0200 Subject: [PATCH 13/21] pixma: change AXIS backend name to pixma_axis --- backend/pixma/pixma_axis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index b469889e9..ba0be82af 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -1,5 +1,5 @@ #undef BACKEND_NAME -#define BACKEND_NAME axis +#define BACKEND_NAME pixma_axis #include "../../include/sane/config.h" #include "../../include/sane/sane.h" From 89ad855ec9b1eec29991a8fbf38920a769cf98ad Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 4 May 2020 16:28:12 +0200 Subject: [PATCH 14/21] pixma: disable AXIS autodetection by default Require manual configuration in pixma.conf to enable AXIS autodetection --- backend/pixma/pixma_axis.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index ba0be82af..70687fbe8 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -517,7 +517,7 @@ sanei_axis_find_devices (const char **conf_devices, struct sockaddr_in from; uint16_t source_port; int udp_socket, num_ifaces; - int auto_detect = 1, i; + int auto_detect = 0, i; udp_socket = create_udp_socket(htonl(INADDR_ANY), &source_port); if (udp_socket < 0) @@ -536,10 +536,9 @@ sanei_axis_find_devices (const char **conf_devices, } for (i = 0; conf_devices[i] != NULL; i++) { - if (!strcmp(conf_devices[i], "auto_detection=no")) + if (!strcmp(conf_devices[i], "axis_auto_detection=yes")) { - auto_detect = 0; - DBG(LOG_DEBUG, "%s: auto detection of network scanners disabled in configuration file\n", __func__); + auto_detect = 1; continue; } else @@ -552,6 +551,7 @@ sanei_axis_find_devices (const char **conf_devices, if (!auto_detect) { + DBG(LOG_DEBUG, "%s: auto detection of AXIS network scanners not enabled in configuration file\n", __func__); close(udp_socket); return SANE_STATUS_GOOD; } From 72802d9519058e8789244a77a9b810618d6d34e9 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 5 May 2020 12:29:38 +0200 Subject: [PATCH 15/21] pixma: Update pixma.conf with AXIS support --- backend/pixma.conf.in | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/pixma.conf.in b/backend/pixma.conf.in index d6184b493..1e573f21e 100644 --- a/backend/pixma.conf.in +++ b/backend/pixma.conf.in @@ -5,6 +5,7 @@ # Uncomment the following line: # networking=no # +### BJNP/MFNP configuration # bjnp-timeout=5000 # Specify the timeout (in ms) to be used for all the folllowing # scanners. @@ -30,3 +31,13 @@ # # Example using for a scanner using mfnp including the optional timeout: # mfnp://scanner.bad-network.org/timeout=1500 +# +# +### AXIS configuration +# Uncomment the following line to enable auto detection of AXIS network +# scanners (on the same subnet): +# axis_auto_detection=yes +# +# Or add a scanner manually: +# axis://myscanner.my.domain +# axis://192.168.0.123 From 48d2f18833469c55a5d984a70c1c8d855aadb6ac Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 5 May 2020 13:20:57 +0200 Subject: [PATCH 16/21] pixma: replace if/else/else with switch --- backend/pixma/pixma_io_sanei.c | 59 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/backend/pixma/pixma_io_sanei.c b/backend/pixma/pixma_io_sanei.c index 5238f91ef..e85dfb31e 100644 --- a/backend/pixma/pixma_io_sanei.c +++ b/backend/pixma/pixma_io_sanei.c @@ -542,22 +542,21 @@ pixma_write (pixma_io_t * io, const void *cmd, unsigned len) size_t count = len; int error; - if (io->interface == INT_BJNP) - { - sanei_bjnp_set_timeout (io->dev, PIXMA_BULKOUT_TIMEOUT); - error = map_error (sanei_bjnp_write_bulk (io->dev, cmd, &count)); - } - else if (io->interface == INT_AXIS) - { - sanei_axis_set_timeout (io->dev, PIXMA_BULKOUT_TIMEOUT); - error = map_error (sanei_axis_write_bulk (io->dev, cmd, &count)); - } - else + switch (io->interface) { + case INT_BJNP: + sanei_bjnp_set_timeout (io->dev, PIXMA_BULKOUT_TIMEOUT); + error = map_error (sanei_bjnp_write_bulk (io->dev, cmd, &count)); + break; + case INT_AXIS: + sanei_axis_set_timeout (io->dev, PIXMA_BULKOUT_TIMEOUT); + error = map_error (sanei_axis_write_bulk (io->dev, cmd, &count)); + break; + default: #ifdef HAVE_SANEI_USB_SET_TIMEOUT - sanei_usb_set_timeout (PIXMA_BULKOUT_TIMEOUT); + sanei_usb_set_timeout (PIXMA_BULKOUT_TIMEOUT); #endif - error = map_error (sanei_usb_write_bulk (io->dev, cmd, &count)); + error = map_error (sanei_usb_write_bulk (io->dev, cmd, &count)); } if (error == PIXMA_EIO) error = PIXMA_ETIMEDOUT; /* FIXME: SANE doesn't have ETIMEDOUT!! */ @@ -579,18 +578,17 @@ pixma_read (pixma_io_t * io, void *buf, unsigned size) size_t count = size; int error; - if (io-> interface == INT_BJNP) - { - sanei_bjnp_set_timeout (io->dev, PIXMA_BULKIN_TIMEOUT); - error = map_error (sanei_bjnp_read_bulk (io->dev, buf, &count)); - } - else if (io-> interface == INT_AXIS) - { - sanei_axis_set_timeout (io->dev, PIXMA_BULKIN_TIMEOUT); - error = map_error (sanei_axis_read_bulk (io->dev, buf, &count)); - } - else + switch (io->interface) { + case INT_BJNP: + sanei_bjnp_set_timeout (io->dev, PIXMA_BULKIN_TIMEOUT); + error = map_error (sanei_bjnp_read_bulk (io->dev, buf, &count)); + break; + case INT_AXIS: + sanei_axis_set_timeout (io->dev, PIXMA_BULKIN_TIMEOUT); + error = map_error (sanei_axis_read_bulk (io->dev, buf, &count)); + break; + default: #ifdef HAVE_SANEI_USB_SET_TIMEOUT sanei_usb_set_timeout (PIXMA_BULKIN_TIMEOUT); #endif @@ -616,18 +614,17 @@ pixma_wait_interrupt (pixma_io_t * io, void *buf, unsigned size, int timeout) timeout = INT_MAX; else if (timeout < 100) timeout = 100; - if (io-> interface == INT_BJNP) + switch (io->interface) { + case INT_BJNP: sanei_bjnp_set_timeout (io->dev, timeout); error = map_error (sanei_bjnp_read_int (io->dev, buf, &count)); - } - else if (io-> interface == INT_AXIS) - { + break; + case INT_AXIS: sanei_axis_set_timeout (io->dev, timeout); error = map_error (sanei_axis_read_int (io->dev, buf, &count)); - } - else - { + break; + default: #ifdef HAVE_SANEI_USB_SET_TIMEOUT sanei_usb_set_timeout (timeout); #endif From c41455dd19df53502ca8afa14ca5102bb8979b06 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 5 May 2020 16:47:53 +0200 Subject: [PATCH 17/21] pixma: allow NULL parameters in axis_recv Allow NULL parameters in axis_recv to remove dummy buffers --- backend/pixma/pixma_axis.c | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 70687fbe8..9cb003309 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -334,12 +334,12 @@ int axis_send_cmd(int tcp_socket, uint8_t cmd, void *data, uint16_t len) { return 0; } -int axis_recv(SANE_Int dn, SANE_Byte *data, size_t *len) { +int axis_recv(SANE_Int dn, SANE_Byte *data, size_t *data_len) { uint8_t packet[MAX_PACKET_DATA_SIZE]; uint8_t *data_pos; struct axis_header *header = (void *)packet; struct axis_reply *reply = (void *)packet; - ssize_t ret, remaining; + ssize_t ret, len, remaining; retry: /* AXIS sends 0x24 byte 15 seconds after end of scan, then repeats 3 more times each 5 seconds - the purpose is unknown, get rid of that */ @@ -371,27 +371,32 @@ retry: dbg_hexdump(LOG_CRIT, packet, ret); return -1; } - *len = le32toh(header->len); - DBG(LOG_DEBUG, "len=0x%zx\n", *len); - ret = recv(device[dn].tcp_socket, packet, *len, 0); + len = le32toh(header->len); + DBG(LOG_DEBUG, "len=0x%zx\n", len); + ret = recv(device[dn].tcp_socket, packet, len, 0); if (ret < 512) { DBG(LOG_DEBUG2, "got2:\n"); dbg_hexdump(LOG_DEBUG2, packet, ret); } - *len = le32toh(reply->len); + len = le32toh(reply->len); if (reply->cmd == AXIS_CMD_UNKNOWN2) { DBG(LOG_DEBUG, "interrupt\n"); - memcpy(device[dn].int_data, packet + sizeof(struct axis_reply), *len); - device[dn].int_size = *len; + memcpy(device[dn].int_data, packet + sizeof(struct axis_reply), len); + device[dn].int_size = len; goto retry; } - memcpy(data, packet + sizeof(struct axis_reply), ret - sizeof(struct axis_reply)); + if (data) + memcpy(data, packet + sizeof(struct axis_reply), ret - sizeof(struct axis_reply)); + if (data_len) + *data_len = len; if (reply->status != 0) { DBG(LOG_CRIT, "status=0x%x\n", le32toh(reply->status)); return SANE_STATUS_IO_ERROR; } - remaining = *len - (ret - sizeof(struct axis_reply)); + if (!data) + return 0; + remaining = len - (ret - sizeof(struct axis_reply)); data_pos = data + ret - sizeof(struct axis_reply); while (remaining > 0) { DBG(LOG_DEBUG, "remaining bytes: %zd\n", remaining); @@ -626,16 +631,15 @@ sanei_axis_open (SANE_String_Const devname, SANE_Int * dn) username = getusername(); axis_send_cmd(tcp_socket, AXIS_CMD_CONNECT, username, strlen(username) + 1); - SANE_Byte dummy_buf[MAX_PACKET_DATA_SIZE]; - size_t dummy_len; - axis_recv(i, dummy_buf, &dummy_len); + /* server replies with USB descriptor but we ignore it */ + axis_recv(i, NULL, NULL); uint8_t timeout[] = { 0x0e, 0x01, 0x00, 0x00 }; axis_send_cmd(tcp_socket, AXIS_CMD_UNKNOWN3, timeout, sizeof(timeout)); - axis_recv(i, dummy_buf, &dummy_len); + axis_recv(i, NULL, NULL); axis_send_cmd(tcp_socket, AXIS_CMD_UNKNOWN, NULL, 0); - axis_recv(i, dummy_buf, &dummy_len); + axis_recv(i, NULL, NULL); return SANE_STATUS_GOOD; } @@ -665,7 +669,7 @@ sanei_axis_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) DBG(LOG_INFO, "%s(%d, %p, %zd)\n", __func__, dn, buffer, *size); uint16_t read_size = htole16(*size); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_READ, &read_size, sizeof(read_size)); - axis_recv(dn, buffer, size); ////FIXME + axis_recv(dn, buffer, size); DBG(LOG_DEBUG2, "sanei_axis_read_bulk:\n"); if (*size < 512) dbg_hexdump(LOG_DEBUG2, buffer, *size); @@ -675,11 +679,9 @@ sanei_axis_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) extern SANE_Status sanei_axis_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) { - SANE_Byte dummy_buf[MAX_PACKET_DATA_SIZE]; - size_t dummy_len; DBG(LOG_INFO, "%s(%d, %p, %zd)\n", __func__, dn, buffer, *size); axis_send_cmd(device[dn].tcp_socket, AXIS_CMD_WRITE, (void *) buffer, *size); - axis_recv(dn, dummy_buf, &dummy_len); ////FIXME + axis_recv(dn, NULL, NULL); return SANE_STATUS_GOOD; } From f7dc5eb0728695b4a38b25bcb5f4a0438c6c765f Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Wed, 6 May 2020 12:58:20 +0200 Subject: [PATCH 18/21] pixma: display AXIS server name in debug messages --- backend/pixma/pixma_axis.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 9cb003309..3f20686ac 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -568,13 +568,14 @@ sanei_axis_find_devices (const char **conf_devices, /* wait for response packets */ while (receive_packet(udp_socket, packet, sizeof(packet), &from) != 0) { struct axis_wimp_header *header = (void *)packet; -// struct axis_wimp_server_info *s_info = (void *)(packet + sizeof(struct axis_wimp_header)); + struct axis_wimp_server_info *s_info = (void *)(packet + sizeof(struct axis_wimp_header)); DBG(LOG_INFO, "got reply from %s\n", inet_ntoa(from.sin_addr)); if (header->type != (WIMP_SERVER_INFO | WIMP_REPLY)) { DBG(LOG_NOTICE, "Received invalid reply\n"); continue; } + DBG(LOG_INFO, "server name=%s\n", s_info->name); sprintf(uri, "axis://%s", inet_ntoa(from.sin_addr)); add_scanner(udp_socket, uri, attach_axis, pixma_devices); From 18ddb14b1faf7711bef40554c259c4ad9f6af87c Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Wed, 6 May 2020 15:00:56 +0200 Subject: [PATCH 19/21] pixma: silence AXIS gcc string truncation warning --- backend/pixma/pixma_axis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 3f20686ac..e489c5975 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -468,7 +468,7 @@ add_scanner(int udp_socket, const char *uri, const struct pixma_config_t *const pixma_devices[]) { char devname[256]; - char serial[AXIS_SERIAL_LEN + 1]; + char serial[2 * AXIS_SERIAL_LEN]; /* 2* to silence gcc truncation warning */ char user[AXIS_USERNAME_LEN + 1]; if (axis_no_devices >= AXIS_NO_DEVICES) From d651e44192c09628d8856debe9bab9cec7c38b15 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 31 Jul 2020 13:47:58 +0200 Subject: [PATCH 20/21] pixma: Log unsupported scanner type in BJNP and AXIS --- backend/pixma/pixma_axis.c | 11 ++++++++++- backend/pixma/pixma_bjnp.c | 3 +++ backend/pixma/pixma_io_sanei.c | 5 +---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index e489c5975..246c97035 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -491,7 +491,16 @@ add_scanner(int udp_socket, const char *uri, if (status == 1) snprintf(serial, sizeof(serial), "%s BUSY %s", inet_ntoa(addr.sin_addr), user); device[axis_no_devices++].addr = addr.sin_addr; - attach_axis(uri, devname, serial, pixma_devices); + switch (attach_axis(uri, devname, serial, pixma_devices)) + { + case SANE_STATUS_GOOD: + break; + case SANE_STATUS_INVAL: + DBG(LOG_CRIT, "add_scanner: Scanner %s is not supported, model is unknown! Please report upstream\n", devname); + break; + default: + DBG(LOG_CRIT, "add_scanner: unexpected error (out of memory?)\n"); + } } return 0; diff --git a/backend/pixma/pixma_bjnp.c b/backend/pixma/pixma_bjnp.c index 2c3fc09d1..dc374bfd0 100644 --- a/backend/pixma/pixma_bjnp.c +++ b/backend/pixma/pixma_bjnp.c @@ -1845,6 +1845,9 @@ static void add_scanner(SANE_Int *dev_no, PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: New scanner added: %s, serial %s, mac address: %s.\n", uri, serial, device[*dev_no].mac_address)); break; + case SANE_STATUS_INVAL: + PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: Scanner %s is not supported, model is unknown! Please report upstream\n", makemodel)); + break; default: PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: unexpected error (out of memory?), adding %s\n", makemodel)); } diff --git a/backend/pixma/pixma_io_sanei.c b/backend/pixma/pixma_io_sanei.c index e85dfb31e..e83c71067 100644 --- a/backend/pixma/pixma_io_sanei.c +++ b/backend/pixma/pixma_io_sanei.c @@ -178,10 +178,7 @@ attach_net (SANE_String_Const devname, SANE_String_Const makemodel, if (!si->devname) return SANE_STATUS_NO_MEM; if ((cfg = lookup_scanner(makemodel, pixma_devices)) == (struct pixma_config_t *)NULL) - { - pixma_dbg (0, "attach_net: Scanner %s is not supported, model is unknown! Please report upstream\n", makemodel); - error = SANE_STATUS_INVAL; - } + error = SANE_STATUS_INVAL; else { si->cfg = cfg; From 2f16465384ce5edfe39f8e0697210427d19630d8 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 31 Jul 2020 13:51:39 +0200 Subject: [PATCH 21/21] pixma: define some magic values --- backend/pixma/pixma_axis.c | 10 +++++----- backend/pixma/pixma_axis_private.h | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/pixma/pixma_axis.c b/backend/pixma/pixma_axis.c index 246c97035..53562dcda 100644 --- a/backend/pixma/pixma_axis.c +++ b/backend/pixma/pixma_axis.c @@ -135,7 +135,7 @@ static ssize_t axis_send_wimp(int udp_socket, struct sockaddr_in *addr, uint8_t ssize_t ret; header->type = cmd; - header->magic = 0x03; + header->magic = WIMP_HEADER_MAGIC; header->zero = 0x00; memcpy(packet + sizeof(struct axis_wimp_header), data, len); ret = sendto(udp_socket, packet, sizeof(struct axis_wimp_header) + len, 0, addr, sizeof(struct sockaddr_in)); @@ -154,11 +154,11 @@ static ssize_t axis_wimp_get(int udp_socket, struct sockaddr_in *addr, uint8_t c struct axis_wimp_header *reply = (void *)data_out; struct axis_wimp_get_reply *str = (void *)(data_out + sizeof(struct axis_wimp_header)); - wimp_get.port = htole16(ntohs(addr->sin_port)), /* network order -> LE */ - wimp_get.magic = 0x02, + wimp_get.port = htole16(ntohs(addr->sin_port)); /* network order -> LE */ + wimp_get.magic = WIMP_GET_MAGIC; wimp_get.zero = 0; - wimp_get.cmd = cmd, - wimp_get.idx = idx, + wimp_get.cmd = cmd; + wimp_get.idx = idx; ret = axis_send_wimp(udp_socket, addr, WIMP_SERVER_STATUS, &wimp_get, sizeof(wimp_get)); if (ret) return ret; diff --git a/backend/pixma/pixma_axis_private.h b/backend/pixma/pixma_axis_private.h index ab24b2a2f..6ddc45b1f 100644 --- a/backend/pixma/pixma_axis_private.h +++ b/backend/pixma/pixma_axis_private.h @@ -10,6 +10,7 @@ #define AXIS_WIMP_PORT 10260 /* UDP port for discovery */ +#define WIMP_HEADER_MAGIC 0x03 #define WIMP_SERVER_INFO 0x24 #define WIMP_SERVER_STATUS 0x30 #define WIMP_REPLY (1 << 0) @@ -19,6 +20,7 @@ struct axis_wimp_header { uint8_t zero; } __attribute__((__packed__)); +#define WIMP_GET_MAGIC 0x02 #define WIMP_GET_NAME 0x02 #define WIMP_GET_STATUS 0x03 struct axis_wimp_get {