updated fujitsu backend with thread support

merge-requests/1/head
m. allan noah 2004-05-24 13:28:38 +00:00
rodzic 07d7013992
commit f7eb787095
3 zmienionych plików z 91 dodań i 56 usunięć

Wyświetl plik

@ -1,3 +1,7 @@
2004-05-24 m. allan noah <anoah at pfeiffer dot edu>
* backend/fujitsu.[ch]: apply Mattias Ellert's thread patch
split packet counter into r and w
2004-05-23 Henning Meier-Geinitz <henning@meier-geinitz.de>
* tools/check-usb-scanner.c: Detect GL660+GL646 on USB2 also.

Wyświetl plik

@ -167,7 +167,6 @@
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef HAVE_LIBC_H
# include <libc.h> /* NeXTStep/OpenStep */
@ -178,6 +177,7 @@
#include "sane/sanei_usb.h"
#include "sane/saneopts.h"
#include "sane/sanei_config.h"
#include "sane/sanei_thread.h"
#include "fujitsu-scsi.h"
#include "fujitsu.h"
@ -380,7 +380,8 @@ static int scsiBuffer = 64 * 1024;
/* flaming hack to get USB scanners
working without timeouts under linux */
static unsigned int cmd_count = 0;
static unsigned int r_cmd_count = 0;
static unsigned int w_cmd_count = 0;
/*
* required for compressed data transfer. sense_handler has to tell
@ -432,6 +433,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
DBG (10, "sane_init\n");
sanei_usb_init();
sanei_thread_init();
if (version_code)
*version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 0);
@ -2023,9 +2025,9 @@ sane_start (SANE_Handle handle)
*/
int exit_status;
DBG (10, "sane_start: waiting for reader to terminate...\n");
while (wait (&exit_status) != scanner->reader_pid);
sanei_thread_waitpid (scanner->reader_pid, &exit_status);
DBG (10, "sane_start: reader process has terminated.\n");
lseek (scanner->duplex_pipe, 0, SEEK_SET);
lseek (scanner->duplex_pipe_r, 0, SEEK_SET);
}
scanner->object_count = 2;
@ -2175,41 +2177,27 @@ sane_start (SANE_Handle handle)
}
ret = SANE_STATUS_GOOD;
scanner->reader_pid = fork();
if (scanner->reader_pid == 0)
{
/* reader_pid = 0 ===> child process */
sigset_t ignore_set;
struct SIGACTION act;
close (defaultFds[0]);
if (duplexFds[0] != -1)
close (duplexFds[0]);
scanner->default_pipe_r = defaultFds[0];
scanner->default_pipe_w = defaultFds[1];
scanner->duplex_pipe_r = (tempFile != -1) ? tempFile : duplexFds[0];
scanner->duplex_pipe_w = (tempFile != -1) ? tempFile : duplexFds[1];
sigfillset (&ignore_set);
sigdelset (&ignore_set, SIGTERM);
sigprocmask (SIG_SETMASK, &ignore_set, 0);
scanner->reader_pid = sanei_thread_begin (reader_process, scanner);
memset (&act, 0, sizeof (act));
sigaction (SIGTERM, &act, 0);
/* don't use exit() since that would run the atexit() handlers... */
_exit (reader_process
(scanner, defaultFds[1],
(tempFile != -1) ? tempFile : duplexFds[1]));
}
else if (scanner->reader_pid == -1)
if (scanner->reader_pid == -1)
{
DBG(MSG_ERR, "cannot fork reader process.\n");
DBG(MSG_ERR, "%s", strerror(errno));
ret = SANE_STATUS_IO_ERROR;
}
close (defaultFds[1]);
if (duplexFds[1] != -1)
close (duplexFds[1]);
scanner->default_pipe = defaultFds[0];
scanner->duplex_pipe = (tempFile != -1) ? tempFile : duplexFds[0];
if (sanei_thread_is_forked())
{
close (scanner->default_pipe_w);
if (scanner->duplex_pipe_w != -1)
close (scanner->duplex_pipe_w);
}
if (ret == SANE_STATUS_GOOD)
{
@ -2315,10 +2303,10 @@ sane_read (SANE_Handle handle, SANE_Byte * buf,
switch (scanner->object_count)
{
case 1:
source = scanner->default_pipe; /* this is always a pipe */
source = scanner->default_pipe_r; /* this is always a pipe */
break;
case 2:
source = scanner->duplex_pipe; /* this may be a pipe or a file */
source = scanner->duplex_pipe_r; /* this may be a pipe or a file */
break;
default:
return do_cancel (scanner);
@ -3077,6 +3065,13 @@ do_scsi_cmd (int fd, unsigned char *cmd,
/**
* Sends a USB command to the device.
* the fi-4x20 appear to have a firmware bug
* that prevents them from resetting the data0/1
* toggle on both bulk endpoints.
* so, this function is splits the commands into
* 64 byte chunks to enable us to count packets
* this is terrible for performance.
* FIXME: find a better way
*/
static int
do_usb_cmd (int fd, unsigned char *cmd,
@ -3094,8 +3089,6 @@ do_usb_cmd (int fd, unsigned char *cmd,
retry:
hexdump (IO_CMD, "<cmd<", cmd, cmd_len);
cmd_count++;
if (cmd_len > 0) op_code = ((int)cmd[0]) & 0xff;
if ((cmd_len+USB_CMD_HEADER_BYTES) > (int)sizeof(buf)) {
@ -3115,14 +3108,17 @@ retry:
for (j = 0; j < i;) {
cnt = i-j;
/* First URB has to be 31 bytes. */
/* All other URBs must be 64 bytes (max) per URB. */
/* First URB has to be 31 bytes. */
/* All other URBs must be 64 bytes (max) per URB. */
if ( (j == 0) && (cnt > 31) ) cnt = 31; else if (cnt > 64) cnt = 64;
hexdump (IO_CMD, "*** URB going out:", &buf[j], cnt);
DBG (10, "try to write %u bytes\n", cnt);
ret = sanei_usb_write_bulk(fd, &buf[j], &cnt);
DBG (10, "wrote %u bytes\n", cnt);
if (ret != SANE_STATUS_GOOD) break;
w_cmd_count++;
j += cnt;
}
if (ret != SANE_STATUS_GOOD) {
@ -3136,6 +3132,12 @@ retry:
cnt = (size_t)(req_out_len-ol);
DBG (10, "try to read %u bytes\n", cnt);
ret = sanei_usb_read_bulk(fd, &out[ol], &cnt);
/*flaming hack, count packets to fix data0/1 toggle issues*/
r_cmd_count += (cnt/64);
if(cnt % 64)
r_cmd_count++;
DBG (10, "read %u bytes\n", cnt);
if (cnt > 0) {
hexdump (IO_CMD, "*** Data read:", &out[ol], cnt);
@ -3145,12 +3147,13 @@ retry:
}
/* if (ret != SANE_STATUS_GOOD) break;*/
ol += cnt;
}
/* }*/
/* }*/
}
DBG(10, "*** Try to read CSW\n");
cnt = 13;
sanei_usb_read_bulk(fd, buf, &cnt);
r_cmd_count++;
hexdump (IO_CMD, "*** Read CSW", buf, cnt);
status_byte = ((int)buf[9]) & 0xff;
@ -3163,7 +3166,7 @@ retry:
ret,
req_out_len,
ol);
}
}
}
/* Auto-retry failed data reads, in case the scanner is busy. */
@ -3326,11 +3329,22 @@ free_scanner (struct fujitsu *s)
/* flaming hack cause some usb scanners (fi-4x20) fail
to work properly on next connection if an odd number
of commands are sent to the scanner. */
if(s->connection == SANE_FUJITSU_USB && cmd_count % 2){
ret = get_hardware_status(s);
if (ret)
return ret;
of commands are sent to the scanner on either endpoint */
if(s->connection == SANE_FUJITSU_USB){
/* if read counter is odd */
if(r_cmd_count % 2){
ret = do_cmd (s->connection, s->sfd, test_unit_readyB.cmd,
test_unit_readyB.size, 0, 0, NULL);
if (ret)
return ret;
}
/* if write is odd */
if(w_cmd_count % 2 && !r_cmd_count % 2){
ret = get_hardware_status(s);
if (ret)
return ret;
}
}
DBG (10, "free_scanner: ok\n");
@ -3513,10 +3527,10 @@ do_cancel (struct fujitsu *scanner)
if (scanner->object_count != 0)
{
close (scanner->default_pipe);
close (scanner->default_pipe_r);
if (scanner->duplex_mode == DUPLEX_BOTH)
{
close (scanner->duplex_pipe);
close (scanner->duplex_pipe_r);
}
}
@ -3531,10 +3545,10 @@ do_cancel (struct fujitsu *scanner)
* has already terminated and been waited for - for example,
* in the duplex-with-tempfile scenario.
*/
if (kill (scanner->reader_pid, SIGTERM) == 0)
if (sanei_thread_kill (scanner->reader_pid) == 0)
{
while (wait (&exit_status) != scanner->reader_pid)
DBG (50, "wait for scanner to stop\n");
DBG (50, "wait for scanner to stop\n");
sanei_thread_waitpid (scanner->reader_pid, &exit_status);
}
scanner->reader_pid = 0;
}
@ -5035,27 +5049,42 @@ calculateDerivedValues (struct fujitsu *scanner)
* This function is executed as a child process.
*/
static int
reader_process (struct fujitsu *scanner, int pipe_fd, int duplex_pipeFd)
reader_process (void *s)
{
FILE *fp1, *fp2;
sigset_t ignore_set;
sigset_t sigterm_set;
struct SIGACTION act;
time_t start_time, end_time;
unsigned int total_data_size = 0;
struct fujitsu *scanner = (struct fujitsu *) s;
(void) time (&start_time);
DBG (10, "reader_process started\n");
if (sanei_thread_is_forked())
{
close (scanner->default_pipe_r);
if (scanner->duplex_pipe_r != -1)
close (scanner->duplex_pipe_r);
}
sigfillset (&ignore_set);
sigdelset (&ignore_set, SIGTERM);
sigprocmask (SIG_SETMASK, &ignore_set, 0);
sigemptyset (&sigterm_set);
sigaddset (&sigterm_set, SIGTERM);
memset (&act, 0, sizeof (act));
#ifdef _POSIX_SOURCE
act.sa_handler = sigtermHandler;
#endif
sigaction (SIGTERM, &act, 0);
fp1 = fdopen (pipe_fd, "w");
fp1 = fdopen (scanner->default_pipe_w, "w");
if (!fp1)
{
DBG (MSG_ERR, "reader_process: couldn't open pipe!\n");
@ -5063,7 +5092,7 @@ reader_process (struct fujitsu *scanner, int pipe_fd, int duplex_pipeFd)
}
if (scanner->duplex_mode == DUPLEX_BOTH)
{
fp2 = fdopen (duplex_pipeFd, "w");
fp2 = fdopen (scanner->duplex_pipe_w, "w");
if (!fp2)
{
DBG (MSG_ERR, "reader_process: couldn't open pipe!\n");

Wyświetl plik

@ -268,8 +268,10 @@ struct fujitsu
/* Operational values (contain internal status information etc.) */
/* --------------------------------------------------------------------- */
int default_pipe; /* Pipe between reader process and backend. */
int duplex_pipe; /* Additional pipe for duplex scans. */
int default_pipe_r; /* Pipe between reader process and backend. */
int default_pipe_w; /* Pipe between reader process and backend. */
int duplex_pipe_r; /* Additional pipe for duplex scans. */
int duplex_pipe_w; /* Additional pipe for duplex scans. */
int reader_pid; /* Process ID of the reader process. */
int reverse; /* Whether to reverse the image. Not user */
@ -529,7 +531,7 @@ static size_t maxStringSize (const SANE_String_Const strings[]);
static int start_scan (struct fujitsu *s);
static int reader_process (struct fujitsu *scanner, int fd1, int fd2);
static int reader_process (void *scanner);
static unsigned int reader3091ColorDuplex (struct fujitsu *scanner, FILE * fd,
FILE * fd2);