[sane-devel] Fujitsu USB patches

Ron Cemer ron@roncemer.com
Tue, 11 Mar 2003 13:26:48 -0800


This is a multi-part message in MIME format.
--------------050501080703020005050807
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

The attached patch fixes the broken "ADF empty" detection on the Fujitsu 
scanners when connected via USB.  It also fixes a sense-request issues, 
which were required in order to determine whether the ADF is empty.  It 
also eliminates some duplicate code blocks.

The patch is against the March 3, 2003, CVS snapshot.

Can you apply this to the latest CVS?

Thanks!
Ron

--------------050501080703020005050807
Content-Type: text/plain;
 name="fujitsuPatch20030311.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="fujitsuPatch20030311.diff"

--- backend/fujitsu.c.ORIG	2003-03-02 18:11:10.000000000 -0800
+++ backend/fujitsu.c	2003-03-07 14:12:32.000000000 -0800
@@ -339,7 +339,7 @@
  * required for compressed data transfer. sense_handler has to tell
  * the caller the number of scanned bytes. 
  */
-static struct fujitsu *current_scanner;
+static struct fujitsu *current_scanner = NULL;
 
 /*
  * used by sane_get_devices
@@ -1985,28 +1985,14 @@
   if ((ret = fujitsu_send(scanner)))
     {
       DBG (5, "sane_start: ERROR: failed to start send command\n");
-      freeScanner (scanner);
-      if (scanner->connection == SANE_FUJITSU_USB) {
-	    sanei_usb_close (scanner->sfd);
-      } else if (scanner->connection == SANE_FUJITSU_SCSI) {
-	    sanei_scsi_close (scanner->sfd);
-      }
-      scanner->object_count = 0;
-      scanner->sfd = -1;
+      doCancel(scanner);
       return ret;
     }
 #if 0
   if ((ret = imprinter(scanner)))
     {
       DBG (5, "sane_start: ERROR: failed to start imprinter command\n");
-      freeScanner (scanner);
-      if (scanner->connection == SANE_FUJITSU_USB) {
-	    sanei_usb_close (scanner->sfd);
-      } else if (scanner->connection == SANE_FUJITSU_SCSI) {
-	    sanei_scsi_close (scanner->sfd);
-      }
-      scanner->object_count = 0;
-      scanner->sfd = -1;
+      doCancel(scanner);
       return ret;
     }
 #endif
@@ -2015,14 +2001,7 @@
       (ret = object_position (scanner, SANE_TRUE)))
     {
       DBG (5, "sane_start: WARNING: ADF empty\n");
-      freeScanner (scanner);
-      if (scanner->connection == SANE_FUJITSU_USB) {
-	    sanei_usb_close (scanner->sfd);
-      } else if (scanner->connection == SANE_FUJITSU_SCSI) {
-	    sanei_scsi_close (scanner->sfd);
-      }
-      scanner->object_count = 0;
-      scanner->sfd = -1;
+      doCancel(scanner);
       return ret;
     }
 
@@ -2032,14 +2011,7 @@
   if ((ret = setWindowParam (scanner)))
     {
       DBG (5, "sane_start: ERROR: failed to set window\n");
-      freeScanner (scanner);
-      if (scanner->connection == SANE_FUJITSU_USB) {
-	    sanei_usb_close (scanner->sfd);
-      } else if (scanner->connection == SANE_FUJITSU_SCSI) {
-	    sanei_scsi_close (scanner->sfd);
-      }
-      scanner->object_count = 0;
-      scanner->sfd = -1;
+      doCancel(scanner);
       return ret;
     }
 
@@ -2059,13 +2031,7 @@
     {
       DBG (MSG_ERR, "ERROR: could not create pipe\n");
       scanner->object_count = 0;
-      freeScanner (scanner);
-      if (scanner->connection == SANE_FUJITSU_USB) {
-	    sanei_usb_close (scanner->sfd);
-      } else if (scanner->connection == SANE_FUJITSU_SCSI) {
-	    sanei_scsi_close (scanner->sfd);
-      }
-      scanner->sfd = -1;
+      doCancel(scanner);
       return SANE_STATUS_IO_ERROR;
     }
 
@@ -2078,13 +2044,7 @@
             {
               DBG (MSG_ERR, "ERROR: could not create temporary file.\n");
               scanner->object_count = 0;
-              freeScanner (scanner);
-	      if (scanner->connection == SANE_FUJITSU_USB) {
-		    sanei_usb_close (scanner->sfd);
-	      } else if (scanner->connection == SANE_FUJITSU_SCSI) {
-		    sanei_scsi_close (scanner->sfd);
-	      }
-              scanner->sfd = -1;
+	      doCancel(scanner);
               return SANE_STATUS_IO_ERROR;
             }
         }
@@ -2094,13 +2054,7 @@
             {
               DBG (MSG_ERR, "ERROR: could not create duplex pipe.\n");
               scanner->object_count = 0;
-              freeScanner (scanner);
-	      if (scanner->connection == SANE_FUJITSU_USB) {
-		    sanei_usb_close (scanner->sfd);
-	      } else if (scanner->connection == SANE_FUJITSU_SCSI) {
-		    sanei_scsi_close (scanner->sfd);
-	      }
-              scanner->sfd = -1;
+	      doCancel(scanner);
               return SANE_STATUS_IO_ERROR;
             }
         }
@@ -2518,11 +2472,10 @@
     {
     case 0x0:                   /* No Sense */
       DBG (5, "\t%d/%d/%d: Scanner ready\n", sense, asc, ascq);
