canon_dr backend v64

- add complete support for imprinters on X10C (#585)

The vast majority of the work here was originally done in !706 by
Charles Quarra. I had some merge conflicts, and it was easier to
pull all his work into a patch and apply it myself.

The only changes I made were minor updates to comments, and adding
an imprinter group option. Sorry for the loss of attribution, and
thanks Charles!
merge-requests/768/head
m. allan noah 2022-11-18 21:14:28 -05:00
rodzic bab852c5bb
commit ba1b68e6e9
3 zmienionych plików z 904 dodań i 3 usunięć

Wyświetl plik

@ -222,6 +222,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define SR_datatype_endorser 0x90
#define SR_datatype_fineoffset 0x90
#define SR_datatype_finegain 0x91
#define SR_datatype_imprinters 0x96 /*DR-X10C*/
/* ==================================================================== */
/* READ */
@ -258,6 +259,18 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define get_R_COUNTERS_total(in) getnbyte(in + 0x04, 4)
#define get_R_COUNTERS_last_srv(in) getnbyte(in + 0x44, 4)
/*imprinters*/
#define R_IMPRINTER_len 0x20
#define R_PRE_IMPRINTER 0
#define R_POST_IMPRINTER 1
#define get_R_IMPRINTER_found(in) getbitfield(in+1, 1, 0)
/*4 bytes at in + 0: (DR-X10C)
pre-imprinter on: 0x07010000
pre-imprinter off: 0x06000000
post-imprinter on: 0x03010000
post-imprinter off: 0x02000000
*/
/*endorser unread?*/
/*fine gain*/
@ -458,6 +471,14 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define SM2_pc_buffer 0x02
#define SM2_pc_hw_enhancement 0x03
#define SM2_pc_dropout 0x06
#define SM2_pc_date_time 0x07
#define SM2_pc_imprinter_settings 0x33
#define SM2_pc_imprinter_specstring 0x34
/* ==================================================================== */
/* GET SCAN MODE 2 */
#define GET_SCAN_MODE2_code 0xe4
#define GET_SCAN_MODE2_len 12
/* ==================================================================== */
/* SET SCAN MODE 2 */
@ -469,11 +490,15 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
/* the payload */
#define SSM2_PAY_len 0x10
#define SSM2_IMPRINTER_STRING_PAY_len 0x8e
/* for DF (0x00) page */
#define set_SSM2_DF_thick(sb, val) setbitfield(sb+3, 1, 2, val)
#define set_SSM2_DF_imprint(sb, val) setbitfield(sb+2, 1, 0, val)
#define set_SSM2_DF_post_addon(sb, val) setbitfield(sb+2, 1, 1, val)
#define set_SSM2_DF_len(sb, val) setbitfield(sb+3, 1, 0, val)
#define set_SSM2_DF_thick(sb, val) setbitfield(sb+3, 1, 2, val)
#define set_SSM2_DF_staple(sb, val) setbitfield(sb+3, 1, 4, val)
#define set_SSM2_DF_imprint2(sb, val) setbitfield(sb+3, 1, 6, val)
/* for ULTRA (0x01) page */
#define set_SSM2_ULTRA_top(sb, val) putnbyte(sb + 0x07, val, 2)
@ -493,6 +518,32 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define set_SSM2_DO_en(sb, val) sb[0x0a] = val
#define set_SSM2_DO_side(sb, val) sb[0x05] = val
/* for IMPRINT DATE & TIME (0x07) */
#define set_SSM2_imprint_year(sb, val) putnbyte(sb + 0x02, val, 2)
#define set_SSM2_imprint_month(sb, val) putnbyte(sb + 0x04, val, 1)
#define set_SSM2_imprint_day(sb, val) putnbyte(sb + 0x05, val, 1)
#define set_SSM2_imprint_hour(sb, val) putnbyte(sb + 0x06, val, 1)
#define set_SSM2_imprint_min(sb, val) putnbyte(sb + 0x07, val, 1)
#define set_SSM2_imprint_sec(sb, val) putnbyte(sb + 0x08, val, 1)
/* for IMPRINTER SETTINGS (0x33) page */
#define set_SSM2_postimprint_cmd(sb) sb[0x04] = 1
#define set_SSM2_postimprint_addon(sb) setbitfield(sb, 1, 1, 1)
#define set_SSM2_imprint_hoffset(sb, val) putnbyte(sb + 0x05, val, 2)
#define set_SSM2_imprint_voffset(sb, val) putnbyte(sb + 0x07, val, 2)
/* for IMPRINTER STRING SPECIFICATION (0x34) page */
#define IMPRINTER_12x12_FONT 0
#define IMPRINTER_8x12_FONT 1
#define set_SSM2_imprint_fontsize(sb, val) setbitfield(sb + 0xA, 1, 0, val)
#define set_SSM2_imprint_spacing(sb, val) setbitfield(sb + 0xA, 1, 1, val)
#define set_SSM2_imprint_addonmode(sb, val) setbitfield(sb + 0x9, 3, 4, val)
#define IMPRINTER_0_FONT_ROT 0
#define IMPRINTER_90_FONT_ROT 1
#define IMPRINTER_180_FONT_ROT 2
#define IMPRINTER_270_FONT_ROT 3
#define set_SSM2_imprint_fontrot(sb, val) setbitfield(sb + 0x9, 3, 0, val)
/* ==================================================================== */
/* window descriptor macros for SET_WINDOW and GET_WINDOW */

Wyświetl plik

@ -357,6 +357,8 @@
- 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
@ -395,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"
@ -408,7 +411,7 @@
#include "canon_dr.h"
#define DEBUG 1
#define BUILD 63
#define BUILD 64
/* values for SANE_DEBUG_CANON_DR env var:
- errors 5
@ -451,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;
@ -994,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) {
@ -1879,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;
@ -1901,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");
@ -1908,6 +1980,30 @@ init_model (struct scanner *s)
return SANE_STATUS_GOOD;
}
/*
* 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
*/
@ -2014,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;
@ -2798,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;
@ -3197,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);
@ -3530,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 */
@ -3735,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,
@ -4525,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)
@ -4614,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;

