mustek 3-pass backend now working!

David Mosberger-Tang (davidm@azstarnet.com)
Thu, 17 Apr 1997 11:41:45 -0700

OK, thanks to the patience of Mathias Weigt, 3-pass scanning with the
Mustek backend now finally seems to work. Below is a patch relative
to sane-0.53 that should get things working (until sane-0.54 comes
out).

If you have a 3-pass Mustek scanner, could you please try this patch
and let me know if/how it works? If it works, could you send me the
following info so I can update the README file?

- Exact scanner type: label on front of scanner & the SCSI id string & firmware version

- the SCSI card you're using

The SCSI id and firmware rev can be obtained like this:

SANE_DEBUG_MUSTEK=128 scan -h -d mustek >/dev/null

Enjoy,

--david

--
--- sane-0.53/backend/mustek.c	Fri Apr 11 22:23:38 1997
+++ sane-0.54/backend/mustek.c	Thu Apr 17 09:03:49 1997
@@ -264,8 +264,9 @@
   if (strncmp (model_name, "MFS-12000CX", 11) == 0)
     {
       dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH);
-      dev->y_range.max = SANE_FIX (14.0 * MM_PER_INCH); /* is this correct? */
+      dev->y_range.max = SANE_FIX (14.0 * MM_PER_INCH);
       dev->dpi_range.max = SANE_FIX (1200);
+      dev->flags |= MUSTEK_FLAG_USE_EIGHTS;
     }
   else if (strncmp (model_name, "MFS-06000CX", 11) == 0)
     {
@@ -361,8 +362,11 @@
   if (result[63] & (1 << 6))
     dev->flags |= MUSTEK_FLAG_TA;
 
-  DBG(3, "attach: found Mustek scanner model %s (%s)\n",
-      dev->sane.model, dev->sane.type);
+  DBG(3, "attach: found Mustek scanner model %s (%s), %s%s%s\n",
+      dev->sane.model, dev->sane.type,
+      (dev->flags & MUSTEK_FLAG_SINGLE_PASS) ? "1-pass" : "3-pass",
+      (dev->flags & MUSTEK_FLAG_ADF) ? ", ADF" : "",
+      (dev->flags & MUSTEK_FLAG_TA)  ? ", TA" : "");
 
   ++num_devices;
   dev->next = first_dev;
@@ -552,15 +556,17 @@
 
   if (s->hw->flags & MUSTEK_FLAG_USE_EIGHTS)
     {
+      double eights_per_mm = 8 / MM_PER_INCH;
+
       /*
        * The MSF-06000CZ seems to lock-up if the pixel-unit is used.
        * Using 1/8" works.
        */
       *cp++ = ((s->mode & MUSTEK_MODE_HALFTONE) ? 0x01 : 0x00);
-      STORE16(cp, SANE_UNFIX(s->val[OPT_TL_X].w) * 8 / MM_PER_INCH + 0.5);
-      STORE16(cp, SANE_UNFIX(s->val[OPT_TL_Y].w) * 8 / MM_PER_INCH + 0.5);
-      STORE16(cp, SANE_UNFIX(s->val[OPT_BR_X].w) * 8 / MM_PER_INCH + 0.5);
-      STORE16(cp, SANE_UNFIX(s->val[OPT_BR_Y].w) * 8 / MM_PER_INCH + 0.5);
+      STORE16(cp, SANE_UNFIX(s->val[OPT_TL_X].w) * eights_per_mm + 0.5);
+      STORE16(cp, SANE_UNFIX(s->val[OPT_TL_Y].w) * eights_per_mm + 0.5);
+      STORE16(cp, SANE_UNFIX(s->val[OPT_BR_X].w) * eights_per_mm + 0.5);
+      STORE16(cp, SANE_UNFIX(s->val[OPT_BR_Y].w) * eights_per_mm + 0.5);
     }
   else
     {
@@ -690,7 +696,7 @@
       if (s->hw->flags & MUSTEK_FLAG_SINGLE_PASS)
 	start[4] |= 0x20;
       else
-	start[4] |= ((s->pass << 3) + 1);
+	start[4] |= ((s->pass + 1) << 3);
     }
   /* or in single/multi bit: */
   start[4] |= (s->mode & MUSTEK_MODE_MULTIBIT) ? (1 << 6) : 0;
@@ -1315,55 +1321,53 @@
 	  DBG(1, "reader_process: read_data failed with status=%d\n", status);
 	  return 3;
 	}
+      DBG(3, "reader_process: read %d lines", lines_per_buffer);
 
       /* convert to pixel-interleaved format: */
