summaryrefslogtreecommitdiff
path: root/backend/canon_dr.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/canon_dr.c')
-rw-r--r--backend/canon_dr.c937
1 files changed, 929 insertions, 8 deletions
diff --git a/backend/canon_dr.c b/backend/canon_dr.c
index 95799e7..58299d7 100644
--- a/backend/canon_dr.c
+++ b/backend/canon_dr.c
@@ -3,7 +3,7 @@
This file is part of the SANE package, and implements a SANE backend
for various Canon DR-series scanners.
- Copyright (C) 2008-2021 m. allan noah
+ Copyright (C) 2008-2022 m. allan noah
Yabarana Corp. www.yabarana.com provided significant funding
EvriChart, Inc. www.evrichart.com provided funding and loaned equipment
@@ -355,6 +355,10 @@
- rewrite do_cmd() timeout handling
- remove long timeout TUR from v61 (did not help)
- allow config file to set initial tur timeout for DR-X10C (#142)
+ v63 2022-11-18, CQ, MAN
+ - add support for reading the total and roller counters
+ v64 2022-11-18, CQ, MAN
+ - add complete support for imprinters on X10C (#585)
SANE FLOW DIAGRAM
@@ -393,6 +397,7 @@
#include <math.h> /*tan*/
#include <unistd.h> /*usleep*/
#include <sys/time.h> /*gettimeofday*/
+#include <time.h> /*localtime*/
#include <stdlib.h> /*strtol*/
#include "../include/sane/sanei_backend.h"
@@ -406,7 +411,7 @@
#include "canon_dr.h"
#define DEBUG 1
-#define BUILD 62
+#define BUILD 64
/* values for SANE_DEBUG_CANON_DR env var:
- errors 5
@@ -449,6 +454,13 @@
#define STRING_NONE SANE_I18N("None")
#define STRING_JPEG SANE_I18N("JPEG")
+#define STRING_IMPRINTER_8x12_FONT SANE_I18N("8x12")
+#define STRING_IMPRINTER_12x12_FONT SANE_I18N("12x12")
+
+#define STRING_IMPRINTER_ADDON_BoW SANE_I18N("Black-on-White")
+#define STRING_IMPRINTER_ADDON_BoI SANE_I18N("Black-on-Image")
+#define STRING_IMPRINTER_ADDON_WoB SANE_I18N("White-on-Black")
+
/* Also set via config file. */
static int global_buffer_size;
static int global_buffer_size_default = 2 * 1024 * 1024;
@@ -494,7 +506,7 @@ static struct scanner *scanner_devList = NULL;
SANE_Status
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
{
- authorize = authorize; /* get rid of compiler warning */
+ (void) authorize; /* get rid of compiler warning */
DBG_INIT ();
DBG (10, "sane_init: start\n");
@@ -547,7 +559,7 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
int num_devices=0;
int i=0;
- local_only = local_only; /* get rid of compiler warning */
+ (void) local_only; /* get rid of compiler warning */
DBG (10, "sane_get_devices: start\n");
@@ -992,6 +1004,12 @@ attach_one (const char *device_name, int connType)
return ret;
}
+ /* this detects imprinters if they are available */
+ ret = init_imprinters (s);
+ if (ret != SANE_STATUS_GOOD) {
+ DBG (5, "attach_one: errors while trying to detect optional imprinters, continuing\n");
+ }
+
/* enable/read the buttons */
ret = init_panel (s);
if (ret != SANE_STATUS_GOOD) {
@@ -1001,6 +1019,13 @@ attach_one (const char *device_name, int connType)
return ret;
}
+ /* enable/read the lifecycle counters */
+ ret = init_counters (s);
+ if (ret != SANE_STATUS_GOOD) {
+ DBG (5, "attach_one: unable to detect lifecycle counters, continuing\n");
+ return ret;
+ }
+
/* sets SANE option 'values' to good defaults */
ret = init_user (s);
if (ret != SANE_STATUS_GOOD) {
@@ -1168,6 +1193,7 @@ init_inquire (struct scanner *s)
if (strncmp ("DR", s->model_name, 2)
&& strncmp ("CR", s->model_name, 2)
&& strncmp ("P-", s->model_name, 2)
+ && strncmp ("R", s->model_name, 1)
) {
DBG (5, "The device at '%s' is reported to be a '%s'\n",
s->device_name, s->model_name);
@@ -1388,8 +1414,9 @@ init_model (struct scanner *s)
s->max_x_fb = s->max_x;
s->max_y_fb = s->max_y;
- /* missing from vpd- we will unset this for b&w machines below */
+ /* missing from vpd- we will unset these for some machines below */
s->can_color = 1;
+ s->can_read_lifecycle_counters = 1;
/* specific settings missing from vpd */
if (strstr (s->model_name,"DR-9080")){
@@ -1491,6 +1518,34 @@ init_model (struct scanner *s)
s->can_monochrome=0;
}
+ else if (strstr (s->model_name,"R40")
+ ){
+ /* confirmed */
+ s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_C120;
+ s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_C120;
+ s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_C120;
+ s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_C120;
+ s->duplex_interlace = DUPLEX_INTERLACE_2510;
+ /*s->duplex_offset = 320; now set in config file*/
+ s->fixed_width = 1;
+ s->need_ccal = 1;
+ s->fcal_src = FCAL_SRC_SCAN;
+ s->fcal_dest = FCAL_DEST_SW;
+ s->rgb_format = 1;
+ s->sw_lut = 1;
+
+ /*only in Y direction, so we trash them in X*/
+ s->std_res_x[DPI_100]=0;
+ s->std_res_x[DPI_150]=0;
+ s->std_res_x[DPI_200]=0;
+ s->std_res_x[DPI_240]=0;
+ s->std_res_x[DPI_400]=0;
+
+ /* suspected settings */
+ s->ccal_version = 3;
+ s->has_df_ultra = 1;
+ }
+
/* copied from 2510, possibly incorrect */
else if (strstr (s->model_name,"DR-3010")){
s->rgb_format = 1;
@@ -1840,6 +1895,7 @@ init_model (struct scanner *s)
}
else if (strstr (s->model_name,"DR-X10C")){
+ int i = 0;
/* Required for USB coms */
s->has_ssm = 0;
@@ -1862,6 +1918,61 @@ init_model (struct scanner *s)
s->std_res_y[DPI_600]=1;
s->has_hwcrop = 1;
+
+ /*valid horizontal offsets for post-imprinter*/
+ s->post_imprinter_h_offset_list[++i] = 21;
+ s->post_imprinter_h_offset_list[++i] = 35;
+ s->post_imprinter_h_offset_list[++i] = 47;
+ s->post_imprinter_h_offset_list[++i] = 59;
+ s->post_imprinter_h_offset_list[++i] = 72;
+ s->post_imprinter_h_offset_list[++i] = 99;
+ s->post_imprinter_h_offset_list[++i] = 114;
+ s->post_imprinter_h_offset_list[++i] = 143;
+ s->post_imprinter_h_offset_list[++i] = 155;
+ s->post_imprinter_h_offset_list[++i] = 167;
+ s->post_imprinter_h_offset_list[++i] = 196;
+ s->post_imprinter_h_offset_list[++i] = 211;
+ s->post_imprinter_h_offset_list[++i] = 239;
+ s->post_imprinter_h_offset_list[++i] = 251;
+ s->post_imprinter_h_offset_list[++i] = 263;
+ s->post_imprinter_h_offset_list[++i] = 275;
+ s->post_imprinter_h_offset_list[++i] = 289;
+ s->post_imprinter_h_offset_list[0] = i;
+
+ i = 0;
+ /*valid horizontal offsets for pre-imprinter*/
+ s->pre_imprinter_h_offset_list[++i] = 14;
+ s->pre_imprinter_h_offset_list[++i] = 28;
+ s->pre_imprinter_h_offset_list[++i] = 41;
+ s->pre_imprinter_h_offset_list[++i] = 53;
+ s->pre_imprinter_h_offset_list[++i] = 65;
+ s->pre_imprinter_h_offset_list[++i] = 106;
+ s->pre_imprinter_h_offset_list[0] = i;
+
+ /*valid vertical offsets for imprinters*/
+ s->imprinter_v_offset_range.min = 0;
+ s->imprinter_v_offset_range.max = 500;
+ s->imprinter_v_offset_range.quant = 1;
+
+ i = 0;
+ /*valid font angles for imprinters*/
+ s->imprinter_font_angle_list[++i] = 0;
+ s->imprinter_font_angle_list[++i] = 90;
+ s->imprinter_font_angle_list[++i] = 180;
+ s->imprinter_font_angle_list[++i] = 270;
+ s->imprinter_font_angle_list[0] = i;
+
+ i = 0;
+ s->imprint_font_size_list[i++] = STRING_IMPRINTER_8x12_FONT;
+ s->imprint_font_size_list[i++] = STRING_IMPRINTER_12x12_FONT;
+ s->imprint_font_size_list[i] = NULL;
+
+ i = 0;
+ s->imprint_addon_mode_list[i++] = STRING_IMPRINTER_ADDON_BoI;
+ s->imprint_addon_mode_list[i++] = STRING_IMPRINTER_ADDON_BoW;
+ s->imprint_addon_mode_list[i++] = STRING_IMPRINTER_ADDON_WoB;
+ s->imprint_addon_mode_list[i++] = STRING_NONE;
+ s->imprint_addon_mode_list[i] = NULL;
}
DBG (10, "init_model: finish\n");
@@ -1870,6 +1981,30 @@ init_model (struct scanner *s)
}
/*
+ * try to detect imprinters.
+ */
+static SANE_Status
+init_imprinters (struct scanner *s)
+{
+ SANE_Status ret = SANE_STATUS_GOOD;
+
+ s->has_pre_imprinter = 0;
+ s->has_post_imprinter = 0;
+
+ ret = detect_imprinter(s,R_PRE_IMPRINTER);
+ if(ret != SANE_STATUS_GOOD){
+ return ret;
+ }
+
+ ret = detect_imprinter(s,R_POST_IMPRINTER);
+ if(ret != SANE_STATUS_GOOD){
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
* This function enables the buttons and preloads the current panel values
*/
static SANE_Status
@@ -1901,6 +2036,28 @@ init_panel (struct scanner *s)
}
/*
+ * This function disables the lifecycle counters if not available
+ */
+static SANE_Status
+init_counters (struct scanner *s)
+{
+ SANE_Status ret = SANE_STATUS_GOOD;
+
+ DBG (10, "init_counters: start\n");
+
+ ret = read_counters(s);
+ if(ret){
+ DBG (5, "init_counters: disabling lifecycle counters\n");
+ s->can_read_lifecycle_counters = 0;
+ return ret;
+ }
+
+ DBG (10, "init_counters: finish\n");
+
+ return ret;
+}
+
+/*
* set good default user values.
* struct is already initialized to 0.
*/
@@ -1953,6 +2110,10 @@ init_user (struct scanner *s)
s->threshold = 90;
s->compress_arg = 50;
+ s->pre_imprint.h_offset = 65;
+ s->post_imprint.h_offset = 155;
+ s->post_imprint_addon_mode = ADDON_BoI;
+
DBG (10, "init_user: finish\n");
return SANE_STATUS_GOOD;
@@ -2737,6 +2898,197 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
opt->cap = SANE_CAP_INACTIVE;
}
+ /* "Imprinter" group --------------------------------------------------- */
+ if(option==OPT_IMPRINT_GROUP){
+ opt->name = "imprinter-options";
+ opt->title = SANE_I18N ("Imprinter Options");
+ opt->desc = SANE_I18N ("Controls for imprinter units");
+ opt->type = SANE_TYPE_GROUP;
+ opt->constraint_type = SANE_CONSTRAINT_NONE;
+
+ /*flaming hack to get scanimage to hide group*/
+ if ( !(s->has_pre_imprinter || s->has_post_imprinter) )
+ opt->type = SANE_TYPE_BOOL;
+ }
+
+ if(option==OPT_PRE_IMPRINT_SPECSTRING){
+ opt->name = "pre-imprint-string";
+ opt->title = "Pre-Imprinter string";
+ opt->desc = "String specifier for the pre-imprinter text";
+ opt->type = SANE_TYPE_STRING;
+ opt->size = IMPRINT_SPECSTRING_LEN;
+ if (s->has_pre_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_PRE_IMPRINT_H_OFFSET){
+ opt->name = "pre-imprint-h-offset";
+ opt->title = "Pre-Imprinter horizontal offset";
+ opt->desc = "Integer specifying the horizontal positioning of the pre-imprinter";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_MM;
+ opt->size = sizeof(SANE_Word);
+ opt->constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ opt->constraint.word_list = s->pre_imprinter_h_offset_list;
+ if (s->has_pre_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_PRE_IMPRINT_V_OFFSET){
+ opt->name = "pre-imprint-v-offset";
+ opt->title = "Pre-Imprinter vertical offset";
+ opt->desc = "Integer specifying the vertical positioning of the pre-imprinter";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_MM;
+ opt->size = sizeof(SANE_Word);
+ opt->constraint_type = SANE_CONSTRAINT_RANGE;
+ opt->constraint.range = &s->imprinter_v_offset_range;
+ if (s->has_pre_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_PRE_IMPRINT_FONT_SIZE){
+ opt->name = "pre-imprint-font-size";
+ opt->title = "Pre-Imprinter font size";
+ opt->desc = "Integer specifying the pre-imprint font size";
+ opt->type = SANE_TYPE_STRING;
+ opt->constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ opt->constraint.string_list = s->imprint_font_size_list;
+ opt->size = maxStringSize (opt->constraint.string_list);
+ if (s->has_pre_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_PRE_IMPRINT_FONT_ROT){
+ opt->name = "pre-imprint-font-rot";
+ opt->title = "Pre-Imprinter font rotation";
+ opt->desc = "Integer specifying the pre-imprint font rotation";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_NONE;
+ opt->size = sizeof(SANE_Word);
+ opt->constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ opt->constraint.word_list = s->imprinter_font_angle_list;
+ if (s->has_pre_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_PRE_IMPRINT_SPACING){
+ opt->name = "pre-imprint-spacing";
+ opt->title = "Pre-Imprinter spacing";
+ opt->desc = "Enables the pre-imprint extra spacing";
+ opt->type = SANE_TYPE_BOOL;
+ if (s->has_pre_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_POST_IMPRINT_SPECSTRING){
+ opt->name = "post-imprint-string";
+ opt->title = "Post-Imprinter string";
+ opt->desc = "String specifier for the post-imprinter text";
+ opt->type = SANE_TYPE_STRING;
+ opt->size = IMPRINT_SPECSTRING_LEN;
+ if (s->has_post_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_POST_IMPRINT_H_OFFSET){
+ opt->name = "post-imprint-h-offset";
+ opt->title = "Post-Imprinter horizontal offset";
+ opt->desc = "Integer specifying the horizontal positioning of the post-imprinter";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_MM;
+ opt->size = sizeof(SANE_Word);
+ opt->constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ opt->constraint.word_list = s->post_imprinter_h_offset_list;
+ if (s->has_post_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_POST_IMPRINT_V_OFFSET){
+ opt->name = "post-imprint-v-offset";
+ opt->title = "Post-Imprinter vertical offset";
+ opt->desc = "Integer specifying the vertical positioning of the post-imprinter";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_MM;
+ opt->size = sizeof(SANE_Word);
+ opt->constraint_type = SANE_CONSTRAINT_RANGE;
+ opt->constraint.range = &s->imprinter_v_offset_range;
+ if (s->has_post_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_POST_IMPRINT_FONT_SIZE){
+ opt->name = "post-imprint-font-size";
+ opt->title = "Post-Imprinter font size";
+ opt->desc = "Integer specifying the post-imprint font size";
+ opt->type = SANE_TYPE_STRING;
+ opt->constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ opt->constraint.string_list = s->imprint_font_size_list;
+ opt->size = maxStringSize (opt->constraint.string_list);
+ if (s->has_post_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_POST_IMPRINT_FONT_ROT){
+ opt->name = "post-imprint-font-rot";
+ opt->title = "Post-Imprinter font rotation";
+ opt->desc = "Integer specifying the post-imprint font rotation";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_NONE;
+ opt->size = sizeof(SANE_Word);
+ opt->constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ opt->constraint.word_list = s->imprinter_font_angle_list;
+ if (s->has_post_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_POST_IMPRINT_SPACING){
+ opt->name = "post-imprint-spacing";
+ opt->title = "Post-Imprinter spacing";
+ opt->desc = "Enables the post-imprint extra spacing";
+ opt->type = SANE_TYPE_BOOL;
+ if (s->has_post_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_POST_IMPRINT_ADDON_MODE){
+ opt->name = "post-imprint-addon-mode";
+ opt->title = "Post-Imprinter addon mode";
+ opt->desc = "Integer specifying the type of post-imprint addon rendered in the scanned image";
+ opt->type = SANE_TYPE_STRING;
+ opt->constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ opt->constraint.string_list = s->imprint_addon_mode_list;
+ opt->size = maxStringSize (opt->constraint.string_list);
+ if (s->has_post_imprinter)
+ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
/* "Sensor" group ------------------------------------------------------ */
if(option==OPT_SENSOR_GROUP){
opt->name = SANE_NAME_SENSORS;
@@ -2830,6 +3182,34 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
opt->cap = SANE_CAP_INACTIVE;
}
+ if(option==OPT_ROLLERCOUNTER){
+ opt->name = "roller-counter";
+ opt->title = "Roller Counter";
+ opt->desc = "Scans since last roller replacement";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_NONE;
+ opt->constraint_type = SANE_CONSTRAINT_NONE;
+
+ if (s->can_read_lifecycle_counters)
+ opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
+ if(option==OPT_TOTALCOUNTER){
+ opt->name = "total-counter";
+ opt->title = "Total Counter";
+ opt->desc = "Total scan count of the device";
+ opt->type = SANE_TYPE_INT;
+ opt->unit = SANE_UNIT_NONE;
+ opt->constraint_type = SANE_CONSTRAINT_NONE;
+
+ if (s->can_read_lifecycle_counters)
+ opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
+ else
+ opt->cap = SANE_CAP_INACTIVE;
+ }
+
if(option==OPT_ADF_LOADED){
opt->name = "adf-loaded";
opt->title = "ADF Loaded";
@@ -3108,6 +3488,122 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
*val_p = s->hwcrop;
return SANE_STATUS_GOOD;
+ case OPT_PRE_IMPRINT_SPECSTRING:
+ strcpy(val, s->pre_imprint.specstring);
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_H_OFFSET:
+ *val_p = s->pre_imprint.h_offset;
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_V_OFFSET:
+ *val_p = s->pre_imprint.v_offset;
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_FONT_SIZE:
+ switch (s->pre_imprint.font_size){
+ case IMPRINTER_12x12_FONT:
+ strcpy(val, STRING_IMPRINTER_12x12_FONT);
+ break;
+
+ case IMPRINTER_8x12_FONT:
+ strcpy(val, STRING_IMPRINTER_8x12_FONT);
+ break;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_FONT_ROT:
+ switch (s->pre_imprint.font_rot){
+ case IMPRINTER_0_FONT_ROT:
+ *val_p = 0;
+ break;
+
+ case IMPRINTER_90_FONT_ROT:
+ *val_p = 90;
+ break;
+
+ case IMPRINTER_180_FONT_ROT:
+ *val_p = 180;
+ break;
+
+ case IMPRINTER_270_FONT_ROT:
+ *val_p = 270;
+ break;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_SPACING:
+ *val_p = s->pre_imprint.spacing;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_SPECSTRING:
+ strcpy(val, s->post_imprint.specstring);
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_H_OFFSET:
+ *val_p = s->post_imprint.h_offset;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_V_OFFSET:
+ *val_p = s->post_imprint.v_offset;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_FONT_SIZE:
+ switch (s->post_imprint.font_size){
+ case IMPRINTER_12x12_FONT:
+ strcpy(val, STRING_IMPRINTER_12x12_FONT);
+ break;
+
+ case IMPRINTER_8x12_FONT:
+ strcpy(val, STRING_IMPRINTER_8x12_FONT);
+ break;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_FONT_ROT:
+ switch (s->post_imprint.font_rot){
+ case IMPRINTER_0_FONT_ROT:
+ *val_p = 0;
+ break;
+
+ case IMPRINTER_90_FONT_ROT:
+ *val_p = 90;
+ break;
+
+ case IMPRINTER_180_FONT_ROT:
+ *val_p = 180;
+ break;
+
+ case IMPRINTER_270_FONT_ROT:
+ *val_p = 270;
+ break;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_SPACING:
+ *val_p = s->post_imprint.spacing;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_ADDON_MODE:
+ switch (s->post_imprint_addon_mode){
+ case ADDON_BoW:
+ strcpy(val, STRING_IMPRINTER_ADDON_BoW);
+ break;
+
+ case ADDON_BoI:
+ strcpy(val, STRING_IMPRINTER_ADDON_BoI);
+ break;
+
+ case ADDON_WoB:
+ strcpy(val, STRING_IMPRINTER_ADDON_WoB);
+ break;
+
+ case ADDON_DISABLED:
+ strcpy(val, STRING_NONE);
+ break;
+ }
+ return SANE_STATUS_GOOD;
+
/* Sensor Group */
case OPT_START:
ret = read_panel(s,OPT_START);
@@ -3144,6 +3640,16 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
*val_p = s->panel_counter;
return ret;
+ case OPT_ROLLERCOUNTER:
+ ret = read_counters(s);
+ *val_p = s->roller_counter;
+ return ret;
+
+ case OPT_TOTALCOUNTER:
+ ret = read_counters(s);
+ *val_p = s->total_counter;
+ return ret;
+
case OPT_ADF_LOADED:
ret = read_sensors(s,OPT_ADF_LOADED);
*val_p = s->sensor_adf_loaded;
@@ -3431,6 +3937,119 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
s->hwcrop = val_c;
return SANE_STATUS_GOOD;
+ case OPT_PRE_IMPRINT_SPECSTRING:
+ if (strlen(val) < IMPRINT_SPECSTRING_LEN){
+ strncpy(s->pre_imprint.specstring, val, IMPRINT_SPECSTRING_LEN);
+ return SANE_STATUS_GOOD;
+ }
+ DBG (5, "sane_control_option: pre-imprint spec string '%s' exceed the limit of %d characters\n", (SANE_String)val, IMPRINT_SPECSTRING_LEN);
+ return SANE_STATUS_INVAL;
+
+ case OPT_PRE_IMPRINT_H_OFFSET:
+ s->pre_imprint.h_offset = val_c;
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_V_OFFSET:
+ s->pre_imprint.v_offset = val_c;
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_FONT_SIZE:
+ if (!strcmp (val, STRING_IMPRINTER_12x12_FONT)) {
+ s->pre_imprint.font_size = IMPRINTER_12x12_FONT;
+ }
+ if (!strcmp (val, STRING_IMPRINTER_8x12_FONT)) {
+ s->pre_imprint.font_size = IMPRINTER_8x12_FONT;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_FONT_ROT:
+ switch (val_c){
+ case 0:
+ s->pre_imprint.font_rot = IMPRINTER_0_FONT_ROT;
+ break;
+
+ case 90:
+ s->pre_imprint.font_rot = IMPRINTER_90_FONT_ROT;
+ break;
+
+ case 180:
+ s->pre_imprint.font_rot = IMPRINTER_180_FONT_ROT;
+ break;
+
+ case 270:
+ s->pre_imprint.font_rot = IMPRINTER_270_FONT_ROT;
+ break;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_PRE_IMPRINT_SPACING:
+ s->pre_imprint.spacing = val_c;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_SPECSTRING:
+ if (strlen(val) < IMPRINT_SPECSTRING_LEN){
+ strncpy(s->post_imprint.specstring, val, IMPRINT_SPECSTRING_LEN);
+ return SANE_STATUS_GOOD;
+ }
+ DBG (5, "sane_control_option: post-imprint spec string '%s' exceed the limit of %d characters\n", (SANE_String)val, IMPRINT_SPECSTRING_LEN);
+ return SANE_STATUS_INVAL;
+
+ case OPT_POST_IMPRINT_H_OFFSET:
+ s->post_imprint.h_offset = val_c;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_V_OFFSET:
+ s->post_imprint.v_offset = val_c;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_FONT_SIZE:
+ if (!strcmp (val, STRING_IMPRINTER_12x12_FONT)) {
+ s->post_imprint.font_size = IMPRINTER_12x12_FONT;
+ }
+ if (!strcmp (val, STRING_IMPRINTER_8x12_FONT)) {
+ s->post_imprint.font_size = IMPRINTER_8x12_FONT;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_FONT_ROT:
+ switch (val_c){
+ case 0:
+ s->post_imprint.font_rot = IMPRINTER_0_FONT_ROT;
+ break;
+
+ case 90:
+ s->post_imprint.font_rot = IMPRINTER_90_FONT_ROT;
+ break;
+
+ case 180:
+ s->post_imprint.font_rot = IMPRINTER_180_FONT_ROT;
+ break;
+
+ case 270:
+ s->post_imprint.font_rot = IMPRINTER_270_FONT_ROT;
+ break;
+ }
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_SPACING:
+ s->post_imprint.spacing = val_c;
+ return SANE_STATUS_GOOD;
+
+ case OPT_POST_IMPRINT_ADDON_MODE:
+ if (!strcmp (val, STRING_IMPRINTER_ADDON_BoW)) {
+ s->post_imprint_addon_mode = ADDON_BoW;
+ }
+ if (!strcmp (val, STRING_IMPRINTER_ADDON_BoI)) {
+ s->post_imprint_addon_mode = ADDON_BoI;
+ }
+ if (!strcmp (val, STRING_IMPRINTER_ADDON_WoB)) {
+ s->post_imprint_addon_mode = ADDON_WoB;
+ }
+ if (!strcmp (val, STRING_NONE)) {
+ s->post_imprint_addon_mode = ADDON_DISABLED;
+ }
+ return SANE_STATUS_GOOD;
+
}
} /* else */
@@ -3636,6 +4255,14 @@ ssm_df (struct scanner *s)
set_SSM2_DF_staple(out, 1);
}
+ int requires_postimprint = s->has_post_imprinter && (strlen(s->post_imprint.specstring) > 0);
+ int requires_preimprint = s->has_pre_imprinter && (strlen(s->pre_imprint.specstring) > 0);
+ if (s->has_post_imprinter)
+ set_SSM2_DF_post_addon(out, requires_postimprint);
+ if (requires_postimprint || requires_preimprint){
+ set_SSM2_DF_imprint(out, 1);
+ }
+
ret = do_cmd (
s, 1, 0,
cmd, cmdLen,
@@ -3897,6 +4524,50 @@ ssm_do (struct scanner *s)
}
static SANE_Status
+read_counters(struct scanner *s)
+{
+ SANE_Status ret = SANE_STATUS_GOOD;
+
+ unsigned char cmd[READ_len];
+ size_t cmdLen = READ_len;
+
+ unsigned char in[R_COUNTERS_len];
+ size_t inLen = R_COUNTERS_len;
+
+ if (!s->can_read_lifecycle_counters){
+ DBG(10, "read_counters: unsupported\n");
+ return ret;
+ }
+
+ DBG(10, "read_counters: start\n");
+
+ memset(cmd,0,cmdLen);
+ set_SCSI_opcode(cmd, READ_code);
+ set_R_datatype_code(cmd, SR_datatype_counters);
+ set_R_xfer_length(cmd, inLen);
+
+ ret = do_cmd(
+ s, 1, 0,
+ cmd, cmdLen,
+ NULL, 0,
+ in, &inLen
+ );
+
+ if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF){
+
+ s->total_counter = get_R_COUNTERS_total(in);
+ s->roller_counter = s->total_counter - get_R_COUNTERS_last_srv(in);
+
+ DBG(10, "read_counters: total counter: %d roller_counter %d \n",s->total_counter,s->roller_counter);
+ ret = SANE_STATUS_GOOD;
+ }else{
+ DBG(10, "read_counters: ERROR: %d\n",ret);
+ }
+
+ return ret;
+}
+
+static SANE_Status
read_sensors(struct scanner *s,SANE_Int option)
{
SANE_Status ret=SANE_STATUS_GOOD;
@@ -4382,6 +5053,248 @@ update_params(struct scanner *s, int calib)
return ret;
}
+/* simplify handling cmd SANE_STATUS_EOF as SANE_STATUS_GOOD */
+SANE_Status
+send_cmd(struct scanner *s, unsigned char* cmd, size_t cmdLen,
+ unsigned char* out, size_t outLen,
+ unsigned char * inBuff, size_t * inLen)
+{
+ SANE_Status ret=SANE_STATUS_GOOD;
+
+ ret = do_cmd (
+ s, 1, 0,
+ cmd, cmdLen,
+ out, outLen,
+ inBuff, inLen
+ );
+
+ if (ret == SANE_STATUS_EOF) {
+ ret = SANE_STATUS_GOOD;
+ }
+
+ return ret;
+}
+
+SANE_Status
+send_imprint_positioning(struct scanner* s, int is_postimprint, int enabled)
+{
+ unsigned char cmd[SET_SCAN_MODE2_len];
+ size_t cmdLen=SET_SCAN_MODE2_len;
+
+ unsigned char out[SSM2_PAY_len];
+ size_t outLen=SSM2_PAY_len;
+
+ unsigned char out_prefix[5]={ 0x01, 0x00, 0x60, 0x00, 0x60 };
+ size_t outPrefixLen=5;
+
+ memset(cmd,0,cmdLen);
+ set_SCSI_opcode(cmd,SET_SCAN_MODE2_code);
+ set_SSM2_page_code(cmd,SM2_pc_imprinter_settings);
+ if (is_postimprint)
+ set_SSM2_postimprint_cmd(cmd);
+ set_SSM2_pay_len(cmd,outLen);
+
+ memset(out,0,outLen);
+ memcpy(out,out_prefix,outPrefixLen);
+
+ int h_offset;
+ int v_offset;
+ if (is_postimprint){
+ if (s->post_imprint_addon_mode != ADDON_DISABLED)
+ set_SSM2_postimprint_addon(out);
+ h_offset = s->post_imprint.h_offset;
+ v_offset = s->post_imprint.v_offset;
+
+ if (enabled)
+ DBG (10, "send_imprint_positioning: post-imprinter: h_offset: %d v_offset: %d\n",h_offset,v_offset);
+ }else{
+ h_offset = s->pre_imprint.h_offset;
+ v_offset = s->pre_imprint.v_offset;
+ if (enabled)
+ DBG (10, "send_imprint_positioning: pre-imprinter: h_offset: %d v_offset: %d\n",h_offset,v_offset);
+ }
+ if(!enabled)
+ h_offset = v_offset = 0;
+ set_SSM2_imprint_hoffset(out,h_offset);
+ set_SSM2_imprint_voffset(out,v_offset);
+
+ return send_cmd(s, cmd, cmdLen, out, outLen, NULL, NULL);
+}
+
+SANE_Status
+send_imprint_specstring(struct scanner* s, int is_postimprint)
+{
+ unsigned char cmd[SET_SCAN_MODE2_len];
+ size_t cmdLen = SET_SCAN_MODE2_len;
+
+ unsigned char out[SSM2_IMPRINTER_STRING_PAY_len];
+ size_t outLen = SSM2_IMPRINTER_STRING_PAY_len;
+
+ memset(cmd,0,cmdLen);
+ set_SCSI_opcode(cmd, SET_SCAN_MODE2_code);
+ set_SSM2_page_code(cmd, SM2_pc_imprinter_specstring);
+ if (is_postimprint)
+ set_SSM2_postimprint_cmd(cmd);
+ set_SSM2_pay_len(cmd, outLen);
+
+ memset(out,0,outLen);
+ /* most of these bytes have yet to be identified to specific functionalities,
+ as they never seem to change under different imprinting mode */
+ unsigned char out_prefix[32] = {
+ 0x01, 0x00,
+ 0x60, 0x00,
+ 0x60, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x03, 0x00,
+ 0x00, 0x00,
+ 0x01, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x01,
+ 0x04, 0x00,
+ 0x00, 0x00
+ };
+ memcpy(out, out_prefix, 32);
+ if (is_postimprint){
+ set_SSM2_imprint_fontsize(out, s->post_imprint.font_size);
+ set_SSM2_imprint_fontrot(out, s->post_imprint.font_rot);
+ set_SSM2_imprint_spacing(out, s->post_imprint.spacing);
+ if (s->post_imprint_addon_mode != ADDON_DISABLED)
+ set_SSM2_imprint_addonmode(out, s->post_imprint_addon_mode);
+ strcpy((SANE_Char*)(out + 45), (SANE_String_Const) s->post_imprint.specstring);
+ DBG (10, "send_imprint_specstring: post-imprinter: font size: %d rotation: %d spacing: %d text: '%s' imprint-addon-mode: %d\n",s->post_imprint.font_size,s->post_imprint.font_rot,s->post_imprint.spacing,s->post_imprint.specstring,s->post_imprint_addon_mode);
+ }else{
+ set_SSM2_imprint_fontsize(out, s->pre_imprint.font_size);
+ set_SSM2_imprint_fontrot(out, s->pre_imprint.font_rot);
+ set_SSM2_imprint_spacing(out, s->pre_imprint.spacing);
+ strcpy((SANE_Char*)(out + 45), (SANE_String_Const) s->pre_imprint.specstring);
+ DBG (10, "send_imprint_specstring: pre-imprinter: font size: %d rotation: %d spacing: %d text: '%s'\n",s->pre_imprint.font_size,s->pre_imprint.font_rot,s->pre_imprint.spacing,s->pre_imprint.specstring);
+ }
+
+ return send_cmd(s, cmd, cmdLen, out, outLen, NULL, NULL);
+}
+
+SANE_Status
+send_imprint_date_and_time(struct scanner* s)
+{
+ unsigned char cmd[SET_SCAN_MODE2_len];
+ size_t cmdLen = SET_SCAN_MODE2_len;
+
+ unsigned char out[SSM2_PAY_len];
+ size_t outLen = SSM2_PAY_len;
+
+ memset(cmd,0,cmdLen);
+ set_SCSI_opcode(cmd, SET_SCAN_MODE2_code);
+ set_SSM2_page_code(cmd, SM2_pc_date_time);
+ set_SSM2_pay_len(cmd, outLen);
+
+ memset(out,0,outLen);
+
+ time_t t = time(NULL);
+ struct tm tM = *localtime(&t);
+
+ set_SSM2_imprint_year(out, tM.tm_year + 1900);
+ set_SSM2_imprint_month(out, tM.tm_mon + 1);
+ set_SSM2_imprint_day(out, tM.tm_mday);
+ set_SSM2_imprint_hour(out, tM.tm_hour);
+ set_SSM2_imprint_min(out, tM.tm_min);
+ set_SSM2_imprint_sec(out, tM.tm_sec);
+
+ return send_cmd(s, cmd, cmdLen, out, outLen, NULL, NULL);
+}
+
+SANE_Status
+load_imprinting_settings(struct scanner *s)
+{
+ SANE_Status ret = SANE_STATUS_GOOD;
+
+ int requires_preimprint = (strlen(s->pre_imprint.specstring) > 0);
+ int requires_postimprint = (strlen(s->post_imprint.specstring) > 0);
+ int send_date_time = (s->has_pre_imprinter && requires_preimprint) || (s->has_post_imprinter && requires_postimprint);
+
+ if (s->has_pre_imprinter){
+ ret = send_imprint_positioning(s, 0, requires_preimprint);
+ DBG(10, "load_imprinting_settings: send_pre_imprint_positioning = %d \n", ret);
+ if (ret != SANE_STATUS_GOOD)
+ return ret;
+ if (requires_preimprint){
+ ret = send_imprint_specstring(s, 0);
+ DBG(10, "load_imprinting_settings: send_pre_imprint_specstring = %d \n", ret);
+ if (ret != SANE_STATUS_GOOD)
+ return ret;
+ }
+ }
+
+ if (s->has_post_imprinter){
+ ret = send_imprint_positioning(s, 1, requires_postimprint);
+ DBG(10, "load_imprinting_settings: send_post_imprint_positioning = %d \n", ret);
+ if (ret != SANE_STATUS_GOOD)
+ return ret;
+ if (requires_postimprint){
+ ret = send_imprint_specstring(s, 1);
+ DBG(10, "load_imprinting_settings: send_post_imprint_specstring = %d \n", ret);
+ if (ret != SANE_STATUS_GOOD)
+ return ret;
+ }
+ }
+
+ if (send_date_time){
+ ret = send_imprint_date_and_time(s);
+ DBG(10, "load_imprinting_settings: send_imprint_date_and_time = %d \n", ret);
+ }
+ return ret;
+}
+
+static SANE_Status
+detect_imprinter(struct scanner *s,SANE_Int option)
+{
+ SANE_Status ret = SANE_STATUS_GOOD;
+
+ unsigned char cmd[READ_len];
+ size_t cmdLen = READ_len;
+
+ unsigned char in[R_IMPRINTER_len];
+ size_t inLen = R_IMPRINTER_len;
+
+ DBG (10, "detect_imprinter: start %d\n", option);
+
+ memset(cmd,0,cmdLen);
+ set_SCSI_opcode(cmd, READ_code);
+ set_R_datatype_code(cmd, SR_datatype_imprinters);
+ set_R_xfer_uid(cmd, option);
+ set_R_xfer_length(cmd, inLen);
+
+ ret = do_cmd(
+ s, 1, 0,
+ cmd, cmdLen,
+ NULL, 0,
+ in, &inLen
+ );
+
+ if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) {
+ ret = SANE_STATUS_GOOD;
+ }
+
+ int imprinter_found = get_R_IMPRINTER_found(in);
+ const char* imprinter_type = "unknown";
+ if (option == R_PRE_IMPRINTER){
+ s->has_pre_imprinter = imprinter_found;
+ imprinter_type = "pre-imprinter";
+ }
+ else if (option == R_POST_IMPRINTER){
+ s->has_post_imprinter = imprinter_found;
+ imprinter_type = "post-imprinter";
+ }
+
+ DBG (10, "detect_imprinter: type: %s. found status bit: %d \n",imprinter_type,imprinter_found);
+
+ return ret;
+}
+
/* reset image size parameters after buffer_xxx functions changed them */
SANE_Status
update_i_params(struct scanner *s)
@@ -4471,6 +5384,14 @@ sane_start (SANE_Handle handle)
goto errors;
}
+ if (s->has_pre_imprinter || s->has_post_imprinter){
+ ret = load_imprinting_settings(s);
+ if (ret != SANE_STATUS_GOOD) {
+ DBG (5, "sane_start: ERROR: invalid imprinting settings\n");
+ goto errors;
+ }
+ }
+
/* reset the page counter after calibration */
s->panel_counter = 0;
s->prev_page = 0;
@@ -7204,7 +8125,7 @@ sense_handler (int fd, unsigned char * sensed_data, void *arg)
DBG (5, "sense_handler: start\n");
/* kill compiler warning */
- fd = fd;
+ (void) fd;
/* copy the rs return data into the scanner struct
so that the caller can use it if he wants
@@ -7465,8 +8386,8 @@ do_scsi_cmd(struct scanner *s, int runRS, int timeout,
int ret;
/*shut up compiler*/
- runRS=runRS;
- timeout=timeout;
+ (void) runRS;
+ (void) timeout;
DBG(10, "do_scsi_cmd: start\n");