kopia lustrzana https://gitlab.com/sane-project/backends
pixma_bjnp: add working scan button support
rodzic
cea03f3946
commit
f9a70e14be
|
@ -60,7 +60,7 @@
|
|||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/timeb.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -98,8 +98,7 @@
|
|||
|
||||
/* static data */
|
||||
static device_t device[BJNP_NO_DEVICES];
|
||||
|
||||
int first_free_device = 0;
|
||||
static int first_free_device = 0;
|
||||
|
||||
/*
|
||||
* Private functions
|
||||
|
@ -137,7 +136,7 @@ parse_IEEE1284_to_model (char *scanner_id, char *model)
|
|||
}
|
||||
|
||||
static int
|
||||
charTo2byte (char d[], char s[], int len)
|
||||
charTo2byte (char *d, const char *s, int len)
|
||||
{
|
||||
/*
|
||||
* copy ASCII string to 2 byte unicode string
|
||||
|
@ -237,7 +236,7 @@ bjnp_open_tcp (int devno)
|
|||
* Close this socket when starting another process...
|
||||
*/
|
||||
|
||||
fcntl (sock, F_SETFD, FD_CLOEXEC);
|
||||
fcntl (sock, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
if (connect
|
||||
(sock, (struct sockaddr *) &device[devno].addr,
|
||||
|
@ -248,7 +247,7 @@ bjnp_open_tcp (int devno)
|
|||
strerror (errno)));
|
||||
return -1;
|
||||
}
|
||||
device[devno].fd = sock;
|
||||
device[devno].tcp_socket = sock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -366,38 +365,30 @@ set_cmd (int devno, struct BJNP_command *cmd, char cmd_code, int payload_len)
|
|||
else
|
||||
{
|
||||
cmd->seq_no = htons (++(device[devno].serial));
|
||||
cmd->session_id = htons (device[devno].session_id);
|
||||
cmd->session_id = (cmd_code == CMD_UDP_POLL ) ? 0 : htons (device[devno].session_id);
|
||||
}
|
||||
cmd->payload_len = htonl (payload_len);
|
||||
device[devno].last_cmd = cmd_code;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
udp_command (const int dev_no, char *command, int cmd_len, char *response,
|
||||
int resp_len)
|
||||
bjnp_setup_udp_socket ( const int dev_no )
|
||||
{
|
||||
/*
|
||||
* Send UDP command and retrieve response
|
||||
* Returns: length of response or -1 in case of error
|
||||
* Setup a udp socket for the given device
|
||||
* Returns the socket or -1 in case of error
|
||||
*/
|
||||
|
||||
int sockfd;
|
||||
int numbytes = 0;
|
||||
fd_set fdset;
|
||||
struct timeval timeout;
|
||||
int result;
|
||||
int try, attempt;
|
||||
|
||||
PDBG (pixma_dbg (LOG_DEBUG, "udp_command: Sending UDP command to %s:%d\n",
|
||||
PDBG (pixma_dbg (LOG_DEBUG, "setup_udp_socket: Setting up the UDP socket to: %s:%d\n",
|
||||
inet_ntoa (device[dev_no].addr.sin_addr),
|
||||
ntohs (device[dev_no].addr.sin_port)));
|
||||
|
||||
if ((sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT, "udp_command: can not open socket - %s\n",
|
||||
(LOG_CRIT, "setup_udp_socket: can not open socket - %s\n",
|
||||
strerror (errno)));
|
||||
return -1;
|
||||
}
|
||||
|
@ -407,17 +398,37 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response,
|
|||
(socklen_t) sizeof (struct sockaddr_in)) != 0)
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT, "udp_command: connect failed- %s\n",
|
||||
(LOG_CRIT, "setup_udp_socket: connect failed- %s\n",
|
||||
strerror (errno)));
|
||||
return -1;
|
||||
}
|
||||
device[dev_no].udp_socket = sockfd;
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
static int
|
||||
udp_command (const int dev_no, char *command, int cmd_len, char *response,
|
||||
int resp_len)
|
||||
{
|
||||
/*
|
||||
* send udp command to given device and recieve the response`
|
||||
* returns: the legth of the response or -1
|
||||
*/
|
||||
int sockfd = device[dev_no].udp_socket;
|
||||
struct timeval timeout;
|
||||
int result;
|
||||
int try, attempt;
|
||||
int numbytes;
|
||||
fd_set fdset;
|
||||
struct BJNP_command *resp = (struct BJNP_command *) response;
|
||||
struct BJNP_command *cmd = (struct BJNP_command *) command;
|
||||
|
||||
for (try = 0; try < 3; try++)
|
||||
{
|
||||
if ((numbytes = send (sockfd, command, cmd_len, 0)) != cmd_len)
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT, "udp_command: Sent only 0x%x = %d bytes of packet",
|
||||
(LOG_NOTICE, "udp_command: Sent only 0x%x = %d bytes of packet\n",
|
||||
numbytes, numbytes));
|
||||
continue;
|
||||
}
|
||||
|
@ -426,14 +437,17 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response,
|
|||
do
|
||||
{
|
||||
/* wait for data to be received, ignore signals being received */
|
||||
/* skip late udp responses (they have an incorrect sequence number */
|
||||
FD_ZERO (&fdset);
|
||||
FD_SET (sockfd, &fdset);
|
||||
timeout.tv_sec = device[dev_no].bjnp_timeout_sec;
|
||||
timeout.tv_usec = device[dev_no].bjnp_timeout_msec;
|
||||
|
||||
timeout.tv_sec = BJNP_TIMEOUT_UDP;
|
||||
timeout.tv_usec = 0;
|
||||
}
|
||||
while (((result =
|
||||
select (sockfd + 1, &fdset, NULL, NULL, &timeout)) <= 0)
|
||||
&& (errno == EINTR) && (attempt++ < MAX_SELECT_ATTEMPTS));
|
||||
&& (errno == EINTR) && (attempt++ < MAX_SELECT_ATTEMPTS)
|
||||
&& resp-> seq_no != cmd->seq_no);
|
||||
|
||||
if (result <= 0)
|
||||
{
|
||||
|
@ -450,7 +464,6 @@ udp_command (const int dev_no, char *command, int cmd_len, char *response,
|
|||
strerror (errno)));
|
||||
continue;
|
||||
}
|
||||
close (sockfd);
|
||||
return numbytes;
|
||||
}
|
||||
|
||||
|
@ -526,7 +539,7 @@ u8tohex (uint8_t x, char *str)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
static void
|
||||
parse_scanner_address (char *resp_buf, char *address, char *serial)
|
||||
{
|
||||
/*
|
||||
|
@ -589,7 +602,7 @@ parse_scanner_address (char *resp_buf, char *address, char *serial)
|
|||
{
|
||||
|
||||
/* found match, good */
|
||||
PDBG (pixma_dbg (LOG_DEBUG,
|
||||
PDBG (pixma_dbg (LOG_INFO,
|
||||
"Forward lookup for %s succeeded, using as hostname\n", myhost-> h_name));
|
||||
match = 1;
|
||||
break;
|
||||
|
@ -604,7 +617,7 @@ parse_scanner_address (char *resp_buf, char *address, char *serial)
|
|||
}
|
||||
else
|
||||
{
|
||||
PDBG (pixma_dbg (LOG_DEBUG,
|
||||
PDBG (pixma_dbg (LOG_INFO,
|
||||
"Reseverse lookup for %s succeeded, IP-address however not found, using IP-address instead",
|
||||
myhost-> h_name));
|
||||
strcpy (address, ip_address);
|
||||
|
@ -613,7 +626,7 @@ parse_scanner_address (char *resp_buf, char *address, char *serial)
|
|||
else
|
||||
{
|
||||
/* lookup failed, use ip-address */
|
||||
PDBG( pixma_dbg (LOG_DEBUG, "reverse lookup of %s failed, using IP-address", myhost-> h_name));
|
||||
PDBG( pixma_dbg (LOG_INFO, "reverse lookup of %s failed, using IP-address", myhost-> h_name));
|
||||
strcpy (address, ip_address);
|
||||
}
|
||||
}
|
||||
|
@ -640,7 +653,7 @@ static int create_broadcast_socket( struct in_addr local_addr, int local_port )
|
|||
if ((sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_INFO, "create_braodcast_socket: can not open socket - %s",
|
||||
(LOG_CRIT, "create_braodcast_socket: can not open socket - %s",
|
||||
strerror (errno)));
|
||||
return -1;
|
||||
}
|
||||
|
@ -652,7 +665,7 @@ static int create_broadcast_socket( struct in_addr local_addr, int local_port )
|
|||
sizeof (broadcast)) != 0)
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_INFO,
|
||||
(LOG_CRIT,
|
||||
"create_braodcast_socket: setting socket options failed - %s",
|
||||
strerror (errno)));
|
||||
close (sockfd);
|
||||
|
@ -671,7 +684,7 @@ static int create_broadcast_socket( struct in_addr local_addr, int local_port )
|
|||
(socklen_t) sizeof (sendaddr)) != 0)
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_INFO,
|
||||
(LOG_CRIT,
|
||||
"create_braodcast_socket: bind socket to local address failed - %s\n",
|
||||
strerror (errno)));
|
||||
close (sockfd);
|
||||
|
@ -734,7 +747,7 @@ bjnp_finish_job (int devno)
|
|||
if (resp_len != sizeof (struct BJNP_command))
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT,
|
||||
(LOG_INFO,
|
||||
"Received %d characters on close scanjob command, expected %d\n",
|
||||
resp_len, (int) sizeof (struct BJNP_command)));
|
||||
return;
|
||||
|
@ -744,105 +757,108 @@ bjnp_finish_job (int devno)
|
|||
|
||||
}
|
||||
|
||||
#ifdef PIXMA_BJNP_STATUS
|
||||
#ifdef PIXMA_BJNP_USE_STATUS
|
||||
static int
|
||||
bjnp_get_intr (int devno, char type, char *hostname, char *user,
|
||||
SANE_Byte * buffer, int len)
|
||||
bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *status, int size)
|
||||
{
|
||||
/*
|
||||
* get interrupt status from device
|
||||
* this appear to be the equivalent of the status read by sanei_usb_read_int
|
||||
* returns number of bytes received or -1
|
||||
* send details of user to the scanner
|
||||
*/
|
||||
|
||||
char cmd_buf[BJNP_CMD_MAX];
|
||||
char resp_buf[BJNP_RESP_MAX];
|
||||
int resp_len;
|
||||
struct INTR_STATUS_REQ request;
|
||||
struct INTR_STATUS_RESP *resp;
|
||||
char details[64];
|
||||
int len = 0; /* payload length */
|
||||
int buf_len; /* length of the whole command buffer */
|
||||
struct POLL_DETAILS *poll;
|
||||
struct POLL_RESPONSE *response;
|
||||
char user_host[256];
|
||||
time_t t;
|
||||
int plen; /* payload lenght */
|
||||
int user_host_len;
|
||||
|
||||
if (len > (int) (sizeof (resp->status)))
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT, "requested status too big: %d, have %d\n", (int) len,
|
||||
(int) (sizeof (resp->status))));
|
||||
return -1;
|
||||
}
|
||||
poll = (struct POLL_DETAILS *) (cmd_buf);
|
||||
memset(poll, 0, sizeof( struct POLL_DETAILS));
|
||||
memset(resp_buf, 0, sizeof( resp_buf) );
|
||||
|
||||
/* Cacluate payload length. Type 0 and 1 packets do not contain the date.
|
||||
We format it all but do not send the date part */
|
||||
|
||||
plen = (type < 2) ?
|
||||
sizeof (request) - sizeof (struct BJNP_command) -
|
||||
sizeof (request.ascii_date) : sizeof (request) -
|
||||
sizeof (struct BJNP_command);
|
||||
|
||||
/* fill in the command header */
|
||||
|
||||
set_cmd (devno, (struct BJNP_command *) &request, CMD_UDP_SCAN_INFO, plen);
|
||||
|
||||
/* create payload */
|
||||
poll->type = htons(type);
|
||||
|
||||
request.type = htons (type);
|
||||
request.unknown_2 = htonl (0);
|
||||
if (type < 2)
|
||||
{
|
||||
request.dialogue = htons (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.dialogue = htons (device[devno].dialogue);
|
||||
}
|
||||
request.unknown_4 = htons (0x14);
|
||||
sprintf (details, "%s %s", user, hostname);
|
||||
charTo2byte (request.user_details, details, sizeof (request.user_details));
|
||||
user_host_len = sizeof( poll -> extensions.type2.user_host);
|
||||
snprintf(user_host, (user_host_len /2) ,"%s %s", user, hostname);
|
||||
user_host[ user_host_len /2 + 1] = '\0';
|
||||
|
||||
memset (request.unknown_5, 0, sizeof (request.unknown_5));
|
||||
request.date_len = (type < 2) ? 0 : sizeof (request.ascii_date);
|
||||
switch( type) {
|
||||
case 0:
|
||||
len = 80;
|
||||
break;
|
||||
case 1:
|
||||
charTo2byte(poll->extensions.type1.user_host, user_host, user_host_len);
|
||||
len = 80;
|
||||
break;
|
||||
case 2:
|
||||
poll->extensions.type2.dialog = htonl(device[devno].dialog);
|
||||
charTo2byte(poll->extensions.type2.user_host, user_host, user_host_len);
|
||||
poll->extensions.type2.unknown_1 = htonl(0x14);
|
||||
poll->extensions.type2.unknown_2 = htonl(0x10);
|
||||
t = time (NULL);
|
||||
strftime (poll->extensions.type2.ascii_date,
|
||||
sizeof (poll->extensions.type2.ascii_date),
|
||||
"%Y%m%d%H%M%S", localtime (&t));
|
||||
len = 116;
|
||||
break;
|
||||
case 5:
|
||||
poll->extensions.type5.dialog = htonl(device[devno].dialog);
|
||||
charTo2byte(poll->extensions.type5.user_host, user_host, user_host_len);
|
||||
poll->extensions.type5.unknown_1 = htonl(0x14);
|
||||
poll->extensions.type5.key = htonl(device[devno].status_key);
|
||||
len = 100;
|
||||
break;
|
||||
default:
|
||||
PDBG (pixma_dbg (LOG_INFO, "bjnp_poll_scanner: unknown packet type: %d\n", type));
|
||||
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,
|
||||
len);
|
||||
|
||||
/* set time field */
|
||||
buf_len = len + sizeof(struct BJNP_command);
|
||||
PDBG (pixma_dbg (LOG_DEBUG2, "Poll details (type %d)\n", type));
|
||||
PDBG (pixma_hexdump (LOG_DEBUG2, cmd_buf,
|
||||
buf_len));
|
||||
|
||||
t = time (NULL);
|
||||
strftime (request.ascii_date, sizeof (request.ascii_date) + 2,
|
||||
"%Y%m%d%H%M%S", localtime (&t));
|
||||
resp_len = udp_command (devno, cmd_buf, buf_len, resp_buf, BJNP_RESP_MAX);
|
||||
|
||||
/* length (plen) determines how many bytes get sent, this skips
|
||||
date for type 0 and 1 */
|
||||
|
||||
PDBG (pixma_dbg (LOG_DEBUG2, "Interrupt status request\n"));
|
||||
PDBG (pixma_hexdump (LOG_DEBUG2, (char *) &request,
|
||||
sizeof (struct BJNP_command) + plen));
|
||||
|
||||
resp_len = udp_command (devno, (char *) &request,
|
||||
sizeof (struct BJNP_command) + plen, resp_buf,
|
||||
BJNP_RESP_MAX);
|
||||
if (resp_len > 0)
|
||||
{
|
||||
PDBG (pixma_dbg (LOG_DEBUG2, "Interrupt status response:\n"));
|
||||
PDBG (pixma_dbg (LOG_DEBUG2, "Poll details response:\n"));
|
||||
PDBG (pixma_hexdump (LOG_DEBUG2, resp_buf, resp_len));
|
||||
response = (struct POLL_RESPONSE *) resp_buf;
|
||||
|
||||
device[devno].dialog = ntohl( response -> dialog );
|
||||
|
||||
if ( response -> result[3] == 1 )
|
||||
{
|
||||
return BJNP_RESTART_POLL;
|
||||
}
|
||||
if ( (response -> result[2] & 0x80) != 0)
|
||||
{
|
||||
memcpy( status, response->status, size);
|
||||
PDBG( pixma_dbg(LOG_INFO, "received button status!\n"));
|
||||
PDBG (pixma_hexdump( LOG_DEBUG2, status, size ));
|
||||
device[devno].status_key = ntohl( response -> key );
|
||||
return size;
|
||||
}
|
||||
}
|
||||
if (resp_len != sizeof (struct INTR_STATUS_RESP))
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT,
|
||||
"bjnp_get_intr: could not read interrupt status (expected %d bytes, got %d!\n",
|
||||
(int) sizeof (struct INTR_STATUS_RESP), (int) resp_len));
|
||||
return -1;
|
||||
}
|
||||
resp = (struct INTR_STATUS_RESP *) resp_buf;
|
||||
memcpy (buffer, resp->status, len);
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
static void
|
||||
bjnp_send_job_details (int devno, char *hostname, char *user, char *title)
|
||||
{
|
||||
/*
|
||||
* send details of scanjob to scanner
|
||||
* Returns: addrlist set to address details of used scanner
|
||||
*/
|
||||
|
||||
char cmd_buf[BJNP_CMD_MAX];
|
||||
|
@ -853,7 +869,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_DET,
|
||||
set_cmd (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_JOB_DETAILS,
|
||||
sizeof (*job) - sizeof (struct BJNP_command));
|
||||
|
||||
/* create payload */
|
||||
|
@ -879,7 +895,6 @@ bjnp_send_job_details (int devno, char *hostname, char *user, char *title)
|
|||
resp = (struct BJNP_command *) resp_buf;
|
||||
device[devno].session_id = ntohs (resp->session_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -895,7 +910,7 @@ bjnp_write (int devno, const SANE_Byte * buf, size_t count)
|
|||
|
||||
if (device[devno].scanner_data_left)
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT, "bjnp_write: ERROR scanner data left = 0x%lx = %ld\n",
|
||||
(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));
|
||||
|
||||
|
@ -909,7 +924,7 @@ bjnp_write (int devno, const SANE_Byte * buf, size_t count)
|
|||
sizeof (struct BJNP_command) + count)));
|
||||
|
||||
if ((sent_bytes =
|
||||
send (device[devno].fd, &bjnp_buf,
|
||||
send (device[devno].tcp_socket, &bjnp_buf,
|
||||
sizeof (struct BJNP_command) + count, 0)) <
|
||||
(ssize_t) (sizeof (struct BJNP_command) + count))
|
||||
{
|
||||
|
@ -957,7 +972,7 @@ bjnp_send_read_request (int devno)
|
|||
sizeof (struct BJNP_command)));
|
||||
|
||||
if ((sent_bytes =
|
||||
send (device[devno].fd, &bjnp_buf, sizeof (struct BJNP_command),
|
||||
send (device[devno].tcp_socket, &bjnp_buf, sizeof (struct BJNP_command),
|
||||
0)) < 0)
|
||||
{
|
||||
/* return result from write */
|
||||
|
@ -991,7 +1006,7 @@ bjnp_recv_header (int devno)
|
|||
|
||||
PDBG (pixma_dbg
|
||||
(LOG_DEBUG, "bjnp_recv_header: receiving response header\n"));
|
||||
fd = device[devno].fd;
|
||||
fd = device[devno].tcp_socket;
|
||||
|
||||
if (device[devno].scanner_data_left)
|
||||
PDBG (pixma_dbg
|
||||
|
@ -1007,8 +1022,8 @@ bjnp_recv_header (int devno)
|
|||
FD_ZERO (&input);
|
||||
FD_SET (fd, &input);
|
||||
|
||||
timeout.tv_sec = device[devno].bjnp_timeout_sec;
|
||||
timeout.tv_usec = device[devno].bjnp_timeout_msec;
|
||||
timeout.tv_sec = BJNP_TIMEOUT_TCP;
|
||||
timeout.tv_usec = 0;
|
||||
}
|
||||
while (((result = select (fd + 1, &input, NULL, NULL, &timeout)) == -1) &&
|
||||
(errno == EINTR) && (attempt++ < MAX_SELECT_ATTEMPTS));
|
||||
|
@ -1098,7 +1113,7 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len)
|
|||
int attempt;
|
||||
|
||||
PDBG (pixma_dbg (LOG_DEBUG, "bjnp_recv_data: receiving response data\n"));
|
||||
fd = device[devno].fd;
|
||||
fd = device[devno].tcp_socket;
|
||||
|
||||
PDBG (pixma_dbg
|
||||
(LOG_DEBUG, "bjnp_recv_data: read response payload (%ld bytes max)\n",
|
||||
|
@ -1108,11 +1123,10 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t * len)
|
|||
do
|
||||
{
|
||||
/* wait for data to be received, retry on a signal being received */
|
||||
|
||||
FD_ZERO (&input);
|
||||
FD_SET (fd, &input);
|
||||
timeout.tv_sec = device[devno].bjnp_timeout_sec;
|
||||
timeout.tv_usec = device[devno].bjnp_timeout_msec;
|
||||
timeout.tv_sec = BJNP_TIMEOUT_TCP;
|
||||
timeout.tv_usec = 0;
|
||||
}
|
||||
while (((result = select (fd + 1, &input, NULL, NULL, &timeout)) == -1) &&
|
||||
(errno == EINTR) && (attempt++ < MAX_SELECT_ATTEMPTS));
|
||||
|
@ -1242,19 +1256,18 @@ bjnp_allocate_device (SANE_String_Const devname, SANE_Int * dn,
|
|||
*dn = first_free_device++;
|
||||
device[*dn].open = 1;
|
||||
device[*dn].active = 0;
|
||||
#ifdef PIXMA_BJNP_STATUS
|
||||
device[*dn].polling = 0;
|
||||
device[*dn].dialogue = 0;
|
||||
#ifdef PIXMA_BJNP_USE_STATUS
|
||||
device[*dn].polling_status = BJNP_POLL_STOPPED;
|
||||
device[*dn].dialog = 0;
|
||||
device[*dn].status_key = 0;
|
||||
#endif
|
||||
device[*dn].fd = -1;
|
||||
device[*dn].tcp_socket = -1;
|
||||
device[*dn].addr.sin_family = AF_INET;
|
||||
device[*dn].addr.sin_port = htons (port);
|
||||
device[*dn].addr.sin_addr = addr_list[0];
|
||||
|
||||
device[*dn].session_id = 0;
|
||||
device[*dn].serial = -1;
|
||||
device[*dn].bjnp_timeout_sec = 1;
|
||||
device[*dn].bjnp_timeout_msec = 0;
|
||||
device[*dn].bjnp_timeout = 0;
|
||||
device[*dn].scanner_data_left = 0;
|
||||
device[*dn].last_cmd = 0;
|
||||
|
||||
|
@ -1264,6 +1277,11 @@ bjnp_allocate_device (SANE_String_Const devname, SANE_Int * dn,
|
|||
device[*dn].blocksize = 1024;
|
||||
device[*dn].short_read = 0;
|
||||
|
||||
if (bjnp_setup_udp_socket(*dn) == -1 )
|
||||
{
|
||||
first_free_device--;
|
||||
return BJNP_STATUS_INVAL;
|
||||
}
|
||||
return BJNP_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -1317,12 +1335,11 @@ sanei_bjnp_find_devices (const char **conf_devices,
|
|||
char uri[256];
|
||||
int dev_no;
|
||||
char serial[13];
|
||||
struct in_addr broadcast_addr[BJNP_SOCK_MAX];
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
struct ifaddrs *interfaces;
|
||||
struct ifaddrs *interface;
|
||||
struct in_addr local_addr[BJNP_SOCK_MAX];
|
||||
#else
|
||||
struct in_addr broadcast;
|
||||
struct in_addr local;
|
||||
#endif
|
||||
|
||||
|
@ -1402,7 +1419,7 @@ sanei_bjnp_find_devices (const char **conf_devices,
|
|||
|| (((struct sockaddr_in *) interface->ifa_addr)->sin_addr.s_addr ==
|
||||
htonl (INADDR_LOOPBACK)))
|
||||
{
|
||||
/* not an IPv4 address */
|
||||
/* not a valid IPv4 address */
|
||||
|
||||
PDBG (pixma_dbg (LOG_DEBUG,
|
||||
"%s is not a valid IPv4 interface, skipping...\n",
|
||||
|
@ -1417,9 +1434,9 @@ sanei_bjnp_find_devices (const char **conf_devices,
|
|||
{
|
||||
PDBG (pixma_dbg (LOG_INFO, "%s is IPv4 capable, sending broadcast..\n",
|
||||
interface->ifa_name));
|
||||
local_addr[no_sockets] = ((struct sockaddr_in *)
|
||||
broadcast_addr[no_sockets] = ((struct sockaddr_in *)
|
||||
interface->ifa_broadaddr)->sin_addr;
|
||||
/* track highest used port forlater use in select */
|
||||
/* track highest used socket for later use in select */
|
||||
if (socket_fd[no_sockets] > last_socketfd)
|
||||
{
|
||||
last_socketfd = socket_fd[no_sockets];
|
||||
|
@ -1429,7 +1446,7 @@ sanei_bjnp_find_devices (const char **conf_devices,
|
|||
}
|
||||
else
|
||||
{
|
||||
PDBG (pixma_dbg (LOG_INFO, "%s is IPv4 capable, ibut failed to create a socket.\n",
|
||||
PDBG (pixma_dbg (LOG_INFO, "%s is IPv4 capable, but failed to create a socket.\n",
|
||||
interface->ifa_name));
|
||||
}
|
||||
}
|
||||
|
@ -1437,44 +1454,31 @@ sanei_bjnp_find_devices (const char **conf_devices,
|
|||
}
|
||||
freeifaddrs (interfaces);
|
||||
|
||||
/* send MAX_SELECT_ATTEMPTS broadcasts on each suitable interface */
|
||||
#else
|
||||
/* we have no easy way to find interfaces with their broadcast addresses, use global broadcast */
|
||||
|
||||
local.s_addr = htonl (INADDR_ANY);
|
||||
broadcast_addr[0].s_addr = htonl (INADDR_BROADCAST);
|
||||
socket_fd[0] = create_broadcast_socket( local, BJNP_PORT_SCAN);
|
||||
|
||||
no_sockets = 1;
|
||||
last_socketfd = socket_fd[0];
|
||||
|
||||
FD_SET (socket_fd[0], &fdset);
|
||||
#endif
|
||||
|
||||
/* send MAX_SELECT_ATTEMPTS broadcasts on each socket */
|
||||
for (attempt = 0; attempt < MAX_SELECT_ATTEMPTS; attempt++)
|
||||
{
|
||||
for ( i=0; i < no_sockets; i++)
|
||||
{
|
||||
bjnp_send_broadcast ( socket_fd[i], local_addr[i], cmd, sizeof (cmd));
|
||||
bjnp_send_broadcast ( socket_fd[i], broadcast_addr[i], cmd, sizeof (cmd));
|
||||
}
|
||||
/* wait for some time between broadcast packets */
|
||||
usleep (BJNP_BROADCAST_INTERVAL * USLEEP_MS);
|
||||
}
|
||||
#else
|
||||
/* we have no easy way to find interfaces with their broadcast addresses, use global broadcast */
|
||||
|
||||
no_sockets = 0;
|
||||
broadcast.s_addr = htonl (INADDR_BROADCAST);
|
||||
local.s_addr = htonl (INADDR_ANY);
|
||||
|
||||
for (attempt = 0; attempt < MAX_SELECT_ATTEMPTS; attempt++)
|
||||
{
|
||||
if ((socket_fd[no_sockets] =
|
||||
bjnp_send_broadcast (local, BJNP_PORT_BROADCAST_BASE + attempt,
|
||||
broadcast, cmd, sizeof (cmd))) != -1)
|
||||
{
|
||||
if (socket_fd[no_sockets] > last_socketfd)
|
||||
{
|
||||
/* track highest used socket for use in select */
|
||||
|
||||
last_socketfd = socket_fd[no_sockets];
|
||||
}
|
||||
FD_SET (socket_fd[no_sockets], &fdset);
|
||||
no_sockets++;
|
||||
}
|
||||
/* wait for some time between broadcast packets */
|
||||
usleep (100 * USLEEP_MS);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* wait for up to 0.5 second for a UDP response */
|
||||
/* wait for a UDP response */
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 500 * USLEEP_MS;
|
||||
|
@ -1543,7 +1547,7 @@ sanei_bjnp_find_devices (const char **conf_devices,
|
|||
|
||||
case BJNP_STATUS_INVAL:
|
||||
PDBG (pixma_dbg
|
||||
(LOG_NOTICE,
|
||||
(LOG_CRIT,
|
||||
"Found scanner at %s, but can not open it\n", uri));
|
||||
break;
|
||||
|
||||
|
@ -1558,8 +1562,8 @@ sanei_bjnp_find_devices (const char **conf_devices,
|
|||
}
|
||||
}
|
||||
active_fdset = fdset;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 500 * USLEEP_MS;
|
||||
}
|
||||
PDBG (pixma_dbg (LOG_DEBUG, "scanner discovery finished...\n"));
|
||||
|
||||
|
@ -1597,11 +1601,13 @@ sanei_bjnp_open (SANE_String_Const devname, SANE_Int * dn)
|
|||
char pid_str[64];
|
||||
char my_hostname[256];
|
||||
char *login;
|
||||
int result;
|
||||
|
||||
PDBG (pixma_dbg (LOG_INFO, "sanei_bjnp_open(%s, %d):\n", devname, *dn));
|
||||
|
||||
if (bjnp_allocate_device (devname, dn, NULL) == BJNP_STATUS_INVAL)
|
||||
return SANE_STATUS_INVAL;
|
||||
result = bjnp_allocate_device (devname, dn, NULL);
|
||||
if ( (result != BJNP_STATUS_GOOD) && (result != BJNP_STATUS_ALREADY_ALLOCATED ) )
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
login = getusername ();
|
||||
gethostname (my_hostname, 256);
|
||||
|
@ -1626,9 +1632,12 @@ sanei_bjnp_close (SANE_Int dn)
|
|||
{
|
||||
PDBG (pixma_dbg (LOG_INFO, "sanei_bjnp_close(%d):\n", dn));
|
||||
if (device[dn].active)
|
||||
sanei_bjnp_deactivate (dn);
|
||||
|
||||
{
|
||||
sanei_bjnp_deactivate (dn);
|
||||
}
|
||||
/* we do not close the udp socket as long as the device remains allocated! */
|
||||
device[dn].open = 0;
|
||||
device[dn].active = 0;
|
||||
}
|
||||
|
||||
/** Activate BJNP device connection
|
||||
|
@ -1665,32 +1674,22 @@ sanei_bjnp_deactivate (SANE_Int dn)
|
|||
{
|
||||
PDBG (pixma_dbg (LOG_INFO, "sanei_bjnp_deactivate (%d)\n", dn));
|
||||
bjnp_finish_job (dn);
|
||||
close (device[dn].fd);
|
||||
device[dn].fd = -1;
|
||||
#ifdef PIXMA_BJNP_STATUS
|
||||
device[dn].polling = 0;
|
||||
#endif
|
||||
close (device[dn].tcp_socket);
|
||||
device[dn].tcp_socket = -1;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** Set the timeout for bulk and interrupt reads.
|
||||
*
|
||||
/** Set the timeout for interrupt reads.
|
||||
* we do not use it for bulk reads!
|
||||
* @param timeout the new timeout in ms
|
||||
*/
|
||||
extern void
|
||||
sanei_bjnp_set_timeout (SANE_Int devno, SANE_Int timeout)
|
||||
{
|
||||
int my_timeout = timeout;
|
||||
PDBG (pixma_dbg (LOG_INFO, "bjnp_set_timeout to %d\n",
|
||||
timeout));
|
||||
|
||||
/* timeout must be at least 10 second */
|
||||
|
||||
if (my_timeout < 20000)
|
||||
my_timeout = 20000;
|
||||
PDBG (pixma_dbg (LOG_INFO, "bjnp_set_timeout(requested %d, set %d):\n",
|
||||
timeout, my_timeout));
|
||||
|
||||
device[devno].bjnp_timeout_sec = my_timeout / 1000;
|
||||
device[devno].bjnp_timeout_msec = my_timeout % 1000;
|
||||
device[devno].bjnp_timeout = timeout;
|
||||
}
|
||||
|
||||
/** Initiate a bulk transfer read.
|
||||
|
@ -1720,7 +1719,7 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size)
|
|||
size_t left;
|
||||
|
||||
PDBG (pixma_dbg
|
||||
(LOG_DEBUG, "bjnp_read_bulk(%d, bufferptr, 0x%lx = %ld)\n", dn,
|
||||
(LOG_INFO, "bjnp_read_bulk(%d, bufferptr, 0x%lx = %ld)\n", dn,
|
||||
(unsigned long) *size, (unsigned long) size));
|
||||
|
||||
recvd = 0;
|
||||
|
@ -1760,7 +1759,6 @@ sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size)
|
|||
{
|
||||
/*
|
||||
* send new read request
|
||||
* TODO: Better error checking below
|
||||
*/
|
||||
|
||||
PDBG (pixma_dbg
|
||||
|
@ -1911,70 +1909,87 @@ sanei_bjnp_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size)
|
|||
extern SANE_Status
|
||||
sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size)
|
||||
{
|
||||
#ifndef PIXMA_BJNP_STATUS
|
||||
#ifndef PIXMA_BJNP_USE_STATUS
|
||||
PDBG (pixma_dbg
|
||||
(LOG_INFO, "bjnp_read_int(%d, bufferptr, 0x%lx = %ld):\n", dn,
|
||||
(unsigned long) *size, (unsigned long) *size));
|
||||
|
||||
memset (buffer, 0, *size);
|
||||
sleep (1);
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
#else
|
||||
char hostname[256];
|
||||
int result;
|
||||
int i;
|
||||
|
||||
char hostname[256];
|
||||
int resp_len;
|
||||
int timeout;
|
||||
int seconds;
|
||||
|
||||
PDBG (pixma_dbg
|
||||
(LOG_INFO, "bjnp_read_int(%d, bufferptr, %lx = %ld):\n", dn,
|
||||
(LOG_INFO, "bjnp_read_int(%d, bufferptr, 0x%lx = %ld):\n", dn,
|
||||
(unsigned long) *size, (unsigned long) *size));
|
||||
|
||||
memset (buffer, 0, *size);
|
||||
|
||||
gethostname (hostname, 32);
|
||||
hostname[32] = '\0';
|
||||
|
||||
|
||||
if (device[dn].polling == 0)
|
||||
switch (device[dn].polling_status)
|
||||
{
|
||||
/* establish status/read_intr dialogue */
|
||||
case BJNP_POLL_STOPPED:
|
||||
|
||||
device[dn].dialogue++;
|
||||
/* establish dialog */
|
||||
|
||||
if ((bjnp_get_intr (dn, 0, hostname, getusername (), buffer,
|
||||
*size) != (ssize_t) * size)
|
||||
|| sleep (4)
|
||||
|| (bjnp_get_intr (dn, 1, hostname, getusername (), buffer,
|
||||
*size) != (ssize_t) * size))
|
||||
{
|
||||
PDBG (pixma_dbg
|
||||
(LOG_NOTICE,
|
||||
"Failed to setup read_intr dialogue with device!\n"));
|
||||
}
|
||||
device[dn].polling = 1;
|
||||
if ( (bjnp_poll_scanner (dn, 0, hostname, getusername (), buffer, *size ) != 0) ||
|
||||
(bjnp_poll_scanner (dn, 1, hostname, getusername (), buffer, *size ) != 0) )
|
||||
{
|
||||
PDBG (pixma_dbg (LOG_NOTICE, "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;
|
||||
|
||||
case BJNP_POLL_STARTED:
|
||||
/* we use only seonds accuracy between poll attempts */
|
||||
timeout = device[dn].bjnp_timeout /1000;
|
||||
|
||||
do
|
||||
{
|
||||
if ( (resp_len = bjnp_poll_scanner (dn, 2, hostname, getusername (), buffer, *size ) ) < 0 )
|
||||
{
|
||||
PDBG (pixma_dbg (LOG_NOTICE, "Restarting polling dialog!\n"));
|
||||
device[dn].polling_status = BJNP_POLL_STOPPED;
|
||||
*size = 0;
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
*size = (size_t) resp_len;
|
||||
if ( resp_len > 0 )
|
||||
{
|
||||
device[dn].polling_status = BJNP_POLL_STATUS_RECEIVED;
|
||||
|
||||
/* this is a bit of a hack, but the scanner does not like */
|
||||
/* us to continue using the existing tcp socket */
|
||||
|
||||
sanei_bjnp_deactivate(dn);
|
||||
sanei_bjnp_activate(dn);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
seconds = timeout > 2 ? 2 : timeout;
|
||||
sleep(seconds);
|
||||
timeout = timeout - seconds;
|
||||
} while ( timeout > 0 ) ;
|
||||
break;
|
||||
case BJNP_POLL_STATUS_RECEIVED:
|
||||
if ( (resp_len = bjnp_poll_scanner (dn, 5, hostname, getusername (), buffer, *size ) ) < 0 )
|
||||
{
|
||||
PDBG (pixma_dbg (LOG_NOTICE, "Restarting polling dialog!\n"));
|
||||
device[dn].polling_status = BJNP_POLL_STOPPED;
|
||||
*size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = bjnp_get_intr (dn, 2, hostname, getusername (), buffer, *size);
|
||||
if (result < (int) *size)
|
||||
{
|
||||
*size = (result > 0) ? result : 0;
|
||||
PDBG (pixma_dbg
|
||||
(LOG_CRIT,
|
||||
"Could not retrieve interrupt information from device!\n"));
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
for (i = 0; i < result; i++)
|
||||
{
|
||||
if (buffer[i] != '\0')
|
||||
{
|
||||
PDBG (pixma_dbg (LOG_NOTICE, "Interrupt data received...\n"));
|
||||
PDBG (pixma_hexdump (LOG_NOTICE, buffer, result));
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
}
|
||||
/* no interrupt received, we just sleep for the indicated mount of time
|
||||
* and leave it to the caller to retry */
|
||||
|
||||
sleep (4);
|
||||
|
||||
PDBG (pixma_dbg (LOG_NOTICE, "sanei_bjnp_read_int: no data received\n"));
|
||||
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
return SANE_STATUS_EOF;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -67,9 +67,13 @@
|
|||
#define SCAN_BUF_MAX 65536 /* size of scanner data intermediate buffer */
|
||||
#define MAX_SELECT_ATTEMPTS 5 /* max nr of retries on select (EINTR) */
|
||||
#define USLEEP_MS 1000 /* sleep for 1 msec */
|
||||
#define BJNP_TIMEOUT_UDP 2 /* standard UDP timeout */
|
||||
#define BJNP_TIMEOUT_TCP 4 /* standard TCP timeout */
|
||||
|
||||
/* Do not yet use this, it does not work */
|
||||
/* #define PIXMA_BJNP_STATUS 1 */
|
||||
#define BJNP_RESTART_POLL -1 /* lost poll dialog, restart dialog */
|
||||
|
||||
/* This works now, disable when it gives you problems */
|
||||
#define PIXMA_BJNP_USE_STATUS 1
|
||||
|
||||
/* loglevel definitions */
|
||||
|
||||
|
@ -80,9 +84,9 @@
|
|||
#define LOG_DEBUG2 12
|
||||
#define LOG_DEBUG3 13
|
||||
|
||||
/*
|
||||
* BJNP protocol related definitions
|
||||
*/
|
||||
/*************************************/
|
||||
/* BJNP protocol related definitions */
|
||||
/*************************************/
|
||||
|
||||
/* port numbers */
|
||||
typedef enum bjnp_port_e
|
||||
|
@ -101,13 +105,14 @@ typedef enum bjnp_port_e
|
|||
typedef enum bjnp_cmd_e
|
||||
{
|
||||
CMD_UDP_DISCOVER = 0x01, /* discover if service type is listening at this port */
|
||||
CMD_UDP_JOB_DET = 0x10, /* send print job owner details */
|
||||
CMD_UDP_START_SCAN = 0x02, /* start scan pressed, sent from scanner to 224.0.0.1 */
|
||||
CMD_UDP_JOB_DETAILS = 0x10, /* send print/ scanner job owner details */
|
||||
CMD_UDP_CLOSE = 0x11, /* request connection closure */
|
||||
CMD_UDP_GET_STATUS = 0x20, /* get printer status */
|
||||
CMD_TCP_REQ = 0x20, /* read data from device */
|
||||
CMD_TCP_SEND = 0x21, /* send data to device */
|
||||
CMD_UDP_GET_ID = 0x30, /* get printer identity */
|
||||
CMD_UDP_SCAN_INFO = 0x32 /* Send some scan info?????? */
|
||||
CMD_UDP_POLL = 0x32 /* poll scanner for button status */
|
||||
} bjnp_cmd_t;
|
||||
|
||||
/* command type */
|
||||
|
@ -120,8 +125,13 @@ typedef enum uint8_t
|
|||
BJNP_RES_SCAN = 0x82 /* scanner response */
|
||||
} bjnp_cmd_type_t;
|
||||
|
||||
/***************************/
|
||||
/* BJNP protocol structure */
|
||||
/***************************/
|
||||
|
||||
struct BJNP_command
|
||||
/* The common protocol header */
|
||||
|
||||
struct __attribute__ ((__packed__)) BJNP_command
|
||||
{
|
||||
char BJNP_id[4]; /* string: BJNP */
|
||||
uint8_t dev_type; /* 1 = printer, 2 = scanner */
|
||||
|
@ -130,71 +140,104 @@ struct BJNP_command
|
|||
int16_t seq_no; /* sequence number */
|
||||
uint16_t session_id; /* session id for printing */
|
||||
uint32_t payload_len; /* length of command buffer */
|
||||
} __attribute__ ((__packed__));
|
||||
};
|
||||
|
||||
/* Layout of the init response buffer */
|
||||
|
||||
struct DISCOVER_RESPONSE
|
||||
struct __attribute__ ((__packed__)) DISCOVER_RESPONSE
|
||||
{
|
||||
struct BJNP_command response; /* reponse header */
|
||||
char unknown1[6]; /* 00 01 08 00 06 04 */
|
||||
char mac_addr[6]; /* printers mac address */
|
||||
unsigned char ip_addr[4]; /* printers IP-address */
|
||||
} __attribute__ ((__packed__));
|
||||
};
|
||||
|
||||
/* layout of payload for the JOB_DETAILS command */
|
||||
|
||||
struct JOB_DETAILS
|
||||
struct __attribute__ ((__packed__)) JOB_DETAILS
|
||||
{
|
||||
struct BJNP_command cmd; /* command header */
|
||||
char unknown[8]; /* don't know what these are for */
|
||||
char hostname[64]; /* hostname of sender */
|
||||
char username[64]; /* username */
|
||||
char jobtitle[256]; /* job title */
|
||||
} __attribute__ ((__packed__));
|
||||
};
|
||||
|
||||
/* layout of scan details, prety vague stuff */
|
||||
/* layout of the poll command, not everything is complete */
|
||||
|
||||
struct INTR_STATUS_REQ
|
||||
struct __attribute__ ((__packed__)) POLL_DETAILS
|
||||
{
|
||||
struct BJNP_command cmd; /* command header */
|
||||
uint16_t type; /* 0, 1, 2 or 5 */
|
||||
/* 05 = reset status */
|
||||
union {
|
||||
struct {
|
||||
char empty0[78]; /* type 0 has only 0 */
|
||||
} type0; /* length = 80 */
|
||||
|
||||
struct __attribute__ ((__packed__)) {
|
||||
char empty1[6]; /* 0 */
|
||||
char user_host[64]; /* unicode user <space> <space> hostname */
|
||||
uint64_t emtpy2; /* 0 */
|
||||
} type1; /* length = 80 */
|
||||
|
||||
struct __attribute__ ((__packed__)) {
|
||||
uint16_t empty_1; /* 00 00 */
|
||||
uint32_t dialog; /* constant dialog id, from previous response */
|
||||
char user_host[64]; /* unicode user <space> <space> hostname */
|
||||
uint32_t unknown_1; /* 00 00 00 14 */
|
||||
uint32_t empty_2[5]; /* only 0 */
|
||||
uint32_t unknown_2; /* 00 00 00 10 */
|
||||
char ascii_date[16]; /* YYYYMMDDHHMMSS only for type 2 */
|
||||
} type2; /* length = 116 */
|
||||
|
||||
struct __attribute__ ((__packed__)) {
|
||||
uint16_t empty_1; /* 00 00 */
|
||||
uint32_t dialog; /* constant dialog id, from previous response */
|
||||
char user_host[64]; /* unicode user <space> <space> hostname */
|
||||
uint32_t unknown_1; /* 00 00 00 14 */
|
||||
uint32_t key; /* copied from key field in status msg */
|
||||
uint32_t unknown_3[5]; /* only 0 */
|
||||
} type5; /* length = 100 */
|
||||
|
||||
} extensions;
|
||||
};
|
||||
|
||||
/* the poll response layout */
|
||||
|
||||
struct __attribute__ ((__packed__)) POLL_RESPONSE
|
||||
{
|
||||
struct BJNP_command cmd; /* command header */
|
||||
uint16_t type; /* 00 02 */
|
||||
uint32_t unknown_2; /* 00 00 00 00 */
|
||||
uint16_t dialogue; /* some kind of session number for */
|
||||
/* the status requests */
|
||||
char user_details[66]; /* user <space> <space> hostname */
|
||||
uint16_t unknown_4; /* 00 14 */
|
||||
char unknown_5[23]; /* only zeroes */
|
||||
char date_len; /* length of date-field 0 for type 0 and 1 */
|
||||
/* 0x16 for type 2 */
|
||||
char ascii_date[16]; /* YYYYMMDDHHMMSS */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct INTR_STATUS_RESP
|
||||
{
|
||||
struct BJNP_command cmd; /* command header */
|
||||
char unknown_1[16]; /* unknown stuff */
|
||||
char status[16]; /* interrupt status */
|
||||
char unknown_2[4]; /* 00 00 00 00 */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
unsigned char result[4]; /* unknown stuff, result[2] = 80 -> status is available*/
|
||||
/* result[8] is dialog, size? */
|
||||
uint32_t dialog; /* to be returned in next request */
|
||||
uint32_t unknown_2; /* returns the 00 00 00 14 from unknown_2 in request */
|
||||
uint32_t key; /* to be returned in type 5 status reset */
|
||||
unsigned char status[20]; /* interrupt status */
|
||||
};
|
||||
|
||||
/* Layout of ID and status responses */
|
||||
|
||||
struct IDENTITY
|
||||
struct __attribute__ ((__packed__)) IDENTITY
|
||||
{
|
||||
struct BJNP_command cmd;
|
||||
uint16_t id_len; /* length of identity */
|
||||
char id[BJNP_IEEE1284_MAX]; /* identity */
|
||||
} __attribute__ ((__packed__));
|
||||
};
|
||||
|
||||
|
||||
/* response to TCP print command */
|
||||
|
||||
struct SCAN_BUF
|
||||
struct __attribute__ ((__packed__)) SCAN_BUF
|
||||
{
|
||||
struct BJNP_command cmd;
|
||||
char scan_data[65536];
|
||||
} __attribute__ ((__packed__));
|
||||
};
|
||||
|
||||
/**************************/
|
||||
/* Local enum definitions */
|
||||
/**************************/
|
||||
|
||||
typedef enum bjnp_paper_status_e
|
||||
{
|
||||
|
@ -210,6 +253,15 @@ typedef enum
|
|||
BJNP_STATUS_ALREADY_ALLOCATED
|
||||
} BJNP_Status;
|
||||
|
||||
/* button polling */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BJNP_POLL_STOPPED = 0,
|
||||
BJNP_POLL_STARTED = 1,
|
||||
BJNP_POLL_STATUS_RECEIVED = 2
|
||||
} BJNP_polling_status_e;
|
||||
|
||||
/*
|
||||
* Device information for opened devices
|
||||
*/
|
||||
|
@ -218,19 +270,20 @@ typedef struct device_s
|
|||
{
|
||||
int open; /* connection to printer is opened */
|
||||
int active; /* connection is active (has open tcp connection */
|
||||
int fd; /* file descriptor */
|
||||
struct sockaddr_in addr;
|
||||
int tcp_socket; /* open tcp socket for communcation to scannner */
|
||||
int udp_socket; /* open udp socket for communication to scanner */
|
||||
struct sockaddr_in addr;
|
||||
int session_id; /* session id used in bjnp protocol for TCP packets */
|
||||
int16_t serial; /* sequence number of command */
|
||||
int bjnp_timeout_sec; /* timeout (seconds) for next command */
|
||||
int bjnp_timeout_msec; /* timeout (msec) for next command */
|
||||
int bjnp_timeout; /* timeout (msec) for next poll command */
|
||||
size_t scanner_data_left; /* TCP data left from last read request */
|
||||
int last_cmd; /* last command sent */
|
||||
size_t blocksize; /* size of (TCP) blocks returned by the scanner */
|
||||
char short_read; /* last TCP read command was shorter than blocksize */
|
||||
#ifdef PIXMA_BJNP_STATUS
|
||||
char polling; /* status polling ongoing */
|
||||
int dialogue; /* polling dialogue-id */
|
||||
#ifdef PIXMA_BJNP_USE_STATUS
|
||||
char polling_status; /* status polling ongoing */
|
||||
uint32_t dialog; /* poll dialog */
|
||||
uint32_t status_key; /* key of last received status message */
|
||||
#endif
|
||||
} device_t;
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue