Add support for Canon DR-X10C scanner

Added initial support for DR-X10C SSM2 scanner with dropout color, hardware
deskew and hardware crop.
merge-requests/43/head
Manuel Argüelles 2018-07-30 17:26:13 -05:00
rodzic 082cf4cdf3
commit d61a59ca01
4 zmienionych plików z 245 dodań i 3 usunięć

Wyświetl plik

@ -258,6 +258,11 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define R_FINE_uid_blue 0x09
#define R_FINE_uid_unknown 0x14
/* get pixel size */
#define R_PSIZE_len 16
#define get_R_PSIZE_width(in) getnbyte(in + 0x08, 4)
#define get_R_PSIZE_length(in) getnbyte(in + 0x0c, 4)
/* ==================================================================== */
/* SEND */
#define SEND_code 0x2a
@ -431,6 +436,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define SM2_pc_df 0x00
#define SM2_pc_ultra 0x01
#define SM2_pc_buffer 0x02
#define SM2_pc_hw_enhancement 0x03
#define SM2_pc_dropout 0x06
/* ==================================================================== */
@ -447,6 +453,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
/* for DF (0x00) page */
#define set_SSM2_DF_thick(sb, val) setbitfield(sb+3, 1, 2, val)
#define set_SSM2_DF_len(sb, val) setbitfield(sb+3, 1, 0, val)
#define set_SSM2_DF_staple(sb, val) setbitfield(sb+3, 1, 4, val)
/* for ULTRA (0x01) page */
#define set_SSM2_ULTRA_top(sb, val) putnbyte(sb + 0x07, val, 2)
@ -457,9 +464,14 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define set_SSM2_BUFF_unk2(sb, val) sb[0x06] = val
#define set_SSM2_BUFF_sync(sb, val) sb[0x09] = val
/* for HARDWARE ENHANCEMENT (0x03) */
#define set_SSM2_roller_deskew(sb, val) setbitfield(sb+6, 1, 3, val)
#define set_SSM2_hw_crop(sb, val) setbitfield(sb+6, 1, 5, val)
/* for DROPOUT (0x06) page */
#define set_SSM2_DO_do(sb, val) sb[0x09] = val
#define set_SSM2_DO_en(sb, val) sb[0x0a] = val
#define set_SSM2_DO_side(sb, val) sb[0x05] = val
/* ==================================================================== */
/* window descriptor macros for SET_WINDOW and GET_WINDOW */

Wyświetl plik

