[sane-devel] scanimage problem / sane 1.0.8 / Epson / Solaris 8 (x86)

Ed Randall ed.randall@ingenotech.com
Thu, 27 Jun 2002 16:12:52 +0100


> > I can run scanimage with the default resolution (50) fine;
> > but if I want more detail than that, if I put a "--resolution"
> > option on there, half-way through the scan I get:
> > 
> > $ scanimage --mode gray --resolution 72 >out
> > scanimage: sane_read: Error during device I/O
> >
> > [500 lines of debug output that goes here is
> > available at http://www.ingenotech.com/tmp/sane_debug.txt]
> 
> Scanner initialization seems to work. Then:
> 
> [epson] receive buf, expected = 128520, got = 0
> 
> I don't know the epson code nor Solaris but maybe your driver doesn't
> like this big buffer? The maximum buffer size is set to 128 kB for
> Solaris in sanei_scsi.c however, so it should be allright. Maybe you
> want to reduce the value to e.g. 64kb just to give it a try if
> everything else failse.
> 
> You will get more details when you additionally set
> SANE_DEBUG_SANEI_SCSI=255.


One thing that was immediately apparent by setting 
SANE_DEBUG_SANEI_SCSI=255 was that it was looking for devices other
than my Epson scanner, the first it tried was /dev/camera...a
bit more investigation led me to edit dll.conf and comment out
all those extra devices that are enabled by default.
This didn't fix the problem(s) though, in to the bargain I started 
getting very frequent SIGSEGV's.

I made some debugging code changes to epson.c (see "diff -c" patch
output below) to debug data buffers in a controlled-length hex dump 
instead of 1 byte per line.  There was some code already there to 
do that true, but 
(a) it didn't do it exactly the way I needed, and was slightly
complicated, I couldn't see immediately exactly what it was doing, and
(b) it needed to be in a function so I could use it from a couple
of places.  You could hopefully move it out into a more general
file and use it elsewhere now.

Recompiling with a 64k buffer size didn't seem to make much difference
last night, but today it has - I think my "make install" hadn't worked
cleanly.  Today, in conjunction with the change to dll.conf, it seems 
to have mostly fixed the I/O error and SEGV problems.  I can run xsane
reasonably reliably which was the object of the exercise.

I think there's a lot of non-intrusive interaction going on between 
the various backends that are enabled by default, the initial default
installation maybe needs to be a bit more careful on the settings for
the sake of naive lazy users who just want to scan and not be 
software configuration experts ;-)

A couple of side issues I encountered during installation - the sane-config 
script that gets installed is no longer compatible with the ./configure in 
xsane 0.86, lots of usage messages pop up.  Also it uses "echo -e $usage" in 
lots of places, this may work on Linux/Bash but it is not portable /bin/sh 
behaviour for the Solaris nor the rest of the Unix world ;-)

Anybody who has tried installing gtk, glib and sane in a non-standard
place (ie not /usr/local/bin) as I have will probably agree with me that
the ./configure process for dependant applications has now become much harder.
Whilst the XXX-config script is intended to report back locations of critical
parts, the ./configure seems unable to do the right thing - it can't find the
XXX-config script unless I put it on the path (DESPITE having a separate
--with-XXX=path-to-XXX-config option TELLING it exactly where to look) and
even then I find myself having to set LD_LIBRARY_PATH, LDFLAGS, CFLAGS and 
CPPFLAGS variables to help it along - this shouldn't be necessary.
Perhaps Linux people don't have this trouble - but if all the world is to run 
Linux, why bother with ./configure ? :-)))

Do you need contributors?  When I get more time maybe I'll take a look
at joining in and trying to help fix some of these issues.

Regards,

Ed



diff -c sane-backends-1.0.8/backend/epson.c sane-backends-1.0.8-new/backend/epson.c
*** sane-backends-1.0.8/backend/epson.c Mon Apr 22 19:03:44 2002
--- sane-backends-1.0.8-new/backend/epson.c     Thu Jun 27 15:55:32 2002
***************
*** 301,306 ****
--- 301,311 ----
  #define  TYPE_PROCESSOR                       0x03
  
  
+ #define HEXDUMP_MAX_SIZE        (320)
+ #define HEXDUMP_LINE_LENGTH     (16)
+ void     hexdump(int level, char* prefix, u_char* buf, ssize_t buf_size, ssize_t dump_size);
+ 
+ 
  /*
   * sense handler for the sanei_scsi_XXX comands
   */
***************
*** 398,405 ****
  #     define  XtOffsetOf(s_type,field)  XtOffset(s_type*,field)
  #endif
  
- #define NUM_OF_HEX_ELEMENTS (16)
- 
  /* NOTE: you can find these codes with "man ascii". */
  #define        STX    0x02
  #define        ACK    0x06
--- 403,408 ----
***************
*** 889,905 ****
  
        DBG( 3, "send buf, size = %lu\n", ( u_long) buf_size);
  
