[sane-devel] [PATCH 1/4] canon: Fix sense_handler

Ondrej Zary linux at rainbow-software.org
Fri Aug 10 13:35:25 UTC 2012


sense_handler() crashes with Canon IX-4015 after the scanner is powered on because
scanner returns "unit attention - power on reset" sense status as a reply to the
"Test Unit Ready" command after power on - and dev is still NULL at that time.

The non-NULL dev is needed only to check if the device is a scsi2 device. But all devices
supported by this backend have the is_scsi2 flag set so it's useless.

So remove the flag and all its usage. Also change the return value for "power on
reset" check condition to SANE_STATUS_GOOD to allow IX-4015 to work.

diff --git a/backend/canon.c b/backend/canon.c
index eba677f..f7d3fe1 100644
--- a/backend/canon.c
+++ b/backend/canon.c
@@ -325,7 +325,6 @@ static SANE_Status
 sense_handler (int scsi_fd, u_char * result, void *arg)
 {
   static char me[] = "canon_sense_handler";
-  CANON_Device *dev = (CANON_Device *) arg;
   u_char sense;
   int asc;
   char *sense_str = NULL;
@@ -342,210 +341,198 @@ sense_handler (int scsi_fd, u_char * result, void *arg)
 
   status = SANE_STATUS_GOOD;
 
-  /* If the sense handler is invoked before the scanner has been
-     identified, pretend that nothing has happened. */
-  if (strncmp(dev->sane.vendor, "CANON", 5) != 0) return (status);
+  DBG(11, "sense data interpretation for SCSI-2 devices\n");
+  sense = result[2] & 0x0f;		/* extract the sense key */
+  if (result[7] > 3)		/* additional sense code available? */
+    {
+      asc = (result[12] << 8) + result[13];	/* 12: additional sense code */
+    }					/* 13: a.s.c. qualifier */
+  else
+    asc = 0xffff;
 
-  if (dev && dev->info.is_scsi2)
+  switch (sense)
     {
-      DBG(11, "sense data interpretation for SCSI-2 devices\n");
-      sense = result[2] & 0x0f;		/* extract the sense key */
-      if (result[7] > 3)		/* additional sense code available? */
-	{
-	  asc = (result[12] << 8) + result[13];	/* 12: additional sense code */
-	}					/* 13: a.s.c. qualifier */
-      else
-	asc = 0xffff;
+    case 0x00:
+      DBG(11, "sense category: no error\n");
+      status = SANE_STATUS_GOOD;
+      break;
 
-      switch (sense)
-	{
-	case 0x00:
-	  DBG(11, "sense category: no error\n");
-	  status = SANE_STATUS_GOOD;
-	  break;
-
-	case 0x01:
-	  DBG(11, "sense category: recovered error\n");
-	  switch (asc)
-	    {
-	    case 0x3700:
-	      sense_str = SANE_I18N("rounded parameter");
-	      break;
-	    default:
-	      sense_str = SANE_I18N("unknown");
-	    }
-	  status = SANE_STATUS_GOOD;
-	  break;
+    case 0x01:
+      DBG(11, "sense category: recovered error\n");
+      switch (asc)
+        {
+        case 0x3700:
+          sense_str = SANE_I18N("rounded parameter");
+          break;
+        default:
+          sense_str = SANE_I18N("unknown");
+        }
+      status = SANE_STATUS_GOOD;
+      break;
 
-	case 0x03:
-	  DBG(11, "sense category: medium error\n");
-	  switch (asc)
-	    {
-	    case 0x8000:
-	      sense_str = SANE_I18N("ADF jam");
-	      break;
-	    case 0x8001:
-	      sense_str = SANE_I18N("ADF cover open");
-	      break;
-	    default:
-	      sense_str = SANE_I18N("unknown");
-	    }
-	  status = SANE_STATUS_IO_ERROR;
-	  break;
+    case 0x03:
+      DBG(11, "sense category: medium error\n");
+      switch (asc)
+        {
+        case 0x8000:
+          sense_str = SANE_I18N("ADF jam");
+          break;
+        case 0x8001:
+          sense_str = SANE_I18N("ADF cover open");
+          break;
+        default:
+          sense_str = SANE_I18N("unknown");
+        }
+      status = SANE_STATUS_IO_ERROR;
+      break;
 
-	case 0x04:
-	  DBG(11, "sense category: hardware error\n");
-	  switch (asc)
-	    {
-	    case 0x6000:
-	      sense_str = SANE_I18N("lamp failure");
-	      break;
-	    case 0x6200:
-	      sense_str = SANE_I18N("scan head positioning error");
-	      break;
-	    case 0x8001:
-	      sense_str = SANE_I18N("CPU check error");
-	      break;
-	    case 0x8002:
-	      sense_str = SANE_I18N("RAM check error");
-	      break;
-	    case 0x8003:
-	      sense_str = SANE_I18N("ROM check error");
-	      break;
-	    case 0x8004:
-	      sense_str = SANE_I18N("hardware check error");
-	      break;
-	    case 0x8005:
-	      sense_str = SANE_I18N("transparency unit lamp failure");
-	      break;
-	    case 0x8006:
-	      sense_str = SANE_I18N("transparency unit scan head "
-	      "positioning failure");
-	      break;
-	    default:
-	      sense_str = SANE_I18N("unknown");
-	    }
-	  status = SANE_STATUS_IO_ERROR;
-	  break;
+    case 0x04:
+      DBG(11, "sense category: hardware error\n");
+      switch (asc)
+        {
+        case 0x6000:
+          sense_str = SANE_I18N("lamp failure");
+          break;
+        case 0x6200:
+          sense_str = SANE_I18N("scan head positioning error");
+          break;
+        case 0x8001:
+          sense_str = SANE_I18N("CPU check error");
+          break;
+        case 0x8002:
+          sense_str = SANE_I18N("RAM check error");
+          break;
+        case 0x8003:
+          sense_str = SANE_I18N("ROM check error");
+          break;
+        case 0x8004:
+          sense_str = SANE_I18N("hardware check error");
+          break;
+        case 0x8005:
+          sense_str = SANE_I18N("transparency unit lamp failure");
+          break;
+        case 0x8006:
+          sense_str = SANE_I18N("transparency unit scan head "
+          "positioning failure");
+          break;
+        default:
+          sense_str = SANE_I18N("unknown");
+        }
+      status = SANE_STATUS_IO_ERROR;
+      break;
 
-	case 0x05:
-	  DBG(11, "sense category: illegal request\n");
-	  switch (asc)
-	    {
-	    case 0x1a00:
-	      sense_str = SANE_I18N("parameter list length error");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x2000:
-	      sense_str = SANE_I18N("invalid command operation code");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    case 0x2400:
-	      sense_str = SANE_I18N("invalid field in CDB");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x2500:
-	      sense_str = SANE_I18N("unsupported LUN");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    case 0x2600:
-	      sense_str = SANE_I18N("invalid field in parameter list");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    case 0x2c00:
-	      sense_str = SANE_I18N("command sequence error");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    case 0x2c01:
-	      sense_str = SANE_I18N("too many windows specified");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    case 0x3a00:
-	      sense_str = SANE_I18N("medium not present");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x3d00:
-	      sense_str = SANE_I18N("invalid bit IDENTIFY message");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    case 0x8002:
-	      sense_str = SANE_I18N("option not connect");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    default:
-	      sense_str = SANE_I18N("unknown");
-	      status = SANE_STATUS_UNSUPPORTED;
-	    }
-	  break;
+    case 0x05:
+      DBG(11, "sense category: illegal request\n");
+      switch (asc)
+        {
+        case 0x1a00:
+          sense_str = SANE_I18N("parameter list length error");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x2000:
+          sense_str = SANE_I18N("invalid command operation code");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        case 0x2400:
+          sense_str = SANE_I18N("invalid field in CDB");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x2500:
+          sense_str = SANE_I18N("unsupported LUN");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        case 0x2600:
+          sense_str = SANE_I18N("invalid field in parameter list");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        case 0x2c00:
+          sense_str = SANE_I18N("command sequence error");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        case 0x2c01:
+          sense_str = SANE_I18N("too many windows specified");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        case 0x3a00:
+          sense_str = SANE_I18N("medium not present");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x3d00:
+          sense_str = SANE_I18N("invalid bit IDENTIFY message");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        case 0x8002:
+          sense_str = SANE_I18N("option not connect");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        default:
+          sense_str = SANE_I18N("unknown");
+          status = SANE_STATUS_UNSUPPORTED;
+        }
+      break;
 
-	case 0x06:
-	  DBG(11, "sense category: unit attention\n");
-	  switch (asc)
-	    {
-	    case 0x2900:
-	      sense_str = SANE_I18N("power on reset / bus device reset");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x2a00:
-	      sense_str = SANE_I18N("parameter changed by another initiator");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    default:
-	      sense_str = SANE_I18N("unknown");
-	      status = SANE_STATUS_IO_ERROR;
-	    }
-	  break;
+    case 0x06:
+      DBG(11, "sense category: unit attention\n");
+      switch (asc)
+        {
+        case 0x2900:
+          sense_str = SANE_I18N("power on reset / bus device reset");
+          status = SANE_STATUS_GOOD;
+          break;
+        case 0x2a00:
+          sense_str = SANE_I18N("parameter changed by another initiator");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        default:
+          sense_str = SANE_I18N("unknown");
+          status = SANE_STATUS_IO_ERROR;
+        }
+      break;
 
-	case 0x0b:
-	  DBG(11, "sense category: non-standard\n");
-	  switch (asc)
-	    {
-	    case 0x0000:
-	      sense_str = SANE_I18N("no additional sense information");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x4500:
-	      sense_str = SANE_I18N("reselect failure");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x4700:
-	      sense_str = SANE_I18N("SCSI parity error");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x4800:
-	      sense_str = SANE_I18N("initiator detected error message "
-	      "received");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x4900:
-	      sense_str = SANE_I18N("invalid message error");
-	      status = SANE_STATUS_UNSUPPORTED;
-	      break;
-	    case 0x8000:
-	      sense_str = SANE_I18N("timeout error");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x8001:
-	      sense_str = SANE_I18N("transparency unit shading error");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    case 0x8003:
-	      sense_str = SANE_I18N("lamp not stabilized");
-	      status = SANE_STATUS_IO_ERROR;
-	      break;
-	    default:
-	      sense_str = SANE_I18N("unknown");
-	      status = SANE_STATUS_IO_ERROR;
-	    }
-	  break;
-	default:
-	  DBG(11, "sense category: else\n");
-	}
-    }
-  else
-    {
-      sense_str = SANE_I18N("problem not analyzed (unknown SCSI class)");
-      status = SANE_STATUS_IO_ERROR;
+    case 0x0b:
+      DBG(11, "sense category: non-standard\n");
+      switch (asc)
+        {
+        case 0x0000:
+          sense_str = SANE_I18N("no additional sense information");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x4500:
+          sense_str = SANE_I18N("reselect failure");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x4700:
+          sense_str = SANE_I18N("SCSI parity error");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x4800:
+          sense_str = SANE_I18N("initiator detected error message "
+          "received");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x4900:
+          sense_str = SANE_I18N("invalid message error");
+          status = SANE_STATUS_UNSUPPORTED;
+          break;
+        case 0x8000:
+          sense_str = SANE_I18N("timeout error");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x8001:
+          sense_str = SANE_I18N("transparency unit shading error");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        case 0x8003:
+          sense_str = SANE_I18N("lamp not stabilized");
+          status = SANE_STATUS_IO_ERROR;
+          break;
+        default:
+          sense_str = SANE_I18N("unknown");
+          status = SANE_STATUS_IO_ERROR;
+        }
+      break;
+    default:
+      DBG(11, "sense category: else\n");
     }
   DBG (11, "sense message: %s\n", sense_str);
 #if 0					/* superfluous? [U.D.] */
@@ -855,7 +842,6 @@ attach (const char *devnam, CANON_Device ** devp)
      - whether it can calibrate itself
      - whether it can eject the media
      - whether it can mirror the scanned data
-     - whether it is an SCSI-2 device (gives status information by "sense key")
      - whether it is a film scanner (or can be used as one)
      - whether it has fixed, hardware-set scan resolutions only
   */
@@ -870,7 +856,6 @@ attach (const char *devnam, CANON_Device ** devp)
       dev->info.can_calibrate = SANE_FALSE;
       dev->info.can_eject = SANE_TRUE;
       dev->info.can_mirror = SANE_TRUE;
-      dev->info.is_scsi2 = SANE_TRUE;
       dev->info.is_filmscanner = SANE_TRUE;
       dev->info.has_fixed_resolutions = SANE_TRUE;
     }