Wyświetl plik

@ -51,6 +51,22 @@ enum scanner_Option
OPT_SIDE,
OPT_HW_CROP,
/*imprinter option group*/
OPT_IMPRINT_GROUP,
OPT_PRE_IMPRINT_SPECSTRING,
OPT_PRE_IMPRINT_H_OFFSET,
OPT_PRE_IMPRINT_V_OFFSET,
OPT_PRE_IMPRINT_FONT_SIZE,
OPT_PRE_IMPRINT_FONT_ROT,
OPT_PRE_IMPRINT_SPACING,
OPT_POST_IMPRINT_SPECSTRING,
OPT_POST_IMPRINT_H_OFFSET,
OPT_POST_IMPRINT_V_OFFSET,
OPT_POST_IMPRINT_FONT_SIZE,
OPT_POST_IMPRINT_FONT_ROT,
OPT_POST_IMPRINT_SPACING,
OPT_POST_IMPRINT_ADDON_MODE,
/*sensor group*/
OPT_SENSOR_GROUP,
OPT_START,
@ -108,6 +124,32 @@ struct img_params
};
struct imprint_params
{
/* ------------------------------------------------------------------------------ */
/* allowed values for post imprinter (in mm units): */
/* 21, 35, 47, 59, 72, 99, 114, 143, 155, 167, 196, 211, 239, 251, 263, 275, 289 */
/* allowed values for pre imprinter (in mm units): */
/* 14, 28, 41, 53, 65, 106 */
int h_offset;
/* --------------------------------------- */
/* allowed values: 0 to 500 (in mm units) */
int v_offset;
int font_size;
int font_rot;
int spacing;
#define IMPRINT_SPECSTRING_LEN 64
/* ---------------------------------- */
/* special tokens: */
/* \TIME time in HH:MM:SS */
/* \DMY date in DD/MM/YYYY */
/* \YMD date in YYYY/MM/DD */
/* [[0-9]+] scan page count */
char specstring[IMPRINT_SPECSTRING_LEN];
};
struct scanner
{
/* --------------------------------------------------------------------- */
@ -206,6 +248,8 @@ struct scanner
int has_ssm2; /* newer scanners user this similar command */
int has_ssm_pay_head_len; /* newer scanners put the length twice in ssm */
int has_hwcrop;
int has_pre_imprinter;
int has_post_imprinter;
int can_read_sensors;
int can_read_panel;
int can_write_panel;
@ -320,13 +364,34 @@ struct scanner
unsigned char lut[256];
/* --------------------------------------------------------------------- */
/* values used by the software enhancement code (deskew, crop, etc) */
/* values used by the software enhancement code (deskew, crop, etc) */
SANE_Status deskew_stat;
int deskew_vals[2];
double deskew_slope;
int crop_vals[4];
/* imprinter params */
struct imprint_params pre_imprint;
struct imprint_params post_imprint;
enum {
/*Black-on-White*/
ADDON_BoW = 0,
/*White-on-Black*/
ADDON_WoB,
/*Black-on-Image*/
ADDON_BoI,
ADDON_DISABLED
} post_imprint_addon_mode;
/* imprinter param constraints */
SANE_Int pre_imprinter_h_offset_list[7];
SANE_Int post_imprinter_h_offset_list[18];
SANE_Range imprinter_v_offset_range;
SANE_String_Const imprint_font_size_list[3];
SANE_Int imprinter_font_angle_list[5];
SANE_String_Const imprint_addon_mode_list[5];
/* this is defined in sane spec as a struct containing:
SANE_Frame format;
SANE_Bool last_frame;
@ -546,6 +611,7 @@ static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg);
static SANE_Status init_inquire (struct scanner *s);
static SANE_Status init_vpd (struct scanner *s);
static SANE_Status init_model (struct scanner *s);
static SANE_Status init_imprinters (struct scanner *s);
static SANE_Status init_panel (struct scanner *s);
static SANE_Status init_counters (struct scanner *s);
static SANE_Status init_user (struct scanner *s);
@ -639,6 +705,12 @@ static SANE_Status calibrate_fine_dest_hw(struct scanner *s);
static SANE_Status write_AFE (struct scanner *s);
static SANE_Status calibration_scan (struct scanner *s, int);
static SANE_Status send_imprint_positioning(struct scanner* s, int is_postimprint, int enabled);
static SANE_Status send_imprint_specstring(struct scanner* s, int is_postimprint);
static SANE_Status send_imprint_date_and_time(struct scanner* s);
static SANE_Status load_imprinting_settings(struct scanner *s);
static SANE_Status detect_imprinter(struct scanner *s, SANE_Int option);
static void hexdump (int level, char *comment, unsigned char *p, int l);
static void default_globals (void);