! #if 1
!       {
!               size_t k;
!               const u_char * s = buf;
  
-               for( k = 0; k < buf_size; k++) {
-                       DBG( 125, "buf[%u] %02x %c\n", k, s[ k], isprint( s[ k]) ? s[ k] : '.');
-               }
-       }
- #endif
- 
        if( s->hw->connection == SANE_EPSON_SCSI) {
                return scsi_write( s->fd, buf, buf_size, status);
        } else if (s->hw->connection == SANE_EPSON_PIO) {
--- 892,899 ----
  
        DBG( 3, "send buf, size = %lu\n", ( u_long) buf_size);
  
!         hexdump(125, "send buf", (u_char*)buf, buf_size, HEXDUMP_MAX_SIZE);
  
        if( s->hw->connection == SANE_EPSON_SCSI) {
                return scsi_write( s->fd, buf, buf_size, status);
        } else if (s->hw->connection == SANE_EPSON_PIO) {
***************
*** 963,1034 ****
  
        DBG( 7, "receive buf, expected = %lu, got = %d\n", ( u_long) buf_size, n);
  
! #if 1
!       if (n > 0)
!       {
!               ssize_t k;
!               const u_char * s = buf;
  
!               for( k = 0; k < n; k++) {
!                       DBG( 127, "buf[%u] %02x %c\n", k, s[ k], isprint( s[ k]) ? s[ k] : '.');
!               }
!       }
! #else
!       {
!               int i;
!               ssize_t k;
!               ssize_t hex_start = 0;
!               const u_char * s = buf;
!               char hex_str[NUM_OF_HEX_ELEMENTS*3+1];
!               char tmp_str[NUM_OF_HEX_ELEMENTS*3+1];
!               char ascii_str[NUM_OF_HEX_ELEMENTS*2+1];
  
-               hex_str[0] = '\0';
-               ascii_str[0] = '\0';
  
!               for (k=0; k<buf_size; k++)
!               {
!                       /* write out the data in lines of 16 bytes */
!                       /* add the next hex value to the hex string */
!                       sprintf(tmp_str, "%s %02x", hex_str, s[k]);
!                       strcpy(hex_str, tmp_str);
  
!                       /* add the character to the ascii string */
!                       sprintf(tmp_str, "%s %c",  ascii_str, isprint( s[k]) ? s[k] : '.');
!                       strcpy(ascii_str, tmp_str);
! 
!                       if ((k % (NUM_OF_HEX_ELEMENTS)) == 0)
!                       {
!                               if (k!=0)       /* don't do this the first time */
!                               {
! fprintf(stderr, "running from i=%d to %d\n", strlen(hex_str), NUM_OF_HEX_ELEMENTS*3);
!                                       for (i = strlen(hex_str); i < (NUM_OF_HEX_ELEMENTS*3); i++)
!                                       {
!                                               hex_str[i] = ' ';
!                                       }
!                                       hex_str[NUM_OF_HEX_ELEMENTS+1] = '\0';
! 
!                                       DBG(125, "recv buf[%05d]: %s   %s\n", hex_start, hex_str, ascii_str);
!                                       hex_start = k;
!                                       hex_str[0] = '\0';
!                                       ascii_str[0] = '\0';
!                               }
!                       }
!               }
! 
!               for (i = strlen(hex_str); i < NUM_OF_HEX_ELEMENTS*3; i++)
!               {
!                       hex_str[i] = ' ';
!               }
!               hex_str[NUM_OF_HEX_ELEMENTS+1] = '\0';
! 
!               DBG(125, "recv buf[%05d]: %s   %s\n", hex_start, hex_str, ascii_str);
!       }
! #endif
! 
!       return n;
  }
  
  /*
   *
   *
--- 957,1029 ----
  
        DBG( 7, "receive buf, expected = %lu, got = %d\n", ( u_long) buf_size, n);
  
!         hexdump(127, "recv buf", (u_char*)buf, n, HEXDUMP_MAX_SIZE);
  
!       return n;
! }
  
  
! /**
! * Display large buffers as a hex dump for debugging.
! */
! void     hexdump(int level, char* prefix, u_char* buf, ssize_t buf_size, ssize_t dump_size)
! {
!     char    hex[4];
!     char    ascii[3];
!     char    hex_str[HEXDUMP_LINE_LENGTH*3+3];
!     char    ascii_str[HEXDUMP_LINE_LENGTH*2+3];
!     ssize_t i;
!     int     j;
!     ssize_t k;
!     
!     if (prefix == NULL)
!     {
!         prefix = "";
!     }
!     
!     if (buf == NULL) 
!     {
!         DBG(level, "%s buf==NULL buf_size=%d\n", prefix, buf_size);
!         return;
!     }
!     
!     for (i=0; i<buf_size && i<dump_size; i += HEXDUMP_LINE_LENGTH)
!     {
!         hex_str[0] = '\0';
!         ascii_str[0] = '\0';
!         
!         for (j=0; j<HEXDUMP_LINE_LENGTH; j++)
!         {
!             k = i + j;
!             if (k < buf_size)
!             {
!                 sprintf(hex, "%02x ", buf[k]);
!                 sprintf(ascii, "%c ", isprint(buf[k]) ? buf[k] : '.');
!             }
!             else
!             {
!                 strcpy(hex, "   ");
!                 strcpy(ascii, "  ");
!             }
  
!             if (j == HEXDUMP_LINE_LENGTH/2) {
!                 strcat(hex_str, " ");
!                 strcat(ascii_str, " ");
!             }
!             strcat(hex_str, hex);
!             strcat(ascii_str, ascii);
!             
!         }
!         
!         DBG(level, "%s[%05x]  %s  %s\n", prefix, i, hex_str, ascii_str);
!     }
!     
!     if (i < buf_size) {
!         DBG(level, "%s[%05x] ... %d further lines truncated ...\n", prefix, i, (buf_size-i)/HEXDUMP_LINE_LENGTH);
!     }
  }
  
+ 
  /*
   *
   *