-      if (s->mode & MUSTEK_MODE_COLOR)
+      if ((s->mode & MUSTEK_MODE_COLOR)
+	  && (s->hw->flags & MUSTEK_FLAG_SINGLE_PASS))
 	{
-	  if (s->hw->flags & MUSTEK_FLAG_SINGLE_PASS)
-	    {
-	      SANE_Byte *src;
+	  SANE_Byte *src;
 
-	      if (s->hw->flags & MUSTEK_FLAG_LD_MFS)
-		fix_line_distance_mfs (s, lines_per_buffer, bpl, data, extra);
-	      else if (s->ld.max_value)
-		/* need to correct for distance between r/g/b sensors: */
-		fix_line_distance_normal (s, lines_per_buffer, bpl, data,
-					  extra);
-	      else
-		memcpy (extra, data, lines_per_buffer * bpl);
+	  if (s->hw->flags & MUSTEK_FLAG_LD_MFS)
+	    fix_line_distance_mfs (s, lines_per_buffer, bpl, data, extra);
+	  else if (s->ld.max_value)
+	    /* need to correct for distance between r/g/b sensors: */
+	    fix_line_distance_normal (s, lines_per_buffer, bpl, data, extra);
+	  else
+	    memcpy (extra, data, lines_per_buffer * bpl);
 
-	      src = extra;
-	      if (s->mode & MUSTEK_MODE_MULTIBIT)
+	  src = extra;
+	  if (s->mode & MUSTEK_MODE_MULTIBIT)
+	    {
+	      /* each r/g/b sample is 8 bits in line-interleaved format */
+	      for (y = 0; y < lines_per_buffer; ++y)
 		{
-		  /* each r/g/b sample is 8 bits in line-interleaved format */
-		  for (y = 0; y < lines_per_buffer; ++y)
+		  for (x = 0; x < bpl / 3; ++x)
 		    {
-		      for (x = 0; x < bpl / 3; ++x)
-			{
-			  fputc (src[0 * bpl / 3 + x], fp);
-			  fputc (src[1 * bpl / 3 + x], fp);
-			  fputc (src[2 * bpl / 3 + x], fp);
-			}
-		      src += bpl;
+		      fputc (src[0 * bpl / 3 + x], fp);
+		      fputc (src[1 * bpl / 3 + x], fp);
+		      fputc (src[2 * bpl / 3 + x], fp);
 		    }
+		  src += bpl;
 		}
-	      else
+	    }
+	  else
+	    {
+	      /* each r/g/b/ sample is 1 bit in line-interleaved format */
+#	      define EXPAND(b, v) (((v) & (1 << (bit))) ? 0xff : 0x00)
+	      for (y = 0; y < lines_per_buffer; ++y)
 		{
-		  /* each r/g/b/ sample is 1 bit in line-interleaved format */
-#		  define EXPAND(b, v) (((v) & (1 << (bit))) ? 0xff : 0x00)
-		  for (y = 0; y < lines_per_buffer; ++y)
+		  for (x = 0; x < bpl / 3; ++x)
 		    {
-		      for (x = 0; x < bpl / 3; ++x)
+		      for (bit = 7; bit >= 0; --bit)
 			{
-			  for (bit = 7; bit >= 0; --bit)
-			    {
-			      fputc (EXPAND (bit, src[0 * bpl / 3 + x]), fp);
-			      fputc (EXPAND (bit, src[1 * bpl / 3 + x]), fp);
-			      fputc (EXPAND (bit, src[2 * bpl / 3 + x]), fp);
-			    }
+			  fputc (EXPAND (bit, src[0 * bpl / 3 + x]), fp);
+			  fputc (EXPAND (bit, src[1 * bpl / 3 + x]), fp);
+			  fputc (EXPAND (bit, src[2 * bpl / 3 + x]), fp);
 			}
-		      src += bpl;
 		    }
+		  src += bpl;
 		}
 	    }
 	}
@@ -1757,11 +1761,11 @@
 sane_get_parameters (SANE_Handle handle, SANE_Parameters *params)
 {
   Mustek_Scanner *s = handle;
+  const char *mode;
 
   if (!s->scanning)
     {
       double width, height, dpi;
-      const char *mode;
 
       memset (&s->params, 0, sizeof (s->params));
 
@@ -1778,53 +1782,50 @@
 	  s->params.pixels_per_line = width * dots_per_mm;
 	  s->params.lines = height * dots_per_mm;
 	}
+    }
+  mode = s->val[OPT_MODE].s;
+  if (strcmp (mode, "Lineart") == 0 || strcmp (mode, "Halftone") == 0)
+    {
+      s->params.format = SANE_FRAME_GRAY;
+      s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8;
+      s->params.depth = 1;
+    }
+  else if (strcmp (mode, "Gray") == 0)
+    {
+      s->params.format = SANE_FRAME_GRAY;
+      s->params.bytes_per_line = s->params.pixels_per_line;
+      s->params.depth = 8;
+    }
+  else
+    {
+      /* it's one of the color modes... */
 
-      mode = s->val[OPT_MODE].s;
-      if (strcmp (mode, "Lineart") == 0 || strcmp (mode, "Halftone") == 0)
-	{
-	  s->params.format = SANE_FRAME_GRAY;
-	  s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8;
-	  s->params.depth = 1;
-	}
-      else if (strcmp (mode, "Gray") == 0)
+      if (s->hw->flags & MUSTEK_FLAG_SINGLE_PASS)
 	{
-	  s->params.format = SANE_FRAME_GRAY;
-	  s->params.bytes_per_line = s->params.pixels_per_line;
+	  /* all color modes are treated the same since lineart and
+	     halftoning with 1 bit color pixels still results in 3
+	     bytes/pixel.  */
+	  s->params.format = SANE_FRAME_RGB;
+	  s->params.bytes_per_line = 3 * s->params.pixels_per_line;
 	  s->params.depth = 8;
 	}
       else
 	{
-	  /* all color modes are treated the same since lineart with 1
-	     bit color pixels still results in 3 bytes/pixel.  */
-	  if (s->hw->flags & MUSTEK_FLAG_SINGLE_PASS)
+	  s->params.format = SANE_FRAME_RED + s->pass;
+	  if (strcmp (mode, "Color") == 0)
 	    {
-	      s->params.format = SANE_FRAME_RGB;
-	      s->params.bytes_per_line = 3 * s->params.pixels_per_line;
+	      s->params.bytes_per_line = s->params.pixels_per_line;
 	      s->params.depth = 8;
 	    }
 	  else
 	    {
-	      switch (s->pass)
-		{
-		case 0:
-		  s->params.format = SANE_FRAME_RED;
-		  break;
-		case 1:
-		  s->params.format = SANE_FRAME_GREEN;
-		  break;
-		case 2:
-		  s->params.format = SANE_FRAME_BLUE;
-		  break;
-		default:
-		  break;
-		}
-	      s->params.bytes_per_line = s->params.pixels_per_line;
-	      s->params.depth = 8;
+	      s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8;
+	      s->params.depth = 1;
 	    }
 	}
-      s->params.last_frame = (s->params.format != SANE_FRAME_RED
-			      && s->params.format != SANE_FRAME_GREEN);
     }
+  s->params.last_frame = (s->params.format != SANE_FRAME_RED
+			  && s->params.format != SANE_FRAME_GREEN);
   if (params)
     *params = s->params;
   return SANE_STATUS_GOOD;
@@ -1843,18 +1844,9 @@
   if (status != SANE_STATUS_GOOD)
       return status;
 
-  if (s->fd >= 0)
-    {
-      /* this is the second or third pass... */
-      status = wait_ready (s->fd);
-      if (status != SANE_STATUS_GOOD)
-	{
-	  DBG(1, "open: wait_ready() failed: %s\n", sane_strstatus (status));
-	  goto stop_scanner_and_return;
-	}
-    }
-  else
+  if (s->fd < 0)
     {
+      /* this is the first (and maybe only) pass... */
       const char *mode;
 
       /* translate options into s->mode for convenient access: */
@@ -1883,34 +1875,34 @@
 	      s->hw->sane.name, sane_strstatus (status));
 	  return status;
 	}
