[sane-devel] [PATCH] pieusb: Support ProScan 10T and Reflecta CrystalScan 3600

Klaus Kaempf kkaempf at suse.de
Wed May 3 15:52:15 UTC 2017


Neither of these scanner have an automated slide transport and fail on
respective SCSI commands.

- Add flags parameter to control if automatic slide transport is available
- Reflect flags in pieusb.conf.in
- rename SLIDE_LAMP_ON to SLIDE_INIT
  it fails on scanners without automatic slide transport, so it has
  nothing to do with the lamp.
- run SLIDE_INIT only FLAG_SLIDE_TRANSPORT is set
- pieusb.conf.in: Add Reflecta CrystalScan 3600
---
 backend/pieusb.c          | 89 ++++++++++++++++++++++++++++-------------------
 backend/pieusb.conf.in    | 15 ++++++--
 backend/pieusb.h          |  1 +
 backend/pieusb_scancmd.c  |  2 +-
 backend/pieusb_scancmd.h  |  2 +-
 backend/pieusb_specific.c | 48 ++++++++++++++++++-------
 backend/pieusb_specific.h | 11 ++++--
 7 files changed, 113 insertions(+), 55 deletions(-)

diff --git a/backend/pieusb.c b/backend/pieusb.c
index 4b0730403aeb..973088849ca8 100644
--- a/backend/pieusb.c
+++ b/backend/pieusb.c
@@ -109,6 +109,10 @@ extern void write_tiff_rgbi_header (FILE *fptr, int width, int height, int depth
 #define DBG_info_scan   11      /* information scanner commands */
 #define DBG_info_usb    13      /* information usb level functions */
 
+/* device flags */
+
+#define FLAG_SLIDE_TRANSPORT 0x01
+
 /* --------------------------------------------------------------------------
  *
  * SUPPORTED DEVICES SPECIFICS
@@ -150,7 +154,8 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize
     char config_line[PATH_MAX];
     SANE_Word vendor_id;
     SANE_Word product_id;
-    SANE_Word model_number;
+    SANE_Int model_number;
+    SANE_Int flags;
     SANE_Status status;
     int i;
 
@@ -183,18 +188,22 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize
     pieusb_supported_usb_device_list[0].vendor = 0x05e3;
     pieusb_supported_usb_device_list[0].product = 0x0145;
     pieusb_supported_usb_device_list[0].model = 0x30;
+    pieusb_supported_usb_device_list[0].flags = 0;
     /* Reflecta ProScan 7200, model number 0x36 */
     pieusb_supported_usb_device_list[1].vendor = 0x05e3;
     pieusb_supported_usb_device_list[1].product = 0x0145;
     pieusb_supported_usb_device_list[1].model = 0x36;
-    /* Reflecta 6000 Multiple Slide Scanner */
+    pieusb_supported_usb_device_list[1].flags = 0;
+    /* Reflecta 6000 Multiple Slide Scanner, model number 0x3a */
     pieusb_supported_usb_device_list[2].vendor = 0x05e3;
     pieusb_supported_usb_device_list[2].product = 0x0142;
     pieusb_supported_usb_device_list[2].model = 0x3a;
+    pieusb_supported_usb_device_list[2].flags = FLAG_SLIDE_TRANSPORT;
     /* end of list */
     pieusb_supported_usb_device_list[3].vendor = 0;
     pieusb_supported_usb_device_list[3].product = 0;
     pieusb_supported_usb_device_list[3].model = 0;
+    pieusb_supported_usb_device_list[3].flags = 0;
 
     /* Add entries from config file */
     fp = sanei_config_open (PIEUSB_CONFIG_FILE);
@@ -209,14 +218,14 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize
             if (strncmp (config_line, "usb ", 4) != 0) continue;
             /* Parse vendor-id, product-id and model number and add to list */
             DBG (DBG_info_sane, "sane_init() config file parsing %s\n", config_line);
-            status = sanei_pieusb_parse_config_line(config_line, &vendor_id, &product_id, &model_number);
+            status = sanei_pieusb_parse_config_line(config_line, &vendor_id, &product_id, &model_number, &flags);
             if (status == SANE_STATUS_GOOD) {
-                DBG (DBG_info_sane, "sane_init() config file lists device %04x %04x %02x\n",vendor_id, product_id, model_number);
-                if (!sanei_pieusb_supported_device_list_contains(vendor_id, product_id, model_number)) {
-                    DBG (DBG_info_sane, "sane_init() adding device %04x %04x %02x\n",vendor_id, product_id, model_number);
-                    sanei_pieusb_supported_device_list_add(vendor_id, product_id, model_number);
+                DBG (DBG_info_sane, "sane_init() config file lists device %04x %04x %02x %02x\n",vendor_id, product_id, model_number, flags);
+                if (!sanei_pieusb_supported_device_list_contains(vendor_id, product_id, model_number, flags)) {
+                    DBG (DBG_info_sane, "sane_init() adding device %04x %04x %02x %02x\n",vendor_id, product_id, model_number, flags);
+                    sanei_pieusb_supported_device_list_add(vendor_id, product_id, model_number, flags);
                 } else {
-                    DBG (DBG_info_sane, "sane_init() list already contains %04x %04x %02x\n", vendor_id, product_id, model_number);
+                    DBG (DBG_info_sane, "sane_init() list already contains %04x %04x %02x %02x\n", vendor_id, product_id, model_number, flags);
                 }
             } else {
                 DBG (DBG_info_sane, "sane_init() config file parsing %s: error\n", config_line);
@@ -235,8 +244,13 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize
         pieusb_supported_usb_device.vendor = pieusb_supported_usb_device_list[i].vendor;
         pieusb_supported_usb_device.product = pieusb_supported_usb_device_list[i].product;
         pieusb_supported_usb_device.model = pieusb_supported_usb_device_list[i].model;
+        pieusb_supported_usb_device.flags = pieusb_supported_usb_device_list[i].flags;
         pieusb_supported_usb_device.device_number = -1; /* No device number (yet) */
-        DBG( DBG_info_sane, "sane_init() looking for Reflecta scanner %04x %04x model %02x\n", pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product, pieusb_supported_usb_device.model);
+        DBG( DBG_info_sane, "sane_init() looking for scanner %04x %04x model %02x, flags %02x\n",
+             pieusb_supported_usb_device.vendor,
+             pieusb_supported_usb_device.product,
+             pieusb_supported_usb_device.model,
+             pieusb_supported_usb_device.flags);
         sanei_usb_find_devices (pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product, sanei_pieusb_find_device_callback);
         i++;
     }
@@ -354,6 +368,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
                     pieusb_supported_usb_device.vendor = vendor;
                     pieusb_supported_usb_device.product = product;
                     pieusb_supported_usb_device.model = pieusb_supported_usb_device_list[i].model;
+                    pieusb_supported_usb_device.flags = pieusb_supported_usb_device_list[i].flags;
                     pieusb_supported_usb_device.device_number = -1;
                     sanei_usb_find_devices (vendor, product, sanei_pieusb_find_device_callback);
                     if (pieusb_supported_usb_device.device_number == -1) {
@@ -994,17 +1009,18 @@ sane_start (SANE_Handle handle)
      *
      * ---------------------------------------------------------------------- */
 
-    sanei_pieusb_cmd_17 (scanner->device_number, 1, &status);
-    if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
-      DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_17 failed: %d\n", status.pieusb_status);
-      return SANE_STATUS_IO_ERROR;
-    }
-    st = sanei_pieusb_wait_ready (scanner, 0);
-    if (st != SANE_STATUS_GOOD) {
-      DBG (DBG_error, "sane_start(): scanner not ready after sanei_pieusb_cmd_17: %d\n", st);
-      return st;
+    if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) {
+        sanei_pieusb_cmd_17 (scanner->device_number, 1, &status);
+        if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
+          DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_17 failed: %d\n", status.pieusb_status);
+          return SANE_STATUS_IO_ERROR;
+        }
+        st = sanei_pieusb_wait_ready (scanner, 0);
+        if (st != SANE_STATUS_GOOD) {
+          DBG (DBG_error, "sane_start(): scanner not ready after sanei_pieusb_cmd_17: %d\n", st);
+          return st;
+        }
     }
-
     /* ----------------------------------------------------------------------
      *
      * Get & set initial gains and offsets
@@ -1039,20 +1055,21 @@ sane_start (SANE_Handle handle)
 
     /* ----------------------------------------------------------------------
      *
-     * Lamp on
+     * Init slide transport
      *
      * ---------------------------------------------------------------------- */
-    sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_LAMP_ON, &status);
-    if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
-      DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status);
-      return SANE_STATUS_IO_ERROR;
-    }
-    st = sanei_pieusb_wait_ready (scanner, 0);
-    if (st != SANE_STATUS_GOOD) {
-      DBG (DBG_error, "sane_start: scanner not ready %d\n", st);
-      return st;
+    if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) {
+        sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_INIT, &status);
+        if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
+          DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status);
+          return SANE_STATUS_IO_ERROR;
+        }
+        st = sanei_pieusb_wait_ready (scanner, 0);
+        if (st != SANE_STATUS_GOOD) {
+          DBG (DBG_error, "sane_start: scanner not ready %d\n", st);
+          return st;
+        }
     }
