kopia lustrzana https://gitlab.com/sane-project/backends
changes due to the sanei_thread-lib work.
rodzic
9fabf6307a
commit
81dd39d572
|
@ -609,7 +609,8 @@ typedef struct Plustek_Scanner
|
||||||
struct Plustek_Scanner *next;
|
struct Plustek_Scanner *next;
|
||||||
pid_t reader_pid; /* process id of reader */
|
pid_t reader_pid; /* process id of reader */
|
||||||
SANE_Status exit_code; /* status of the reader process */
|
SANE_Status exit_code; /* status of the reader process */
|
||||||
int pipe; /* pipe to reader process */
|
int r_pipe; /* pipe to reader process */
|
||||||
|
int w_pipe; /* pipe from reader process */
|
||||||
unsigned long bytes_read; /* number of bytes currently read*/
|
unsigned long bytes_read; /* number of bytes currently read*/
|
||||||
Plustek_Device *hw; /* pointer to current device */
|
Plustek_Device *hw; /* pointer to current device */
|
||||||
Option_Value val[NUM_OPTIONS];
|
Option_Value val[NUM_OPTIONS];
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
* - added altCalibration option
|
* - added altCalibration option
|
||||||
* - removed parallelport support --> new backend: plustek_pp
|
* - removed parallelport support --> new backend: plustek_pp
|
||||||
* - cleanup
|
* - cleanup
|
||||||
* - added pthread support
|
* - added sanei_thread support
|
||||||
*.
|
*.
|
||||||
* <hr>
|
* <hr>
|
||||||
* This file is part of the SANE package.
|
* This file is part of the SANE package.
|
||||||
|
@ -142,11 +142,6 @@
|
||||||
#include "sane/sanei_config.h"
|
#include "sane/sanei_config.h"
|
||||||
#include "sane/sanei_thread.h"
|
#include "sane/sanei_thread.h"
|
||||||
|
|
||||||
/** we're using this possibility only on MacOS X... */
|
|
||||||
#if defined HAVE_LIBPTHREAD
|
|
||||||
#define _PLUSTEK_USE_THREAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** might be used to disable all USB stuff - esp. for OS/2 */
|
/** might be used to disable all USB stuff - esp. for OS/2 */
|
||||||
#ifndef HAVE_OS2_H
|
#ifndef HAVE_OS2_H
|
||||||
# define _PLUSTEK_USB
|
# define _PLUSTEK_USB
|
||||||
|
@ -339,58 +334,21 @@ static pModeParam getModeList( Plustek_Scanner *scanner )
|
||||||
return mp;
|
return mp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** function to check what our reader process returns. If the
|
|
||||||
* process didn't exist, we can be sure, that we had any other problems
|
|
||||||
*/
|
|
||||||
static SANE_Bool getReaderProcessExitCode( Plustek_Scanner *scanner )
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
scanner->exit_code = SANE_STATUS_IO_ERROR;
|
|
||||||
|
|
||||||
if( scanner->reader_pid > 0 ) {
|
|
||||||
|
|
||||||
res = sanei_thread_waitpid( scanner->reader_pid, &status, WNOHANG );
|
|
||||||
|
|
||||||
if( res == scanner->reader_pid ) {
|
|
||||||
|
|
||||||
DBG( _DBG_INFO, "res=%i, status=%i\n",res,status );
|
|
||||||
|
|
||||||
if( WIFEXITED( status )) {
|
|
||||||
|
|
||||||
scanner->exit_code = WEXITSTATUS(status);
|
|
||||||
DBG( _DBG_INFO, "Child WEXITSTATUS = %d\n",scanner->exit_code);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if( !WIFSIGNALED( status )) {
|
|
||||||
scanner->exit_code = SANE_STATUS_GOOD;
|
|
||||||
DBG( _DBG_INFO, "Child termination okay\n" );
|
|
||||||
} else {
|
|
||||||
DBG( _DBG_ERROR, "Child terminated by signal %d\n",
|
|
||||||
WTERMSIG(status));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner->reader_pid = -1;
|
|
||||||
return SANE_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SANE_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
static SANE_Status close_pipe( Plustek_Scanner *scanner )
|
static SANE_Status close_pipe( Plustek_Scanner *scanner )
|
||||||
{
|
{
|
||||||
if( scanner->pipe >= 0 ) {
|
if( scanner->r_pipe >= 0 ) {
|
||||||
|
|
||||||
DBG( _DBG_PROC, "close_pipe\n" );
|
DBG( _DBG_PROC, "close_pipe (r_pipe)\n" );
|
||||||
|
close( scanner->r_pipe );
|
||||||
|
scanner->r_pipe = -1;
|
||||||
|
}
|
||||||
|
if( scanner->w_pipe >= 0 ) {
|
||||||
|
|
||||||
close( scanner->pipe );
|
DBG( _DBG_PROC, "close_pipe (w_pipe)\n" );
|
||||||
scanner->pipe = -1;
|
close( scanner->w_pipe );
|
||||||
|
scanner->w_pipe = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SANE_STATUS_EOF;
|
return SANE_STATUS_EOF;
|
||||||
|
@ -400,20 +358,20 @@ static SANE_Status close_pipe( Plustek_Scanner *scanner )
|
||||||
*/
|
*/
|
||||||
static void sig_chldhandler( int signo )
|
static void sig_chldhandler( int signo )
|
||||||
{
|
{
|
||||||
DBG( _DBG_PROC, "Child is down (signal=%d)\n", signo );
|
DBG( _DBG_PROC, "(SIG) Child is down (signal=%d)\n", signo );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** signal handler to kill the child process
|
/** signal handler to kill the child process
|
||||||
*/
|
*/
|
||||||
static RETSIGTYPE reader_process_sigterm_handler( int signo )
|
static RETSIGTYPE reader_process_sigterm_handler( int signo )
|
||||||
{
|
{
|
||||||
DBG( _DBG_PROC, "reader_process: terminated by signal %d\n", signo );
|
DBG( _DBG_PROC, "(SIG) reader_process: terminated by signal %d\n", signo );
|
||||||
_exit( SANE_STATUS_GOOD );
|
_exit( SANE_STATUS_GOOD );
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE usb_reader_process_sigterm_handler( int signo )
|
static RETSIGTYPE usb_reader_process_sigterm_handler( int signo )
|
||||||
{
|
{
|
||||||
DBG( _DBG_PROC, "reader_process: terminated by signal %d\n", signo );
|
DBG( _DBG_PROC, "(SIG) reader_process: terminated by signal %d\n", signo );
|
||||||
cancelRead = SANE_TRUE;
|
cancelRead = SANE_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,25 +384,40 @@ static RETSIGTYPE sigalarm_handler( int signo )
|
||||||
/** executed as a child process
|
/** executed as a child process
|
||||||
* read the data from the driver and send them to the parent process
|
* read the data from the driver and send them to the parent process
|
||||||
*/
|
*/
|
||||||
static int reader_process( Plustek_Scanner *scanner, int pipe_fd )
|
static int reader_process( void *args )
|
||||||
{
|
{
|
||||||
int line;
|
int line;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned long status;
|
unsigned long status;
|
||||||
unsigned long data_length;
|
unsigned long data_length;
|
||||||
struct SIGACTION act;
|
struct SIGACTION act;
|
||||||
|
sigset_t ignore_set;
|
||||||
|
Plustek_Scanner *scanner = (Plustek_Scanner *)args;
|
||||||
|
|
||||||
DBG( _DBG_PROC, "reader_process started\n" );
|
if( sanei_thread_is_forked()) {
|
||||||
|
DBG( _DBG_PROC, "reader_process started (forked)\n" );
|
||||||
|
close( scanner->r_pipe );
|
||||||
|
scanner->r_pipe = -1;
|
||||||
|
} else {
|
||||||
|
DBG( _DBG_PROC, "reader_process started (as thread)\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
sigfillset ( &ignore_set );
|
||||||
|
sigdelset ( &ignore_set, SIGTERM );
|
||||||
|
sigprocmask( SIG_SETMASK, &ignore_set, 0 );
|
||||||
|
|
||||||
|
memset ( &act, 0, sizeof (act));
|
||||||
|
sigaction( SIGTERM, &act, 0 );
|
||||||
|
|
||||||
/* install the signal handler */
|
|
||||||
cancelRead = SANE_FALSE;
|
cancelRead = SANE_FALSE;
|
||||||
|
|
||||||
|
/* install the signal handler */
|
||||||
sigemptyset(&(act.sa_mask));
|
sigemptyset(&(act.sa_mask));
|
||||||
act.sa_flags = 0;
|
act.sa_flags = 0;
|
||||||
|
|
||||||
act.sa_handler = reader_process_sigterm_handler;
|
act.sa_handler = reader_process_sigterm_handler;
|
||||||
sigaction( SIGTERM, &act, 0 );
|
sigaction( SIGTERM, &act, 0 );
|
||||||
|
|
||||||
act.sa_handler = usb_reader_process_sigterm_handler;
|
act.sa_handler = usb_reader_process_sigterm_handler;
|
||||||
sigaction( SIGUSR1, &act, 0 );
|
sigaction( SIGUSR1, &act, 0 );
|
||||||
|
|
||||||
|
@ -472,7 +445,7 @@ static int reader_process( Plustek_Scanner *scanner, int pipe_fd )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
write( pipe_fd, buf, scanner->params.bytes_per_line );
|
write( scanner->w_pipe, buf, scanner->params.bytes_per_line );
|
||||||
buf += scanner->params.bytes_per_line;
|
buf += scanner->params.bytes_per_line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,39 +463,10 @@ static int reader_process( Plustek_Scanner *scanner, int pipe_fd )
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipe_fd = -1;
|
|
||||||
|
|
||||||
DBG( _DBG_PROC, "reader_process: finished reading data\n" );
|
DBG( _DBG_PROC, "reader_process: finished reading data\n" );
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _PLUSTEK_USE_THREAD
|
|
||||||
/*
|
|
||||||
* reader thread: need a wrapper, because threads can have
|
|
||||||
* only one parameter.
|
|
||||||
*/
|
|
||||||
static void reader_thread( void *data )
|
|
||||||
{
|
|
||||||
Plustek_Scanner *s = (Plustek_Scanner *)data;
|
|
||||||
sigset_t ignore_set;
|
|
||||||
struct SIGACTION act;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "reader_thread...\n" );
|
|
||||||
|
|
||||||
sigfillset ( &ignore_set );
|
|
||||||
sigdelset ( &ignore_set, SIGTERM );
|
|
||||||
sigprocmask( SIG_SETMASK, &ignore_set, 0 );
|
|
||||||
|
|
||||||
memset ( &act, 0, sizeof (act));
|
|
||||||
sigaction( SIGTERM, &act, 0 );
|
|
||||||
|
|
||||||
status = reader_process( s, s->pipe );
|
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "reader process done, status = %i\n", status );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** stop the current scan process
|
/** stop the current scan process
|
||||||
*/
|
*/
|
||||||
static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe )
|
static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe )
|
||||||
|
@ -547,16 +491,22 @@ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe )
|
||||||
sigaction( SIGALRM, &act, 0 );
|
sigaction( SIGALRM, &act, 0 );
|
||||||
|
|
||||||
/* kill our child process and wait until done */
|
/* kill our child process and wait until done */
|
||||||
sanei_thread_kill( scanner->reader_pid, SIGUSR1 );
|
sanei_thread_sendsig( scanner->reader_pid, SIGUSR1 );
|
||||||
|
|
||||||
/* give'em 10 seconds 'til done...*/
|
/* give'em 10 seconds 'til done...*/
|
||||||
alarm(10);
|
alarm(10);
|
||||||
res = sanei_thread_waitpid( scanner->reader_pid, 0, 0 );
|
res = sanei_thread_waitpid( scanner->reader_pid, 0 );
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
|
||||||
if( res != scanner->reader_pid ) {
|
if( res != scanner->reader_pid ) {
|
||||||
DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n");
|
DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n");
|
||||||
sanei_thread_kill( scanner->reader_pid, SIGKILL );
|
|
||||||
|
/* do it the hard way...*/
|
||||||
|
#ifdef USE_PTHREAD
|
||||||
|
sanei_thread_kill( scanner->reader_pid );
|
||||||
|
#else
|
||||||
|
sanei_thread_sendsig( scanner->reader_pid, SIGKILL );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
scanner->reader_pid = 0;
|
scanner->reader_pid = 0;
|
||||||
DBG( _DBG_PROC,"reader_process killed\n");
|
DBG( _DBG_PROC,"reader_process killed\n");
|
||||||
|
@ -1228,7 +1178,7 @@ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize )
|
||||||
sanei_thread_init();
|
sanei_thread_init();
|
||||||
|
|
||||||
#if defined PACKAGE && defined VERSION
|
#if defined PACKAGE && defined VERSION
|
||||||
DBG( _DBG_SANE_INIT, "Plustek backend V"BACKEND_VERSION", part of "
|
DBG( _DBG_INFO, "Plustek backend V"BACKEND_VERSION", part of "
|
||||||
PACKAGE " " VERSION "\n");
|
PACKAGE " " VERSION "\n");
|
||||||
#else
|
#else
|
||||||
DBG( _DBG_INFO, "Plustek backend V"BACKEND_VERSION"\n" );
|
DBG( _DBG_INFO, "Plustek backend V"BACKEND_VERSION"\n" );
|
||||||
|
@ -1457,7 +1407,8 @@ SANE_Status sane_open( SANE_String_Const devicename, SANE_Handle* handle )
|
||||||
return SANE_STATUS_NO_MEM;
|
return SANE_STATUS_NO_MEM;
|
||||||
|
|
||||||
memset(s, 0, sizeof (*s));
|
memset(s, 0, sizeof (*s));
|
||||||
s->pipe = -1;
|
s->r_pipe = -1;
|
||||||
|
s->w_pipe = -1;
|
||||||
s->hw = dev;
|
s->hw = dev;
|
||||||
s->scanning = SANE_FALSE;
|
s->scanning = SANE_FALSE;
|
||||||
|
|
||||||
|
@ -2053,22 +2004,21 @@ SANE_Status sane_start( SANE_Handle handle )
|
||||||
|
|
||||||
/* create reader routine as new process */
|
/* create reader routine as new process */
|
||||||
s->bytes_read = 0;
|
s->bytes_read = 0;
|
||||||
#ifdef _PLUSTEK_USE_THREAD
|
s->r_pipe = fds[0];
|
||||||
s->pipe = fds[1];
|
s->w_pipe = fds[1];
|
||||||
s->reader_pid = sanei_thread_begin( reader_thread, s );
|
s->reader_pid = sanei_thread_begin( reader_process, s );
|
||||||
#else
|
|
||||||
s->reader_pid = fork();
|
|
||||||
#endif
|
|
||||||
cancelRead = SANE_FALSE;
|
cancelRead = SANE_FALSE;
|
||||||
|
|
||||||
if( s->reader_pid < 0 ) {
|
if( s->reader_pid < 0 ) {
|
||||||
DBG( _DBG_ERROR, "ERROR: could not create child process\n" );
|
DBG( _DBG_ERROR, "ERROR: could not start reader task\n" );
|
||||||
s->scanning = SANE_FALSE;
|
s->scanning = SANE_FALSE;
|
||||||
dev->close( dev );
|
dev->close( dev );
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reader_pid = 0 ===> child process */
|
/* reader_pid = 0 ===> child process */
|
||||||
|
#if 0
|
||||||
if( 0 == s->reader_pid ) {
|
if( 0 == s->reader_pid ) {
|
||||||
|
|
||||||
sigset_t ignore_set;
|
sigset_t ignore_set;
|
||||||
|
@ -2076,7 +2026,10 @@ SANE_Status sane_start( SANE_Handle handle )
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "reader process...\n" );
|
DBG( _DBG_SANE_INIT, "reader process...\n" );
|
||||||
|
|
||||||
close(fds[0]);
|
if( sanei_thread_is_forked()) {
|
||||||
|
close( s->r_pipe );
|
||||||
|
s->r_pipe = -1;
|
||||||
|
}
|
||||||
|
|
||||||
sigfillset ( &ignore_set );
|
sigfillset ( &ignore_set );
|
||||||
sigdelset ( &ignore_set, SIGTERM );
|
sigdelset ( &ignore_set, SIGTERM );
|
||||||
|
@ -2085,23 +2038,22 @@ SANE_Status sane_start( SANE_Handle handle )
|
||||||
memset ( &act, 0, sizeof (act));
|
memset ( &act, 0, sizeof (act));
|
||||||
sigaction( SIGTERM, &act, 0 );
|
sigaction( SIGTERM, &act, 0 );
|
||||||
|
|
||||||
status = reader_process( s, fds[1] );
|
status = reader_process( s );
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "reader process done, status = %i\n", status );
|
DBG( _DBG_SANE_INIT, "reader process done, status = %i\n", status );
|
||||||
|
|
||||||
/* don't use exit() since that would run the atexit() handlers */
|
/* don't use exit() since that would run the atexit() handlers */
|
||||||
_exit( status );
|
_exit( status );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
signal( SIGCHLD, sig_chldhandler );
|
signal( SIGCHLD, sig_chldhandler );
|
||||||
|
|
||||||
if( sanei_thread_is_forked())
|
if( sanei_thread_is_forked()) {
|
||||||
close(fds[1]);
|
close( s->w_pipe );
|
||||||
|
s->w_pipe = -1;
|
||||||
|
}
|
||||||
|
|
||||||
s->pipe = fds[0];
|
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "sane_start done\n" );
|
DBG( _DBG_SANE_INIT, "sane_start done\n" );
|
||||||
|
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2116,7 +2068,7 @@ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data,
|
||||||
*length = 0;
|
*length = 0;
|
||||||
|
|
||||||
/* here we read all data from the driver... */
|
/* here we read all data from the driver... */
|
||||||
nread = read( s->pipe, data, max_length );
|
nread = read( s->r_pipe, data, max_length );
|
||||||
DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread );
|
DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread );
|
||||||
if (!(s->scanning)) {
|
if (!(s->scanning)) {
|
||||||
return do_cancel( s, SANE_TRUE );
|
return do_cancel( s, SANE_TRUE );
|
||||||
|
@ -2129,7 +2081,7 @@ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data,
|
||||||
/* if we already had red the picture, so it's okay and stop */
|
/* if we already had red the picture, so it's okay and stop */
|
||||||
if( s->bytes_read ==
|
if( s->bytes_read ==
|
||||||
(unsigned long)(s->params.lines * s->params.bytes_per_line)) {
|
(unsigned long)(s->params.lines * s->params.bytes_per_line)) {
|
||||||
sanei_thread_waitpid( s->reader_pid, 0, 0 );
|
sanei_thread_waitpid( s->reader_pid, 0 );
|
||||||
s->reader_pid = -1;
|
s->reader_pid = -1;
|
||||||
drvclose( s->hw );
|
drvclose( s->hw );
|
||||||
return close_pipe(s);
|
return close_pipe(s);
|
||||||
|
@ -2152,7 +2104,7 @@ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data,
|
||||||
if( 0 == nread ) {
|
if( 0 == nread ) {
|
||||||
|
|
||||||
drvclose( s->hw );
|
drvclose( s->hw );
|
||||||
getReaderProcessExitCode( s );
|
s->exit_code = sanei_thread_get_status( s->reader_pid );
|
||||||
|
|
||||||
if( SANE_STATUS_GOOD != s->exit_code ) {
|
if( SANE_STATUS_GOOD != s->exit_code ) {
|
||||||
close_pipe(s);
|
close_pipe(s);
|
||||||
|
@ -2189,12 +2141,12 @@ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( -1 == s->pipe ) {
|
if( -1 == s->r_pipe ) {
|
||||||
DBG( _DBG_ERROR, "ERROR: not supported !\n" );
|
DBG( _DBG_ERROR, "ERROR: not supported !\n" );
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) {
|
if( fcntl (s->r_pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) {
|
||||||
DBG( _DBG_ERROR, "ERROR: can´t set to non-blocking mode !\n" );
|
DBG( _DBG_ERROR, "ERROR: can´t set to non-blocking mode !\n" );
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -2216,7 +2168,7 @@ SANE_Status sane_get_select_fd( SANE_Handle handle, SANE_Int * fd )
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*fd = s->pipe;
|
*fd = s->r_pipe;
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" );
|
DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" );
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
|
@ -370,7 +370,8 @@ typedef struct Plustek_Scanner
|
||||||
struct Plustek_Scanner *next;
|
struct Plustek_Scanner *next;
|
||||||
pid_t reader_pid; /* process id of reader */
|
pid_t reader_pid; /* process id of reader */
|
||||||
SANE_Status exit_code; /* status of the reader process */
|
SANE_Status exit_code; /* status of the reader process */
|
||||||
int pipe; /* pipe to reader process */
|
int r_pipe; /* pipe to reader process */
|
||||||
|
int w_pipe; /* pipe from reader process */
|
||||||
unsigned long bytes_read; /* number of bytes currently read*/
|
unsigned long bytes_read; /* number of bytes currently read*/
|
||||||
pPlustek_Device hw; /* pointer to current device */
|
pPlustek_Device hw; /* pointer to current device */
|
||||||
Option_Value val[NUM_OPTIONS];
|
Option_Value val[NUM_OPTIONS];
|
||||||
|
|
|
@ -80,7 +80,6 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
@ -88,10 +87,11 @@
|
||||||
#include "sane/sanei.h"
|
#include "sane/sanei.h"
|
||||||
#include "sane/saneopts.h"
|
#include "sane/saneopts.h"
|
||||||
|
|
||||||
#define BACKEND_VERSION "0.01-1"
|
#define BACKEND_VERSION "0.01-2"
|
||||||
#define BACKEND_NAME plustek_pp
|
#define BACKEND_NAME plustek_pp
|
||||||
#include "sane/sanei_backend.h"
|
#include "sane/sanei_backend.h"
|
||||||
#include "sane/sanei_config.h"
|
#include "sane/sanei_config.h"
|
||||||
|
#include "sane/sanei_thread.h"
|
||||||
|
|
||||||
#ifdef HAVE_IOPERM
|
#ifdef HAVE_IOPERM
|
||||||
# define _BACKEND_ENABLED
|
# define _BACKEND_ENABLED
|
||||||
|
@ -321,58 +321,21 @@ static pModeParam getModeList( Plustek_Scanner *scanner )
|
||||||
return mp;
|
return mp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** function to check what our reader process returns. If the
|
|
||||||
* process didn't exist, we can be sure, that we had any other problems
|
|
||||||
*/
|
|
||||||
static SANE_Bool getReaderProcessExitCode( Plustek_Scanner *scanner )
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
scanner->exit_code = SANE_STATUS_IO_ERROR;
|
|
||||||
|
|
||||||
if( scanner->reader_pid > 0 ) {
|
|
||||||
|
|
||||||
res = waitpid( scanner->reader_pid, &status, WNOHANG );
|
|
||||||
|
|
||||||
if( res == scanner->reader_pid ) {
|
|
||||||
|
|
||||||
DBG( _DBG_INFO, "res=%i, status=%i\n",res,status );
|
|
||||||
|
|
||||||
if( WIFEXITED( status )) {
|
|
||||||
|
|
||||||
scanner->exit_code = WEXITSTATUS(status);
|
|
||||||
DBG( _DBG_INFO, "Child WEXITSTATUS = %d\n",scanner->exit_code);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if( !WIFSIGNALED( status )) {
|
|
||||||
scanner->exit_code = SANE_STATUS_GOOD;
|
|
||||||
DBG( _DBG_INFO, "Child termination okay\n" );
|
|
||||||
} else {
|
|
||||||
DBG( _DBG_ERROR, "Child terminated by signal %d\n",
|
|
||||||
WTERMSIG(status));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner->reader_pid = -1;
|
|
||||||
return SANE_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SANE_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
static SANE_Status close_pipe( Plustek_Scanner *scanner )
|
static SANE_Status close_pipe( Plustek_Scanner *scanner )
|
||||||
{
|
{
|
||||||
if( scanner->pipe >= 0 ) {
|
if( scanner->r_pipe >= 0 ) {
|
||||||
|
|
||||||
DBG( _DBG_PROC, "close_pipe\n" );
|
DBG( _DBG_PROC, "close r_pipe\n" );
|
||||||
|
close( scanner->r_pipe );
|
||||||
|
scanner->r_pipe = -1;
|
||||||
|
}
|
||||||
|
if( scanner->w_pipe >= 0 ) {
|
||||||
|
|
||||||
close( scanner->pipe );
|
DBG( _DBG_PROC, "close w_pipe\n" );
|
||||||
scanner->pipe = -1;
|
close( scanner->w_pipe );
|
||||||
|
scanner->w_pipe = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SANE_STATUS_EOF;
|
return SANE_STATUS_EOF;
|
||||||
|
@ -402,15 +365,31 @@ static RETSIGTYPE sigalarm_handler( int signo )
|
||||||
/** executed as a child process
|
/** executed as a child process
|
||||||
* read the data from the driver and send them to the parent process
|
* read the data from the driver and send them to the parent process
|
||||||
*/
|
*/
|
||||||
static int reader_process( Plustek_Scanner *scanner, int pipe_fd )
|
static int reader_process( void *args )
|
||||||
{
|
{
|
||||||
int line;
|
int line;
|
||||||
unsigned long status;
|
unsigned long status;
|
||||||
unsigned long data_length;
|
unsigned long data_length;
|
||||||
struct SIGACTION act;
|
struct SIGACTION act;
|
||||||
|
sigset_t ignore_set;
|
||||||
|
Plustek_Scanner *scanner = (Plustek_Scanner *)args;
|
||||||
|
|
||||||
DBG( _DBG_PROC, "reader_process started\n" );
|
if( sanei_thread_is_forked()) {
|
||||||
|
DBG( _DBG_PROC, "reader_process started (forked)\n" );
|
||||||
|
close( scanner->r_pipe );
|
||||||
|
scanner->r_pipe = -1;
|
||||||
|
} else {
|
||||||
|
DBG( _DBG_PROC, "reader_process started (as thread)\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
sigfillset ( &ignore_set );
|
||||||
|
sigdelset ( &ignore_set, SIGTERM );
|
||||||
|
sigprocmask( SIG_SETMASK, &ignore_set, 0 );
|
||||||
|
|
||||||
|
memset ( &act, 0, sizeof (act));
|
||||||
|
sigaction( SIGTERM, &act, 0 );
|
||||||
|
|
||||||
|
/* install the signal handler */
|
||||||
sigemptyset(&(act.sa_mask));
|
sigemptyset(&(act.sa_mask));
|
||||||
act.sa_flags = 0;
|
act.sa_flags = 0;
|
||||||
|
|
||||||
|
@ -449,7 +428,7 @@ static int reader_process( Plustek_Scanner *scanner, int pipe_fd )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
write( pipe_fd, buf, scanner->params.bytes_per_line );
|
write( scanner->w_pipe, buf, scanner->params.bytes_per_line );
|
||||||
|
|
||||||
buf += scanner->params.bytes_per_line;
|
buf += scanner->params.bytes_per_line;
|
||||||
}
|
}
|
||||||
|
@ -472,11 +451,9 @@ static int reader_process( Plustek_Scanner *scanner, int pipe_fd )
|
||||||
/* send to parent */
|
/* send to parent */
|
||||||
if( scanner->hw->readImage ) {
|
if( scanner->hw->readImage ) {
|
||||||
DBG( _DBG_PROC, "sending %lu bytes to parent\n", status );
|
DBG( _DBG_PROC, "sending %lu bytes to parent\n", status );
|
||||||
write( pipe_fd, scanner->buf, status );
|
write( scanner->w_pipe, scanner->buf, status );
|
||||||
}
|
}
|
||||||
|
|
||||||
pipe_fd = -1;
|
|
||||||
|
|
||||||
DBG( _DBG_PROC, "reader_process: finished reading data\n" );
|
DBG( _DBG_PROC, "reader_process: finished reading data\n" );
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
@ -508,18 +485,24 @@ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe )
|
||||||
|
|
||||||
act.sa_handler = sigalarm_handler;
|
act.sa_handler = sigalarm_handler;
|
||||||
sigaction( SIGALRM, &act, 0 );
|
sigaction( SIGALRM, &act, 0 );
|
||||||
|
|
||||||
/* kill our child process and wait until done */
|
|
||||||
kill( scanner->reader_pid, SIGTERM );
|
|
||||||
|
|
||||||
/* give'em 10 seconds 'til done...*/
|
/* kill our child process and wait until done */
|
||||||
alarm(10);
|
sanei_thread_kill( scanner->reader_pid );
|
||||||
res = waitpid( scanner->reader_pid, 0, 0 );
|
|
||||||
alarm(0);
|
/* give'em 10 seconds 'til done...*/
|
||||||
|
alarm(10);
|
||||||
|
res = sanei_thread_waitpid( scanner->reader_pid, 0 );
|
||||||
|
alarm(0);
|
||||||
|
|
||||||
if( res != scanner->reader_pid ) {
|
if( res != scanner->reader_pid ) {
|
||||||
DBG( _DBG_PROC,"waitpid() failed !\n");
|
DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n");
|
||||||
kill( scanner->reader_pid, SIGKILL );
|
|
||||||
|
/* do it the hard way...*/
|
||||||
|
#ifdef USE_PTHREAD
|
||||||
|
sanei_thread_kill( scanner->reader_pid );
|
||||||
|
#else
|
||||||
|
sanei_thread_sendsig( scanner->reader_pid, SIGKILL );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner->reader_pid = 0;
|
scanner->reader_pid = 0;
|
||||||
|
@ -1160,11 +1143,7 @@ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize )
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
DBG_INIT();
|
DBG_INIT();
|
||||||
|
sanei_thread_init();
|
||||||
#ifdef _PLUSTEK_USB
|
|
||||||
sanei_usb_init();
|
|
||||||
sanei_lm983x_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined PACKAGE && defined VERSION
|
#if defined PACKAGE && defined VERSION
|
||||||
DBG( _DBG_SANE_INIT, "PlustekPP backend V"BACKEND_VERSION", part of "
|
DBG( _DBG_SANE_INIT, "PlustekPP backend V"BACKEND_VERSION", part of "
|
||||||
|
@ -1366,7 +1345,8 @@ SANE_Status sane_open( SANE_String_Const devicename, SANE_Handle* handle )
|
||||||
return SANE_STATUS_NO_MEM;
|
return SANE_STATUS_NO_MEM;
|
||||||
|
|
||||||
memset(s, 0, sizeof (*s));
|
memset(s, 0, sizeof (*s));
|
||||||
s->pipe = -1;
|
s->r_pipe = -1;
|
||||||
|
s->w_pipe = -1;
|
||||||
s->hw = dev;
|
s->hw = dev;
|
||||||
s->scanning = SANE_FALSE;
|
s->scanning = SANE_FALSE;
|
||||||
|
|
||||||
|
@ -2028,7 +2008,9 @@ SANE_Status sane_start( SANE_Handle handle )
|
||||||
|
|
||||||
/* create reader routine as new process */
|
/* create reader routine as new process */
|
||||||
s->bytes_read = 0;
|
s->bytes_read = 0;
|
||||||
s->reader_pid = fork();
|
s->r_pipe = fds[0];
|
||||||
|
s->w_pipe = fds[1];
|
||||||
|
s->reader_pid = sanei_thread_begin( reader_process, s );
|
||||||
|
|
||||||
if( s->reader_pid < 0 ) {
|
if( s->reader_pid < 0 ) {
|
||||||
DBG( _DBG_ERROR, "ERROR: could not create child process\n" );
|
DBG( _DBG_ERROR, "ERROR: could not create child process\n" );
|
||||||
|
@ -2037,8 +2019,9 @@ SANE_Status sane_start( SANE_Handle handle )
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reader_pid = 0 ===> child process */
|
/* reader_pid = 0 ===> child process */
|
||||||
if( 0 == s->reader_pid ) {
|
#if 0
|
||||||
|
if( 0 == s->reader_pid ) {
|
||||||
|
|
||||||
sigset_t ignore_set;
|
sigset_t ignore_set;
|
||||||
struct SIGACTION act;
|
struct SIGACTION act;
|
||||||
|
@ -2061,11 +2044,13 @@ SANE_Status sane_start( SANE_Handle handle )
|
||||||
/* don't use exit() since that would run the atexit() handlers */
|
/* don't use exit() since that would run the atexit() handlers */
|
||||||
_exit( status );
|
_exit( status );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
signal( SIGCHLD, sig_chldhandler );
|
signal( SIGCHLD, sig_chldhandler );
|
||||||
|
|
||||||
close(fds[1]);
|
if( sanei_thread_is_forked()) {
|
||||||
s->pipe = fds[0];
|
close( s->w_pipe );
|
||||||
|
s->w_pipe = -1;
|
||||||
|
}
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "sane_start done\n" );
|
DBG( _DBG_SANE_INIT, "sane_start done\n" );
|
||||||
|
|
||||||
|
@ -2083,7 +2068,7 @@ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data,
|
||||||
*length = 0;
|
*length = 0;
|
||||||
|
|
||||||
/* here we read all data from the driver... */
|
/* here we read all data from the driver... */
|
||||||
nread = read( s->pipe, data, max_length );
|
nread = read( s->r_pipe, data, max_length );
|
||||||
DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread );
|
DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread );
|
||||||
if (!(s->scanning)) {
|
if (!(s->scanning)) {
|
||||||
return do_cancel( s, SANE_TRUE );
|
return do_cancel( s, SANE_TRUE );
|
||||||
|
@ -2093,10 +2078,10 @@ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data,
|
||||||
|
|
||||||
if( EAGAIN == errno ) {
|
if( EAGAIN == errno ) {
|
||||||
|
|
||||||
/* if we already had red the picture, so it's okay and stop */
|
/* if we had already red the picture, so it's okay and stop */
|
||||||
if( s->bytes_read ==
|
if( s->bytes_read ==
|
||||||
(unsigned long)(s->params.lines * s->params.bytes_per_line)) {
|
(unsigned long)(s->params.lines * s->params.bytes_per_line)) {
|
||||||
waitpid( s->reader_pid, 0, 0 );
|
sanei_thread_waitpid( s->reader_pid, 0 );
|
||||||
s->reader_pid = -1;
|
s->reader_pid = -1;
|
||||||
drvclose( s->hw );
|
drvclose( s->hw );
|
||||||
return close_pipe(s);
|
return close_pipe(s);
|
||||||
|
@ -2119,7 +2104,7 @@ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data,
|
||||||
if( 0 == nread ) {
|
if( 0 == nread ) {
|
||||||
|
|
||||||
drvclose( s->hw );
|
drvclose( s->hw );
|
||||||
getReaderProcessExitCode( s );
|
s->exit_code = sanei_thread_get_status( s->reader_pid );
|
||||||
|
|
||||||
if( SANE_STATUS_GOOD != s->exit_code ) {
|
if( SANE_STATUS_GOOD != s->exit_code ) {
|
||||||
close_pipe(s);
|
close_pipe(s);
|
||||||
|
@ -2156,12 +2141,12 @@ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( -1 == s->pipe ) {
|
if( -1 == s->r_pipe ) {
|
||||||
DBG( _DBG_ERROR, "ERROR: not supported !\n" );
|
DBG( _DBG_ERROR, "ERROR: not supported !\n" );
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) {
|
if( fcntl (s->r_pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) {
|
||||||
DBG( _DBG_ERROR, "ERROR: can´t set to non-blocking mode !\n" );
|
DBG( _DBG_ERROR, "ERROR: can´t set to non-blocking mode !\n" );
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -2183,7 +2168,7 @@ SANE_Status sane_get_select_fd( SANE_Handle handle, SANE_Int * fd )
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*fd = s->pipe;
|
*fd = s->r_pipe;
|
||||||
|
|
||||||
DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" );
|
DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" );
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
Ładowanie…
Reference in New Issue