+    }
 
-      status = wait_ready (s->fd);
-      if (status != SANE_STATUS_GOOD)
-	{
-	  DBG(1, "open: wait_ready() failed: %s\n", sane_strstatus (status));
-	  goto stop_scanner_and_return;
-	}
+  status = wait_ready (s->fd);
+  if (status != SANE_STATUS_GOOD)
+    {
+      DBG(1, "open: wait_ready() failed: %s\n", sane_strstatus (status));
+      goto stop_scanner_and_return;
+    }
 
-      status = scan_area_and_windows (s);
-      if (status != SANE_STATUS_GOOD)
-	{
-	  DBG(1, "open: set scan area command failed: %s\n",
-	      sane_strstatus (status));
-	  goto stop_scanner_and_return;
-	}
+  status = scan_area_and_windows (s);
+  if (status != SANE_STATUS_GOOD)
+    {
+      DBG(1, "open: set scan area command failed: %s\n",
+	  sane_strstatus (status));
+      goto stop_scanner_and_return;
+    }
 
-      status = request_sense (s);
-      if (status != SANE_STATUS_GOOD)
-	goto stop_scanner_and_return;
+  status = request_sense (s);
+  if (status != SANE_STATUS_GOOD)
+    goto stop_scanner_and_return;
 
-      status = backtrack_and_adf (s);
-      if (status != SANE_STATUS_GOOD)
-	goto stop_scanner_and_return;
+  status = backtrack_and_adf (s);
+  if (status != SANE_STATUS_GOOD)
+    goto stop_scanner_and_return;
 
-      status = request_sense (s);
-      if (status != SANE_STATUS_GOOD)
-	goto stop_scanner_and_return;
-    }
+  status = request_sense (s);
+  if (status != SANE_STATUS_GOOD)
+    goto stop_scanner_and_return;
 
   if (s->one_pass_color_scan)
     {
@@ -2042,6 +2034,7 @@
   *len = 0;
 
   nread = read (s->pipe, buf, max_len);
+  DBG(3, "read %ld bytes\n", (long) nread);
 
   if (!s->scanning)
     return do_cancel (s);

--
Source code, list archive, and docs: http://www.azstarnet.com/~axplinux/sane/
To unsubscribe: mail -s unsubscribe sane-devel-request@listserv.azstarnet.com