-
     /* Enter SCAN phase 1 */
     DBG (DBG_info_sane, "sane_start(): scan phase 1\n");
 
@@ -1200,12 +1217,14 @@ sane_start (SANE_Handle handle)
      * Advance to next slide (except for preview)
      *
      * ---------------------------------------------------------------------- */
-    if (scanner->val[OPT_ADVANCE_SLIDE].b && !scanner->val[OPT_PREVIEW].b) {
-      sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_NEXT, &status);
-      if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
-	DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status);
 
-      }
+    if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) {
+        if (scanner->val[OPT_ADVANCE_SLIDE].b && !scanner->val[OPT_PREVIEW].b) {
+            sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_NEXT, &status);
+            if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
+                DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status);
+            }
+        }
     }
 
     /* ----------------------------------------------------------------------
diff --git a/backend/pieusb.conf.in b/backend/pieusb.conf.in
index ec5ba7ecce5f..1bee8e2d5895 100644
--- a/backend/pieusb.conf.in
+++ b/backend/pieusb.conf.in
@@ -1,9 +1,18 @@
 # pieusb.conf: Configuration file for PIE/Reflecta USB scanner
 # Read man sane-pieusb for documentation
 
-# Autodetect
+# Format
+# usb <vendor-id> <device-id> <model-nr> <has-slide-transport>
+#
+# Autodetect (built-in)
 # Reflecta 6000 Multiple Slide Scanner
-usb 0x05e3 0x0142
+# usb 0x05e3 0x0142 0x3a 0x01
 # Reflecta CrystalScan 7200
+# usb 0x05e3 0x0145 0x30 0x00
 # Reflecta ProScan 7200
-usb 0x05e3 0x0145
+# usb 0x05e3 0x0145 0x36 0x00
+
+# Reflecta ProScan 10T
+usb 0x05e3 0x0145 0x47 0x00
+# Reflecta CrystalScan 3600
+usb 0x05e3 0x0145 0x2e 0x00
diff --git a/backend/pieusb.h b/backend/pieusb.h
index 10ce106d4e3d..dc4cda78592f 100644
--- a/backend/pieusb.h
+++ b/backend/pieusb.h
@@ -80,6 +80,7 @@ struct Pieusb_USB_Device_Entry
     SANE_Word product;		/* USB product identifier */
     SANE_Word model;		/* USB model number */
     SANE_Int device_number;     /* USB device number if the device is present */
