[sane-devel] HP 8250 ADF doesn't work (patch)

Mike Kelly mike at piratehaven.org
Mon Sep 13 13:15:33 UTC 2010


Hi,

I own an HP 8250 scanner, but the ADF unit doesn't work with sane.  In my
attempt to find a solution I stumbled upon Debian bug 521410
(http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=521410).  In this bug, it
is reported that scanning used to work with a previous version of avision.c,
but that with later versions the ADF stopped working.  With the supplied log
files in that bug, I decided to try to figure out what changed in the source
and see if I could return the functionality.

I went through every change in avision.c, going back until June of 2006,
until I narrowed the problem down to a bit field which used to have one of
two bits set for all ADF scanners but was later changed to only set the bits
based on ADF capabilities.  Unfortunately the new code which determines the
ADF's capabilities excludes this scanner.

There are two core problems:
1) The first is that the code is trying to determine the ADF model from the
   scanner, but the returned value from the scanner is not giving us enough
   information to determine what the capabilities are for the ADF.
2) The second is that the code added to correctly set the scanner bits for
   2-pass duplex scanners sets a completely different set of bits than
   before.

About the first problem (detecting the ADF):

The code uses a byte value returned from the scanner labeled "adf_model" in
the source, but the returned value is a value in the range of 0 to 2.
Although the code assigns model names to these values, it seems that
different scanners, with clearly different ADF units, return the same model
number, so the names can't possibly be valid.  How HP uses this byte is
unclear, but I suspect that if it is used at all, there is a lookup table to
determine the ADF features based on the scanner model.  I've looked at debug
logs for almost all of the supported scanners to support this conclusion.

In fact, having reviewed the documentation of each supported model and its
ADF capabilities, I have concluded that this byte can be safely ignored,
and that knowing the base scanner model is sufficient.  I implemented a
simple flag, AV_ADF_SUPPORTS_DUPLEX, which I have applied to the scanner
models which support duplex scanning.  If I can believe the comments, this
change only affects HP scanners.

About the second problem (setting the correct bits):

The original code, for all ADF scanners, set either the duplex (0x10) or
rear scanner bits (0x08) depending on the selected ADF mode.  The subsequent
changes do this for only interlaced scanners (aka 1-pass scanners).  The
code does not set these bits for 2-pass scanners, but instead sets the
lowest three bits (0x07) of the bitset3 bit field.

The comments suggest that only HP scanners do 2-pass scanning, so I haven't
looked at other Avision scanners.  In the 2-pass case, the last three bits
are set, but the duplex mode (0x10) is not.  The comments in the code do not
lead me to believe that the rear scanning mode exists for HP equipment,
neither do the photos, debug logs, or documentation of the equipment.  As a
result, my change is to add setting of the duplex bit (0x10) in addition to
the last three bits (0x07) (although it should be noted that these were not
originally set).  I also changed the setting of the bit fields to use the
SET_BIT macro which seems to be the preferred way to toggle bits.


While I was patching the code, I decided to clean up some clever, but
confusing, code in the set_window() function.  I replaced an intermediate
value (adf_mode) with references to the underlying core data structure
(s->source_mode).  This change looks bigger than it is because of I had to
fix the indenting.


Now for the bad news.  I have not tested this code at all.  Unfortunately,
my scanner is inaccessible to me for the next year, as I've moved overseas
temporarily.  I can only assume it would work based on the debugging output
in the aforementioned bug.  I realize it's kind of rude to just dump
untested code on the group, but I hope you will forgive me as I don't
actually have the hardware in my possession at the moment.

I've put in a lot of effort to avoid breaking other scanners, but I can't be
100% sure that I've been successful.  HP scanners older than the 8200 series
should be unaffected by these changes, as they don't support duplexing and
don't enter these code paths.  However, I'm worried about the 8300 series
scanners because I have not been able to find a debug log for them.  This
implies that they are working with the current code, but without a debug
log, I can't know which code path they use.

So, if possible, please test this patch if you have a ScanJet 8200 series
scanner with an ADF unit.  If you're an owner of a ScanJet 8300 series
scanner with an ADF unit, please send me a debug log (patch or not).

These are the avision supported HP duplex capable scanners:
HP ScanJet 8200  (This model didn't ship with an ADF)
HP ScanJet 8250  (15ppm 2-pass)
HP ScanJet 8290  (25ppm 2-pass)
HP ScanJet 8270  (25ppm 2-pass, replaces the 8290)
HP ScanJet 8300  (This model didn't ship with an ADF)
HP ScanJet 8350  (25ppm 1-pass)
HP ScanJet 8390  (35ppm 1-pass)

Thanks,

Mike
(:

-- 
--------Mike at PirateHaven.org-----------------------The_glass_is_too_big--------
-------------- next part --------------
diff --git a/backend/avision.c b/backend/avision.c
index 15b3f38..a6b2c7c 100644
--- a/backend/avision.c
+++ b/backend/avision.c
@@ -646,7 +646,7 @@ static Avision_HWEntry Avision_Device_List [] =
     { "HP",      "C9930A",
       0x03f0, 0x0b01,
       "Hewlett-Packard", "ScanJet 8200",
-      0,0},
+      0, AV_ADF_SUPPORTS_DUPLEX },
     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
     /* status="good" */
 
@@ -654,7 +654,7 @@ static Avision_HWEntry Avision_Device_List [] =
     { "HP",      "C9930A",
       0x03f0, 0x0b01,
       "Hewlett-Packard", "ScanJet 8250",
-      0,0},
+      0, AV_ADF_SUPPORTS_DUPLEX },
     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
     /* status="good" */
 #endif
@@ -662,7 +662,7 @@ static Avision_HWEntry Avision_Device_List [] =
     { "HP", "C9930A",
       0x03f0, 0x3905,
       "Hewlett-Packard", "ScanJet 8270",
-      0,0},
+      0, AV_ADF_SUPPORTS_DUPLEX },
     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
     /* status="good" */
 