@@ -885,7 +870,6 @@ attach (const char *devnam, CANON_Device ** devp)
       dev->info.can_calibrate = SANE_FALSE;
       dev->info.can_eject = SANE_TRUE;
       dev->info.can_mirror = SANE_TRUE;
-      dev->info.is_scsi2 = SANE_TRUE;
       dev->info.is_filmscanner = SANE_TRUE;
       dev->info.has_fixed_resolutions = SANE_TRUE;
     }
@@ -900,7 +884,6 @@ attach (const char *devnam, CANON_Device ** devp)
       dev->info.can_calibrate = SANE_TRUE;
       dev->info.can_eject = SANE_FALSE;
       dev->info.can_mirror = SANE_FALSE;
-      dev->info.is_scsi2 = SANE_TRUE;
       dev->info.is_filmscanner = SANE_FALSE;
       dev->info.has_fixed_resolutions = SANE_TRUE;
     }
@@ -915,7 +898,6 @@ attach (const char *devnam, CANON_Device ** devp)
       dev->info.can_calibrate = SANE_FALSE;
       dev->info.can_eject = SANE_FALSE;
       dev->info.can_mirror = SANE_FALSE;
-      dev->info.is_scsi2 = SANE_TRUE;
       dev->info.is_filmscanner = SANE_FALSE;
       dev->info.has_fixed_resolutions = SANE_TRUE;
     }
@@ -930,7 +912,6 @@ attach (const char *devnam, CANON_Device ** devp)
       dev->info.can_calibrate = SANE_FALSE;
       dev->info.can_eject = SANE_FALSE;
       dev->info.can_mirror = SANE_TRUE;
-      dev->info.is_scsi2 = SANE_TRUE;
       dev->info.is_filmscanner = SANE_FALSE;
       dev->info.has_fixed_resolutions = SANE_FALSE;
     }
diff --git a/backend/canon.h b/backend/canon.h
index b61823d..a3ad7ae 100644
--- a/backend/canon.h
+++ b/backend/canon.h
@@ -247,7 +247,6 @@ typedef struct CANON_Info
   SANE_Bool can_calibrate;		/* has got calibration control */
   SANE_Bool can_eject;			/* can eject medium */
   SANE_Bool can_mirror;			/* can mirror image by hardware */
-  SANE_Bool is_scsi2;			/* is an SCSI-2 device */
   SANE_Bool is_filmscanner;
   SANE_Bool has_fixed_resolutions;	/* only a finite number possible */
 }



-- 
Ondrej Zary



More information about the sane-devel mailing list