+    SANE_Int flags;             /* flags */
 };
 
 extern struct Pieusb_USB_Device_Entry* pieusb_supported_usb_device_list;
diff --git a/backend/pieusb_scancmd.c b/backend/pieusb_scancmd.c
index 1fc42b0fbb74..672716f41325 100644
--- a/backend/pieusb_scancmd.c
+++ b/backend/pieusb_scancmd.c
@@ -212,7 +212,7 @@ sanei_pieusb_cmd_test_unit_ready(SANE_Int device_number, struct Pieusb_Command_S
 
 /**
  * slide action
- * @param action  SLIDE_NEXT, SLIDE_PREV, SLIDE_LAMP_ON, SLIDE_RELOAD
+ * @param action  SLIDE_NEXT, SLIDE_PREV, SLIDE_INIT, SLIDE_RELOAD
  * @return Pieusb_Command_Status
  */
 
diff --git a/backend/pieusb_scancmd.h b/backend/pieusb_scancmd.h
index 0dee64610920..5eefa5521600 100644
--- a/backend/pieusb_scancmd.h
+++ b/backend/pieusb_scancmd.h
@@ -318,7 +318,7 @@ struct Pieusb_Command_Status {
 typedef struct Pieusb_Scanner_Properties Pieusb_Scanner_Properties;
 
 typedef enum {
-  SLIDE_NEXT = 0x04, SLIDE_PREV = 0x05, SLIDE_LAMP_ON = 0x10, SLIDE_RELOAD = 0x40
+  SLIDE_NEXT = 0x04, SLIDE_PREV = 0x05, SLIDE_INIT = 0x10, SLIDE_RELOAD = 0x40
 } slide_action;
 
 void sanei_pieusb_cmd_slide(SANE_Int device_number, slide_action action, struct Pieusb_Command_Status *status);
diff --git a/backend/pieusb_specific.c b/backend/pieusb_specific.c
index 823107530bc4..ce107cf78de8 100644
--- a/backend/pieusb_specific.c
+++ b/backend/pieusb_specific.c
@@ -292,6 +292,8 @@ sanei_pieusb_find_device_callback (const char *devicename)
         return SANE_STATUS_INVAL;
     }
 
+    dev->flags = pieusb_supported_usb_device.flags;
+
     /* Found a supported scanner, put it in the definitions list*/
     DBG (DBG_info_proc, "sanei_pieusb_find_device_callback: success\n");
     dev->next = pieusb_definition_list_head;
@@ -996,18 +998,23 @@ sanei_pieusb_init_options (Pieusb_Scanner* scanner)
 }
 
 /**
- * Parse line from config file into a vendor id, product id and a model number
+ * Parse line from config file into a vendor id, product id, model number, and flags
  *
  * @param config_line Text to parse
  * @param vendor_id
  * @param product_id
  * @param model_number
+ * @param flags
  * @return SANE_STATUS_GOOD, or SANE_STATUS_INVAL in case of a parse error
  */
 SANE_Status