@ -1690,6 +1690,34 @@ init_model (struct scanner *s)
s->can_halftone = 0;
}
else if (strstr (s->model_name,"DR-X10C")){
/* Required for USB coms */
s->has_ssm = 0;
s->has_ssm2 = 1;
/* missing */
s->std_res_x[DPI_100]=1;
s->std_res_y[DPI_100]=1;
s->std_res_x[DPI_150]=1;
s->std_res_y[DPI_150]=1;
s->std_res_x[DPI_200]=1;
s->std_res_y[DPI_200]=1;
s->std_res_x[DPI_240]=1;
s->std_res_y[DPI_240]=1;
s->std_res_x[DPI_300]=1;
s->std_res_y[DPI_300]=1;
s->std_res_x[DPI_400]=1;
s->std_res_y[DPI_400]=1;
s->std_res_x[DPI_600]=1;
s->std_res_y[DPI_600]=1;
s->reverse_by_mode[MODE_LINEART] = 0;
s->reverse_by_mode[MODE_HALFTONE] = 0;
s->has_hwcrop = 1;
}
DBG (10, "init_model: finish\n");
return SANE_STATUS_GOOD;
@ -2551,6 +2579,18 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
opt->constraint_type = SANE_CONSTRAINT_NONE;
}
/*hardware crop*/
if(option==OPT_HW_CROP){
opt->name = "hwcrop";
opt->title = "Hardware crop";
opt->desc = "Request scanner to crop image automatically";
opt->type = SANE_TYPE_BOOL;
if (s->has_hwcrop)
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;
@ -2963,6 +3003,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
ret = read_sensors(s,OPT_CARD_LOADED);
*val_p = s->sensor_card_loaded;
return ret;
case OPT_HW_CROP:
*val_p = s->hwcrop;
return SANE_STATUS_GOOD;
}
}
else if (action == SANE_ACTION_SET_VALUE) {
@ -3237,6 +3281,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
s->buffermode = val_c;
return SANE_STATUS_GOOD;
case OPT_HW_CROP:
s->hwcrop = val_c;
return SANE_STATUS_GOOD;
}
} /* else */
@ -3437,6 +3485,11 @@ ssm_df (struct scanner *s)
set_SSM2_DF_len(out, 1);
}
/* staple detection */
if(s->stapledetect){
set_SSM2_DF_staple(out, 1);
}
ret = do_cmd (
s, 1, 0,
cmd, cmdLen,
@ -3455,6 +3508,53 @@ ssm_df (struct scanner *s)
return ret;
}
static SANE_Status
ssm2_hw_enhancement (struct scanner *s)
{
SANE_Status ret = SANE_STATUS_GOOD;
DBG (10, "ssm2_hw_enhancement: start\n");
if(s->has_ssm2){
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_hw_enhancement);
set_SSM2_pay_len(cmd, outLen);
memset(out,0,outLen);
if(s->rollerdeskew){
set_SSM2_roller_deskew(out, 1);
}
if(s->hwcrop){
set_SSM2_hw_crop(out, 1);
}
ret = do_cmd (
s, 1, 0,
cmd, cmdLen,
out, outLen,
NULL, NULL
);
}
else{
DBG (10, "ssm2_hw_enhancement: unsupported\n");
}
DBG (10, "ssm2_hw_enhancement: finish\n");
return ret;
}
static SANE_Status
ssm_do (struct scanner *s)
{
@ -3599,6 +3699,46 @@ ssm_do (struct scanner *s)
out, outLen,
NULL, NULL
);
if(ret == SANE_STATUS_GOOD &&
(s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX)){
memset(cmd,0,cmdLen);
set_SCSI_opcode(cmd, SET_SCAN_MODE2_code);
set_SSM2_page_code(cmd, SM2_pc_dropout);
set_SSM2_DO_side(cmd, SIDE_BACK);
set_SSM2_pay_len(cmd, outLen);
memset(out,0,outLen);
switch(s->dropout_color[SIDE_BACK]){
case COLOR_RED:
set_SSM2_DO_do(out,SSM_DO_red);
break;
case COLOR_GREEN:
set_SSM2_DO_do(out,SSM_DO_green);
break;
case COLOR_BLUE:
set_SSM2_DO_do(out,SSM_DO_blue);
break;
case COLOR_EN_RED:
set_SSM2_DO_en(out,SSM_DO_red);
break;
case COLOR_EN_GREEN:
set_SSM2_DO_en(out,SSM_DO_green);
break;
case COLOR_EN_BLUE:
set_SSM2_DO_en(out,SSM_DO_blue);
break;
}
ret = do_cmd (
s, 1, 0,
cmd, cmdLen,
out, outLen,
NULL, NULL
);
}
}
else{
@ -3769,6 +3909,75 @@ send_panel(struct scanner *s)
return ret;
}
/*
* Request the size of the scanned image
*/
static SANE_Status
get_pixelsize(struct scanner *s)
{
SANE_Status ret = SANE_STATUS_GOOD;
unsigned char cmd[READ_len];
size_t cmdLen = READ_len;
unsigned char in[R_PSIZE_len];
size_t inLen = R_PSIZE_len;
int i = 0;
const int MAX_TRIES = 5;
DBG (10, "get_pixelsize: start\n");
if(!s->hwcrop){
DBG (10, "get_pixelsize: unneeded, finishing\n");
return ret;
}
memset(cmd,0,cmdLen);
set_SCSI_opcode(cmd, READ_code);
set_R_datatype_code(cmd, SR_datatype_pixelsize);
set_R_xfer_lid(cmd, 0x02);
set_R_xfer_length(cmd, inLen);
/* May need to retry/block until the scanner is done */
for(i=0;i<MAX_TRIES;i++){
ret = do_cmd (
s, 1, 0,
cmd, cmdLen,
NULL, 0,
in, &inLen
);
if(ret == SANE_STATUS_GOOD &&
get_R_PSIZE_width(in) > 0 &&
get_R_PSIZE_length(in) > 0){
DBG (15, "get_pixelsize: w:%d h:%d\n",
get_R_PSIZE_width(in) * s->u.dpi_x / 1200,
get_R_PSIZE_length(in) * s->u.dpi_y / 1200);
s->u.br_x = get_R_PSIZE_width(in);
s->u.tl_x = 0;
s->u.br_y = get_R_PSIZE_length(in);
s->u.tl_y = 0;
update_params(s,0);
clean_params(s);
break;
}
else{
DBG (10, "get_pixelsize: error reading, status = %d w:%d h:%d\n",
ret, get_R_PSIZE_width(in), get_R_PSIZE_length(in));
ret = SANE_STATUS_INVAL;
usleep(1000000);
}
}
DBG (10, "get_pixelsize: finish\n");
return ret;
}
/*
* @@ Section 4 - SANE scanning functions
*/
@ -4140,6 +4349,12 @@ sane_start (SANE_Handle handle)
goto errors;
}
ret = ssm2_hw_enhancement(s);
if (ret != SANE_STATUS_GOOD) {
DBG (5, "sane_start: ERROR: cannot ssm2 hw enhancement\n");
goto errors;
}
/* clean scan params for new scan */
ret = clean_params(s);
if (ret != SANE_STATUS_GOOD) {
@ -4185,6 +4400,12 @@ sane_start (SANE_Handle handle)
goto errors;
}
ret = get_pixelsize(s);
if (ret != SANE_STATUS_GOOD) {
DBG (5, "sane_start: ERROR: cannot get pixel size\n");
goto errors;
}
s->started = 1;
}
@ -4251,6 +4472,12 @@ sane_start (SANE_Handle handle)
DBG (5, "sane_start: diff counter (%d/%d)\n",
s->prev_page,s->panel_counter);
}
ret = get_pixelsize(s);
if (ret != SANE_STATUS_GOOD) {
DBG (5, "sane_start: ERROR: cannot get pixel size\n");
goto errors;
}
}
}
@ -7232,7 +7459,7 @@ do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength)
}
/*inspect the status byte of the response*/
else if(statBuffer[statOffset]){
DBG(5,"stat: status %d\n",statBuffer[statLength-1-4]);
DBG(5,"stat: status %d\n",statBuffer[statOffset]);
ret = do_usb_clear(s,0,runRS);
}

Wyświetl plik

@ -49,6 +49,7 @@ enum scanner_Option
OPT_DROPOUT_COLOR_B,
OPT_BUFFERMODE,
OPT_SIDE,
OPT_HW_CROP,
/*sensor group*/
OPT_SENSOR_GROUP,
@ -186,6 +187,7 @@ struct scanner
int has_ssm; /* older scanners use this set scan mode command */
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 can_read_sensors;
int can_read_panel;
int can_write_panel;
@ -286,6 +288,7 @@ struct scanner
int swcrop;
int swskip;
int stapledetect;
int hwcrop;
/* --------------------------------------------------------------------- */
/* values which are derived from setting the options above */

Wyświetl plik

@ -262,8 +262,8 @@
:model "DR-X10C"
:interface "USB SCSI"
:usbid "0x1083" "0x1618"
:status :untested
:comment "Please test!"
:status :good
:comment "Simplex, duplex, all resolutions, binary/ht/gray/color, async mode, dropout-color, multifeed/staple detection, deskew, autocrop working. Imprinter, barcode, custom gamma and multistream unsupported"
:model "DR-C120"
:interface "USB"