-      if (get_RS_EOM (sensed_data))
-        {
+      if ( (current_scanner != NULL) && (get_RS_EOM (sensed_data)) ) {
           current_scanner->i_transfer_length = get_RS_information (sensed_data);
           return SANE_STATUS_EOF;
-        }
+      }
       return SANE_STATUS_GOOD;
 
     case 0x2:                   /* Not Ready */
@@ -2730,6 +2683,9 @@
 static void
 doInquiry (struct fujitsu *s)
 {
+  int i, tries = (s->connection == SANE_FUJITSU_USB) ? 5 : 1;
+  size_t res;
+
   DBG (10, "do_inquiry\n");
 
   memset (s->buffer, '\0', 256);        /* clear buffer */
@@ -2739,8 +2695,15 @@
  
   hexdump (MSG_IO, "inquiry", inquiryB.cmd, inquiryB.size);
 
-  do_cmd (s->connection, s->sfd, inquiryB.cmd, inquiryB.size,
-	       s->buffer, 96, NULL);
+  for (i = 0; i < tries; i++) {
+    DBG(10, "try inquiry %d\n", i);
+    if (   (do_cmd (s->connection, s->sfd, inquiryB.cmd, inquiryB.size,
+	    s->buffer, 96, &res) == SANE_STATUS_GOOD)
+	&& (res >= 96)   ) {
+	break;
+    }
+    usleep(100000L);
+  }
 }
 
 static SANE_Status
@@ -2991,8 +2954,8 @@
     int op_code = 0;
     int i, j;
     int tries = 0;
+    int status_byte = 0;
     unsigned char buf[1024];
-/*    unsigned char sense_bytes[64]; */
 
 retry:
     hexdump (IO_CMD, "<cmd<", cmd, cmd_len);
@@ -3020,9 +2983,9 @@
 	    /* 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 (IO_CMD, "try to write %u bytes\n", cnt);
+	DBG (10, "try to write %u bytes\n", cnt);
 	ret = sanei_usb_write_bulk(fd, &buf[j], &cnt);
-	DBG (IO_CMD, "wrote %u bytes\n", cnt);
+	DBG (10, "wrote %u bytes\n", cnt);
 	if (ret != SANE_STATUS_GOOD) break;
 	j += cnt;
     }
@@ -3033,32 +2996,45 @@
     ol = 0;
     if (ret == SANE_STATUS_GOOD) {
 	if ( (out != NULL) && (req_out_len > 0) ) {
-	    while (ol < req_out_len) {
+/*	    while (ol < req_out_len) { */
 		cnt = (size_t)(req_out_len-ol);