-sanei_pieusb_parse_config_line(const char* config_line, SANE_Word* vendor_id, SANE_Word* product_id, SANE_Word* model_number)
+sanei_pieusb_parse_config_line(const char* config_line,
+                               SANE_Word* vendor_id,
+                               SANE_Word* product_id,
+                               SANE_Int* model_number,
+                               SANE_Int* flags)
 {
-    char *vendor_id_string, *product_id_string, *model_number_string;
+    char *vendor_id_string, *product_id_string, *model_number_string, *flags_string;
 
     if (strncmp (config_line, "usb ", 4) != 0) {
         return SANE_STATUS_INVAL;
@@ -1041,12 +1048,12 @@ sanei_pieusb_parse_config_line(const char* config_line, SANE_Word* vendor_id, SA
     } else {
         return SANE_STATUS_INVAL;
     }
-    /* Detect product-id */
+    /* Detect model number */
     config_line = sanei_config_skip_whitespace (config_line);
     if (*config_line) {
         config_line = sanei_config_get_string (config_line, &model_number_string);
         if (model_number_string) {
-            *model_number = strtol (model_number_string, 0, 0);
+            *model_number = (SANE_Int) strtol (model_number_string, 0, 0);
             free (model_number_string);
         } else {
             return SANE_STATUS_INVAL;
@@ -1055,6 +1062,16 @@ sanei_pieusb_parse_config_line(const char* config_line, SANE_Word* vendor_id, SA
     } else {
         return SANE_STATUS_INVAL;
     }
+    /* Detect (optional) flags */
+    *flags = 0;
+    config_line = sanei_config_skip_whitespace (config_line);
+    if (*config_line) {
+        config_line = sanei_config_get_string (config_line, &flags_string);
+        if (flags_string) {
+            *flags = (SANE_Int) strtol (flags_string, 0, 0);
+            free (flags_string);
+        }
+    }
     return SANE_STATUS_GOOD;
 }
 
@@ -1064,16 +1081,18 @@ sanei_pieusb_parse_config_line(const char* config_line, SANE_Word* vendor_id, SA
  * @param vendor_id
  * @param product_id
  * @param model_number
+ * @param flags
  * @return
  */
 SANE_Bool
-sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Word model_number)
+sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags)
 {
     int i = 0;
     while (pieusb_supported_usb_device_list[i].vendor != 0) {
         if (pieusb_supported_usb_device_list[i].vendor == vendor_id
               && pieusb_supported_usb_device_list[i].product == product_id
-              && pieusb_supported_usb_device_list[i].model == model_number) {
+              && pieusb_supported_usb_device_list[i].model == model_number
+              && pieusb_supported_usb_device_list[i].flags == flags) {
             return SANE_TRUE;
         }
         i++;
@@ -1086,10 +1105,11 @@ sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word produ
  * @param vendor_id
  * @param product_id
  * @param model_number
+ * @param flags
  * @return
  */
 SANE_Status
-sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Word model_number)
+sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags)
 {
     int i = 0, k;
     struct Pieusb_USB_Device_Entry* dl;
@@ -1099,10 +1119,11 @@ sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id
     }
     /* i is index of last entry */
     for (k=0; k<=i; k++) {
-        DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add(): current %03d: %04x %04x %02x\n", i,
+        DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add(): current %03d: %04x %04x %02x %02x\n", i,
             pieusb_supported_usb_device_list[k].vendor,
             pieusb_supported_usb_device_list[k].product,
-            pieusb_supported_usb_device_list[k].model);
+            pieusb_supported_usb_device_list[k].model,
+            pieusb_supported_usb_device_list[k].flags);
     }
 
     dl = realloc(pieusb_supported_usb_device_list,(i+2)*sizeof(struct Pieusb_USB_Device_Entry)); /* Add one entry to list */