@@ -670,7 +670,7 @@ static Avision_HWEntry Avision_Device_List [] =
     { "HP", "C9930A",
       0x03f0, 0x0b01,
       "Hewlett-Packard", "ScanJet 8290",
-      0,0},
+      0, AV_ADF_SUPPORTS_DUPLEX },
     /* comment="1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far" */
     /* status="good" */
     
@@ -678,7 +678,7 @@ static Avision_HWEntry Avision_Device_List [] =
     { "HP", "C9930A",
       0x03f0, 0x3805,
       "Hewlett-Packard", "ScanJet 8390",
-      0,0},
+      0, AV_ADF_SUPPORTS_DUPLEX },
     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
     /* status="good" */
 
@@ -3101,7 +3101,7 @@ get_accessories_info (Avision_Scanner* s)
   
   dev->inquiry_adf |= result [0];
 
-  if (result [2] == 2) /* HP */
+  if (dev->hw->feature_type2 & AV_ADF_SUPPORTS_DUPLEX)
   {
     dev->inquiry_duplex = 1;
     dev->inquiry_duplex_interlaced = 0;
@@ -5521,41 +5521,30 @@ set_window (Avision_Scanner* s)
   /* ADF scan? */
   DBG (3, "set_window: source mode %d source mode dim %d\n",
        s->source_mode, s->source_mode_dim);
-  {
-    int adf_mode = 0;  /* offset by 1 to save a is_adf bool */
-    switch (s->source_mode) {
-    case AV_ADF:
-      adf_mode = 1;
-      break;
-    case AV_ADF_REAR:
-      adf_mode = 2;
-      break;
-    case AV_ADF_DUPLEX:
-      adf_mode = 3;
-      break;
-    default:
-      ; /* silence GCC */
-    }
-    if (adf_mode) {
-      DBG (3, "set_window: filling ADF bits\n");
-      SET_BIT (cmd.window.avision.bitset1, 7);
-      adf_mode--;
-
-      /* normal, interlaced duplex scanners */
-      if (dev->inquiry_duplex_interlaced) {
-        DBG (3, "set_window: interlaced duplex type\n");
-        cmd.window.avision.type.normal.bitset3 |= (adf_mode << 3);
+  if (s->source_mode == AV_ADF ||
+      s->source_mode == AV_ADF_REAR ||
+      s->source_mode == AV_ADF_DUPLEX) {
+    DBG (3, "set_window: filling ADF bits\n");
+    SET_BIT (cmd.window.avision.bitset1, 7);
+
+    /* normal, interlaced duplex scanners */
+    if (dev->inquiry_duplex_interlaced) {
+      DBG (3, "set_window: interlaced duplex type\n");
+      if (s->source_mode == AV_ADF_REAR) {
+        SET_BIT(cmd.window.avision.type.normal.bitset3, 3); /* 0x08 */
       }
-      else /* HP 2-pass duplex */
-      {
-	if (adf_mode) /* if duplex */
-	{
-          DBG (3, "set_window: non-interlaced duplex type (HP)\n");
-          /* MIRR 0x04 | FLIP 0x02 | DPLX 0x01 ... */
-	  cmd.window.avision.type.normal.bitset3 |= 7;
-	}
+      if (s->source_mode == AV_ADF_DUPLEX) {
+        SET_BIT(cmd.window.avision.type.normal.bitset3, 4); /* 0x10 */
       }
     }
+    else if (s->source_mode == AV_ADF_DUPLEX) /* HP 2-pass duplex */
+    {
+      DBG (3, "set_window: non-interlaced duplex type (HP)\n");
+      SET_BIT(cmd.window.avision.type.normal.bitset3, 0); /* DPLX 0x01 */
+      SET_BIT(cmd.window.avision.type.normal.bitset3, 1); /* FLIP 0x02 */
+      SET_BIT(cmd.window.avision.type.normal.bitset3, 2); /* MIRR 0x04 */
+      SET_BIT(cmd.window.avision.type.normal.bitset3, 4); /* DUPLEX 0x10 */
+    }
   }
   
   /* Newer scanners can utilize this paper length to detect double feeds.
diff --git a/backend/avision.h b/backend/avision.h
index 8c1d104..54e536a 100644
--- a/backend/avision.h
+++ b/backend/avision.h
@@ -199,7 +199,10 @@ typedef struct Avision_HWEntry {
   /*second enum cause 32 bit int above is full*/
   enum {
     /* force no calibration */
-    AV_NO_TUNE_SCAN_LENGTH = (1<<0)
+    AV_NO_TUNE_SCAN_LENGTH = (1<<0),
+
+    /* For scanners (HP) which do not indicate duplex capability */
+    AV_ADF_SUPPORTS_DUPLEX = (1<<1)
   } feature_type2;
 
 } Avision_HWEntry;


More information about the sane-devel mailing list