-		DBG (IO_CMD, "try to read %u bytes\n", cnt);
+		DBG (10, "try to read %u bytes\n", cnt);
 		ret = sanei_usb_read_bulk(fd, &out[ol], &cnt);
-		DBG (IO_CMD, "read %u bytes\n", cnt);
+		DBG (10, "read %u bytes\n", cnt);
 		if (cnt > 0) {
 		    hexdump (IO_CMD, "*** Data read:", &out[ol], cnt);
 		}
 		if (ret != SANE_STATUS_GOOD) {
 		    DBG(MSG_ERR, "*** Got error %d trying to read\n", ret);
 		}
-		if (ret != SANE_STATUS_GOOD) break;
+/*		if (ret != SANE_STATUS_GOOD) break; */
 		ol += cnt;
-	    }
+/*	    } */
 	}
 
-	DBG(MSG_ERR, "*** Try to read CSW\n");
-	cnt = sizeof(buf);
+	DBG(10, "*** Try to read CSW\n");
+	cnt = 13;
 	sanei_usb_read_bulk(fd, buf, &cnt);
 	hexdump (IO_CMD, "*** Read CSW", buf, cnt);
+
+	status_byte = ((int)buf[9]) & 0xff;
+	if (status_byte != 0) {
+	    DBG
+		(MSG_ERR,
+		 "Got bad status: %2.2x op_code=%2.2x ret=%d req_out_len=%u ol=%u\n",
+		 status_byte,
+		 op_code,
+		 ret,
+		 req_out_len,
+		 ol);
+	}
     }
 
 	/* Auto-retry failed data reads, in case the scanner is busy. */
     if ( (op_code == READ) && (tries < 100) && (ol == 0) ) {
 	usleep(100000L);
 	tries++;
+	DBG(MSG_ERR, "read failed; retry %d\n", tries);
 	goto retry;
     }
 
@@ -3085,6 +3061,22 @@
       hexdump (IO_CMD_RES, ">rslt>", out, (ol > 0x60) ? 0x60 : ol);
     }
 
+/*  if ( (op_code == OBJECT_POSITION) || (op_code == TEST_UNIT_READY) ) { */
+  if (status_byte == 0x02) {	/* check condition */
+      /* Issue a REQUEST_SENSE command and pass the resulting sense data
+         into the scsiSenseHandler routine.  */
+    memset(buf, 0, 18);
+    if (do_usb_cmd
+	  (fd,
+	   request_senseB.cmd,
+	   request_senseB.size,
+	   buf,
+	   18,
+	   NULL) == SANE_STATUS_GOOD) {
+      ret = scsiSenseHandler(fd, buf, NULL);
+    }
+  }
+
   return ret;
 }
 
@@ -3739,6 +3731,7 @@
       DBG(10, "data read = %d data requested = %d\n", *i_data_read, length);
     }
 
+  current_scanner = NULL;
   return status;
 }
 
@@ -4040,7 +4033,6 @@
       s->compression_mode_list[1] = NULL;
     }
 
-
   if (SANE_STATUS_GOOD == getVitalProductData (s))
     {
       /* This scanner supports vital product data.
--- backend/fujitsu-scsi.h.ORIG	2003-03-02 18:11:10.000000000 -0800
+++ backend/fujitsu-scsi.h	2003-03-05 12:19:28.000000000 -0800
@@ -914,12 +914,11 @@
 
 /* ==================================================================== */
 
-/*
   static unsigned char request_senseC[] =
-  {REQUEST_SENSE, 0x00, 0x00, 0x00, 0x00, 0x00};
+  {REQUEST_SENSE, 0x00, 0x00, 0x00, 0x12, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
   static scsiblk request_senseB =
   {request_senseC, sizeof (request_senseC)};
-*/
 
 #define set_RS_allocation_length(sb,val) sb[0x04] = (unsigned char)val
 /* defines for request sense return block */

--------------050501080703020005050807--