@@ -1114,14 +1135,17 @@ sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id
     pieusb_supported_usb_device_list[i].vendor = vendor_id;
     pieusb_supported_usb_device_list[i].product = product_id;
     pieusb_supported_usb_device_list[i].model = model_number;
+    pieusb_supported_usb_device_list[i].flags = flags;
     pieusb_supported_usb_device_list[i+1].vendor = 0;
     pieusb_supported_usb_device_list[i+1].product = 0;
     pieusb_supported_usb_device_list[i+1].model = 0;
+    pieusb_supported_usb_device_list[i+1].flags = 0;
     for (k=0; k<=i+1; k++) {
-        DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add() add: %03d: %04x %04x %02x\n", i,
+        DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add() add: %03d: %04x %04x %02x %02x\n", i,
             pieusb_supported_usb_device_list[k].vendor,
             pieusb_supported_usb_device_list[k].product,
-            pieusb_supported_usb_device_list[k].model);
+            pieusb_supported_usb_device_list[k].model,
+            pieusb_supported_usb_device_list[k].flags);
     }
     return SANE_STATUS_GOOD;
 }
diff --git a/backend/pieusb_specific.h b/backend/pieusb_specific.h
index 3928adfa6d65..f51696089d5e 100644
--- a/backend/pieusb_specific.h
+++ b/backend/pieusb_specific.h
@@ -193,6 +193,7 @@ struct Pieusb_Device_Definition
       /* USB id's like 0x05e3 0x0145, see pieusb.conf */
     SANE_String version; /* INQUIRY productRevision */
     SANE_Byte model; /* INQUIRY model */
+    SANE_Byte flags; /* pieusb.conf flags */
 
     /* Ranges for various quantities */
     SANE_Range dpi_range;
@@ -315,7 +316,11 @@ struct Pieusb_Scanner
 
 typedef struct Pieusb_Scanner Pieusb_Scanner;
 
-SANE_Status sanei_pieusb_parse_config_line(const char* config_line, SANE_Word* vendor_id, SANE_Word* product_id, SANE_Word* model_number);
+SANE_Status sanei_pieusb_parse_config_line(const char* config_line,
+                                           SANE_Word* vendor_id,
+                                           SANE_Word* product_id,
+                                           SANE_Int* model_number,
+                                           SANE_Int* flags);
 /* sub to sane_start() */
 SANE_Status sanei_pieusb_post (Pieusb_Scanner *scanner,  uint16_t **in_img, int planes);
 void sanei_pieusb_correct_shading(struct Pieusb_Scanner *scanner, struct Pieusb_Read_Buffer *buffer);
@@ -329,8 +334,8 @@ SANE_Status sanei_pieusb_set_frame_from_options(Pieusb_Scanner * scanner);
 void sanei_pieusb_print_options(struct Pieusb_Scanner *scanner);
 /* sub to sane_control_option() and sane_start() */
 int sanei_pieusb_analyse_options(struct Pieusb_Scanner *scanner);
-SANE_Bool sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Word model_number);
-SANE_Status sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Word model_number);
+SANE_Bool sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags);
+SANE_Status sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags);
 /* sub to sane_init() and sane_open() */
 SANE_Status sanei_pieusb_find_device_callback (const char *devicename);
 /* sub to sane_open() */
-- 
2.12.2


-- 
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)



More information about the sane-devel mailing list