kopia lustrzana https://gitlab.com/sane-project/backends
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
rodzic
082cf4cdf3
commit
d61a59ca01
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
Ładowanie…
Reference in New Issue