kopia lustrzana https://gitlab.com/sane-project/backends
canon_dr v59: fine calibration updates
- restructure fine calibration code - initial support for uploading fine calibration payloads - improve DR-C225 support Most canon scanners require that the driver apply fine (per-cell) calibration information. But a few require that the info be loaded into the scanner. Here, we add initial support for that, though the needed values are hardcoded instead of calculated.merge-requests/540/head
rodzic
588f01526e
commit
e46adab4f2
|
@ -70,6 +70,11 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
||||||
/* extended status packet */
|
/* extended status packet */
|
||||||
#define get_ES_length(b) getnbyte(b+0x04, 4)
|
#define get_ES_length(b) getnbyte(b+0x04, 4)
|
||||||
|
|
||||||
|
/* ==================================================================== */
|
||||||
|
/* USB packets */
|
||||||
|
#define set_USB_CMD_xfer_length(sb, val) putnbyte(sb + 1, val, 3)
|
||||||
|
#define set_USB_OUT_xfer_length(sb, val) putnbyte(sb + 1, val, 3)
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
/* SCSI commands */
|
/* SCSI commands */
|
||||||
|
|
||||||
|
@ -287,6 +292,17 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
||||||
/*counters*/
|
/*counters*/
|
||||||
/*endorser*/
|
/*endorser*/
|
||||||
|
|
||||||
|
/*fine calibration*/
|
||||||
|
#define set_S_FCAL_datatype(sb, val) sb[0x00] = (unsigned char)val
|
||||||
|
/* these are offset, OR with 0x40 to get gain */
|
||||||
|
#define S_FCAL_id_f_red 0x00
|
||||||
|
#define S_FCAL_id_f_green 0x04
|
||||||
|
#define S_FCAL_id_f_blue 0x08
|
||||||
|
#define S_FCAL_id_b_red 0x01
|
||||||
|
#define S_FCAL_id_b_green 0x05
|
||||||
|
#define S_FCAL_id_b_blue 0x09
|
||||||
|
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
/* OBJECT_POSITION */
|
/* OBJECT_POSITION */
|
||||||
#define OBJECT_POSITION_code 0x31
|
#define OBJECT_POSITION_code 0x31
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
This file is part of the SANE package, and implements a SANE backend
|
This file is part of the SANE package, and implements a SANE backend
|
||||||
for various Canon DR-series scanners.
|
for various Canon DR-series scanners.
|
||||||
|
|
||||||
Copyright (C) 2008-2019 m. allan noah
|
Copyright (C) 2008-2020 m. allan noah
|
||||||
|
|
||||||
Yabarana Corp. www.yabarana.com provided significant funding
|
Yabarana Corp. www.yabarana.com provided significant funding
|
||||||
EvriChart, Inc. www.evrichart.com provided funding and loaned equipment
|
EvriChart, Inc. www.evrichart.com provided funding and loaned equipment
|
||||||
|
@ -340,6 +340,10 @@
|
||||||
- complete support for X-10, including hardware cropping
|
- complete support for X-10, including hardware cropping
|
||||||
v58 2019-11-10, MAN
|
v58 2019-11-10, MAN
|
||||||
- adjust wait_scanner to set runRS only as a last resort, bug #154
|
- adjust wait_scanner to set runRS only as a last resort, bug #154
|
||||||
|
v59 2020-09-23, MAN
|
||||||
|
- restructure fine calibration code
|
||||||
|
- initial support for uploading fine calibration payloads
|
||||||
|
- improve DR-C225 support
|
||||||
|
|
||||||
SANE FLOW DIAGRAM
|
SANE FLOW DIAGRAM
|
||||||
|
|
||||||
|
@ -390,7 +394,7 @@
|
||||||
#include "canon_dr.h"
|
#include "canon_dr.h"
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
#define BUILD 58
|
#define BUILD 59
|
||||||
|
|
||||||
/* values for SANE_DEBUG_CANON_DR env var:
|
/* values for SANE_DEBUG_CANON_DR env var:
|
||||||
- errors 5
|
- errors 5
|
||||||
|
@ -1348,7 +1352,8 @@ init_model (struct scanner *s)
|
||||||
s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG;
|
s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG;
|
||||||
s->duplex_interlace = DUPLEX_INTERLACE_FBfb;
|
s->duplex_interlace = DUPLEX_INTERLACE_FBfb;
|
||||||
s->need_ccal = 1;
|
s->need_ccal = 1;
|
||||||
s->need_fcal = 1;
|
s->fcal_src = FCAL_SRC_SCAN;
|
||||||
|
s->fcal_dest = FCAL_DEST_SW;
|
||||||
/*s->duplex_offset = 432; now set in config file*/
|
/*s->duplex_offset = 432; now set in config file*/
|
||||||
s->duplex_offset_side = SIDE_BACK;
|
s->duplex_offset_side = SIDE_BACK;
|
||||||
|
|
||||||
|
@ -1372,7 +1377,8 @@ init_model (struct scanner *s)
|
||||||
s->duplex_interlace = DUPLEX_INTERLACE_2510;
|
s->duplex_interlace = DUPLEX_INTERLACE_2510;
|
||||||
/*s->duplex_offset = 400; now set in config file*/
|
/*s->duplex_offset = 400; now set in config file*/
|
||||||
s->need_ccal = 1;
|
s->need_ccal = 1;
|
||||||
s->need_fcal = 1;
|
s->fcal_src = FCAL_SRC_SCAN;
|
||||||
|
s->fcal_dest = FCAL_DEST_SW;
|
||||||
s->sw_lut = 1;
|
s->sw_lut = 1;
|
||||||
/*s->invert_tly = 1;*/
|
/*s->invert_tly = 1;*/
|
||||||
|
|
||||||
|
@ -1402,7 +1408,8 @@ init_model (struct scanner *s)
|
||||||
s->duplex_interlace = DUPLEX_INTERLACE_2510;
|
s->duplex_interlace = DUPLEX_INTERLACE_2510;
|
||||||
/*s->duplex_offset = 400; now set in config file*/
|
/*s->duplex_offset = 400; now set in config file*/
|
||||||
s->need_ccal = 1;
|
s->need_ccal = 1;
|
||||||
s->need_fcal = 1;
|
s->fcal_src = FCAL_SRC_SCAN;
|
||||||
|
s->fcal_dest = FCAL_DEST_SW;
|
||||||
s->sw_lut = 1;
|
s->sw_lut = 1;
|
||||||
s->invert_tly = 1;
|
s->invert_tly = 1;
|
||||||
|
|
||||||
|
@ -1427,7 +1434,8 @@ init_model (struct scanner *s)
|
||||||
s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB;
|
s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB;
|
||||||
s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB;
|
s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB;
|
||||||
s->duplex_interlace = DUPLEX_INTERLACE_FBfb;
|
s->duplex_interlace = DUPLEX_INTERLACE_FBfb;
|
||||||
s->need_fcal_buffer = 1;
|
s->fcal_src = FCAL_SRC_HW;
|
||||||
|
s->fcal_dest = FCAL_DEST_SW;
|
||||||
s->bg_color = 0x08;
|
s->bg_color = 0x08;
|
||||||
/*s->duplex_offset = 840; now set in config file*/
|
/*s->duplex_offset = 840; now set in config file*/
|
||||||
s->sw_lut = 1;
|
s->sw_lut = 1;
|
||||||
|
@ -1604,7 +1612,8 @@ init_model (struct scanner *s)
|
||||||
s->unknown_byte2 = 0x88;
|
s->unknown_byte2 = 0x88;
|
||||||
s->need_ccal = 1;
|
s->need_ccal = 1;
|
||||||
s->ccal_version = 3;
|
s->ccal_version = 3;
|
||||||
s->need_fcal = 1;
|
s->fcal_src = FCAL_SRC_SCAN;
|
||||||
|
s->fcal_dest = FCAL_DEST_SW;
|
||||||
s->sw_lut = 1;
|
s->sw_lut = 1;
|
||||||
s->rgb_format = 1;
|
s->rgb_format = 1;
|
||||||
/*s->duplex_offset = 400; now set in config file*/
|
/*s->duplex_offset = 400; now set in config file*/
|
||||||
|
@ -1625,14 +1634,15 @@ init_model (struct scanner *s)
|
||||||
else if (strstr (s->model_name,"DR-C225")){
|
else if (strstr (s->model_name,"DR-C225")){
|
||||||
|
|
||||||
s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB;
|
s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB;
|
||||||
s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_rRgGbB;
|
s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB;
|
||||||
s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG;
|
s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG;
|
||||||
s->duplex_interlace = DUPLEX_INTERLACE_FBfb;
|
s->duplex_interlace = DUPLEX_INTERLACE_PER_CHANNEL;
|
||||||
|
|
||||||
s->unknown_byte2 = 0x88;
|
s->unknown_byte2 = 0x88;
|
||||||
s->need_ccal = 1;
|
s->need_ccal = 1;
|
||||||
s->ccal_version = 3;
|
s->ccal_version = 3;
|
||||||
s->need_fcal = 1;
|
s->fcal_src = FCAL_SRC_SCAN;
|
||||||
|
s->fcal_dest = FCAL_DEST_HW;
|
||||||
s->invert_tly = 1;
|
s->invert_tly = 1;
|
||||||
s->rgb_format = 1;
|
s->rgb_format = 1;
|
||||||
/*s->duplex_offset = 400; now set in config file*/
|
/*s->duplex_offset = 400; now set in config file*/
|
||||||
|
@ -4314,22 +4324,19 @@ sane_start (SANE_Handle handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AFE cal */
|
/* AFE cal */
|
||||||
if((ret = calibrate_AFE(s))){
|
ret = calibrate_AFE(s);
|
||||||
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "sane_start: ERROR: cannot cal afe\n");
|
DBG (5, "sane_start: ERROR: cannot cal afe\n");
|
||||||
goto errors;
|
goto errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fine cal */
|
/* fine cal */
|
||||||
if((ret = calibrate_fine(s))){
|
ret = calibrate_fine(s);
|
||||||
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "sane_start: ERROR: cannot cal fine\n");
|
DBG (5, "sane_start: ERROR: cannot cal fine\n");
|
||||||
goto errors;
|
goto errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((ret = calibrate_fine_buffer(s))){
|
|
||||||
DBG (5, "sane_start: ERROR: cannot cal fine from buffer\n");
|
|
||||||
goto errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the page counter after calibration */
|
/* reset the page counter after calibration */
|
||||||
s->panel_counter = 0;
|
s->panel_counter = 0;
|
||||||
s->prev_page = 0;
|
s->prev_page = 0;
|
||||||
|
@ -5517,6 +5524,7 @@ copy_duplex(struct scanner *s, unsigned char * buf, int len)
|
||||||
{
|
{
|
||||||
SANE_Status ret=SANE_STATUS_GOOD;
|
SANE_Status ret=SANE_STATUS_GOOD;
|
||||||
int i,j;
|
int i,j;
|
||||||
|
int pwidth = s->s.width;
|
||||||
int bwidth = s->s.Bpl;
|
int bwidth = s->s.Bpl;
|
||||||
int dbwidth = 2*bwidth;
|
int dbwidth = 2*bwidth;
|
||||||
unsigned char * front;
|
unsigned char * front;
|
||||||
|
@ -5568,6 +5576,21 @@ copy_duplex(struct scanner *s, unsigned char * buf, int len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* line is in 6 sections, front red, back red, front green, etc. */
|
||||||
|
else if(s->duplex_interlace == DUPLEX_INTERLACE_PER_CHANNEL){
|
||||||
|
|
||||||
|
DBG (10, "copy_duplex: per channel\n");
|
||||||
|
|
||||||
|
for(i=0; i<len; i+=dbwidth){
|
||||||
|
for(j=0;j<3;j++){
|
||||||
|
memcpy(front+flen,buf+i+j*pwidth*2,pwidth);
|
||||||
|
flen+=pwidth;
|
||||||
|
memcpy(back+blen,buf+i+j*pwidth*2+pwidth,pwidth);
|
||||||
|
blen+=pwidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* full line of front, then full line of back */
|
/* full line of front, then full line of back */
|
||||||
else if(s->duplex_interlace == DUPLEX_INTERLACE_FfBb || s->duplex_interlace == DUPLEX_INTERLACE_fFBb){
|
else if(s->duplex_interlace == DUPLEX_INTERLACE_FfBb || s->duplex_interlace == DUPLEX_INTERLACE_fFBb){
|
||||||
for(i=0; i<len; i+=dbwidth){
|
for(i=0; i<len; i+=dbwidth){
|
||||||
|
@ -6119,10 +6142,68 @@ calibrate_AFE (struct scanner *s)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/* alternative version- extracts data from scanner memory */
|
* fine calibration produces a per-cell offset and gain value,
|
||||||
|
* which is then used to adjust the output from the scanner.
|
||||||
|
* There is quite a bit of variation here, with different models
|
||||||
|
* needing different types/amounts of help from the software.
|
||||||
|
*
|
||||||
|
* This function is a common entry point for all variations.
|
||||||
|
*/
|
||||||
static SANE_Status
|
static SANE_Status
|
||||||
calibrate_fine_buffer (struct scanner *s)
|
calibrate_fine (struct scanner *s)
|
||||||
|
{
|
||||||
|
SANE_Status ret = SANE_STATUS_GOOD;
|
||||||
|
|
||||||
|
DBG (10, "calibrate_fine: start\n");
|
||||||
|
|
||||||
|
if(s->fcal_src == FCAL_SRC_NONE || s->fcal_dest == FCAL_DEST_NONE){
|
||||||
|
DBG (10, "calibrate_fine: not required\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* don't recalibrate if we've already done it with these params */
|
||||||
|
if(s->f_res == s->s.dpi_x && s->f_mode == s->s.mode){
|
||||||
|
DBG (10, "calibrate_fine: already done\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get calibration data from scanner memory */
|
||||||
|
if(s->fcal_src == FCAL_SRC_HW){
|
||||||
|
ret = calibrate_fine_src_hw(s);
|
||||||
|
if (ret != SANE_STATUS_GOOD)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get calibration data by making scans */
|
||||||
|
if(s->fcal_src == FCAL_SRC_SCAN){
|
||||||
|
ret = calibrate_fine_src_scan(s);
|
||||||
|
if (ret != SANE_STATUS_GOOD)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send calibration data to scanner */
|
||||||
|
if(s->fcal_dest == FCAL_DEST_HW){
|
||||||
|
ret = calibrate_fine_dest_hw(s);
|
||||||
|
if (ret != SANE_STATUS_GOOD)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* log current cal settings so we won't recalibrate on next scan with same params */
|
||||||
|
s->f_res = s->s.dpi_x;
|
||||||
|
s->f_mode = s->s.mode;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
DBG (10, "calibrate_fine: finish %d\n",ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* extracts fine calibration data from scanner memory */
|
||||||
|
static SANE_Status
|
||||||
|
calibrate_fine_src_hw (struct scanner *s)
|
||||||
{
|
{
|
||||||
SANE_Status ret = SANE_STATUS_GOOD;
|
SANE_Status ret = SANE_STATUS_GOOD;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
@ -6138,12 +6219,7 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
int old_br_y = s->u.br_y;
|
int old_br_y = s->u.br_y;
|
||||||
int old_source = s->u.source;
|
int old_source = s->u.source;
|
||||||
|
|
||||||
DBG (10, "calibrate_fine_buffer: start\n");
|
DBG (10, "calibrate_fine_src_hw: start\n");
|
||||||
|
|
||||||
if(!s->need_fcal_buffer){
|
|
||||||
DBG (10, "calibrate_fine_buffer: not required\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pretend we are doing a 1 line scan in duplex */
|
/* pretend we are doing a 1 line scan in duplex */
|
||||||
s->u.tl_y = 0;
|
s->u.tl_y = 0;
|
||||||
|
@ -6153,19 +6229,14 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
/* load our own private copy of scan params */
|
/* load our own private copy of scan params */
|
||||||
ret = update_params(s,1);
|
ret = update_params(s,1);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine_buffer: ERROR: cannot update_params\n");
|
DBG (5, "calibrate_fine_src_hw: ERROR: cannot update_params\n");
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s->f_res == s->s.dpi_x && s->f_mode == s->s.mode){
|
|
||||||
DBG (10, "calibrate_fine_buffer: already done\n");
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean scan params for new scan */
|
/* clean scan params for new scan */
|
||||||
ret = clean_params(s);
|
ret = clean_params(s);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine_buffer: ERROR: cannot clean_params\n");
|
DBG (5, "calibrate_fine_src_hw: ERROR: cannot clean_params\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6174,7 +6245,7 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
|
|
||||||
in = malloc(reqLen);
|
in = malloc(reqLen);
|
||||||
if (!in) {
|
if (!in) {
|
||||||
DBG (5, "calibrate_fine_buffer: ERROR: cannot malloc in\n");
|
DBG (5, "calibrate_fine_src_hw: ERROR: cannot malloc in\n");
|
||||||
ret = SANE_STATUS_NO_MEM;
|
ret = SANE_STATUS_NO_MEM;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -6182,11 +6253,11 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
/*fine offset*/
|
/*fine offset*/
|
||||||
ret = offset_buffers(s,1);
|
ret = offset_buffers(s,1);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine_buffer: ERROR: cannot load offset buffers\n");
|
DBG (5, "calibrate_fine_src_hw: ERROR: cannot load offset buffers\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG (5, "calibrate_fine_buffer: %d %x\n", s->s.dpi_x/10, s->s.dpi_x/10);
|
DBG (10, "calibrate_fine_src_hw: %d %x\n", s->s.dpi_x/10, s->s.dpi_x/10);
|
||||||
|
|
||||||
memset(cmd,0,cmdLen);
|
memset(cmd,0,cmdLen);
|
||||||
set_SCSI_opcode(cmd, READ_code);
|
set_SCSI_opcode(cmd, READ_code);
|
||||||
|
@ -6196,8 +6267,6 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
|
|
||||||
inLen = reqLen;
|
inLen = reqLen;
|
||||||
|
|
||||||
hexdump(15, "cmd:", cmd, cmdLen);
|
|
||||||
|
|
||||||
ret = do_cmd (
|
ret = do_cmd (
|
||||||
s, 1, 0,
|
s, 1, 0,
|
||||||
cmd, cmdLen,
|
cmd, cmdLen,
|
||||||
|
@ -6232,14 +6301,12 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
s->f_offset[i][j] = 1;
|
s->f_offset[i][j] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hexdump(15, "off:", s->f_offset[i], s->s.valid_Bpl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*fine gain*/
|
/*fine gain*/
|
||||||
ret = gain_buffers(s,1);
|
ret = gain_buffers(s,1);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine_buffer: ERROR: cannot load gain buffers\n");
|
DBG (5, "calibrate_fine_src_hw: ERROR: cannot load gain buffers\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6259,8 +6326,6 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
set_R_xfer_uid (cmd, codes[k]);
|
set_R_xfer_uid (cmd, codes[k]);
|
||||||
inLen = reqLen;
|
inLen = reqLen;
|
||||||
|
|
||||||
hexdump(15, "cmd:", cmd, cmdLen);
|
|
||||||
|
|
||||||
ret = do_cmd (
|
ret = do_cmd (
|
||||||
s, 1, 0,
|
s, 1, 0,
|
||||||
cmd, cmdLen,
|
cmd, cmdLen,
|
||||||
|
@ -6288,8 +6353,6 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
set_R_xfer_uid (cmd, R_FINE_uid_gray);
|
set_R_xfer_uid (cmd, R_FINE_uid_gray);
|
||||||
inLen = reqLen;
|
inLen = reqLen;
|
||||||
|
|
||||||
hexdump(15, "cmd:", cmd, cmdLen);
|
|
||||||
|
|
||||||
ret = do_cmd (
|
ret = do_cmd (
|
||||||
s, 1, 0,
|
s, 1, 0,
|
||||||
cmd, cmdLen,
|
cmd, cmdLen,
|
||||||
|
@ -6310,14 +6373,6 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0;i<2;i++){
|
|
||||||
hexdump(15, "gain:", s->f_gain[i], s->s.valid_Bpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* log current cal type */
|
|
||||||
s->f_res = s->s.dpi_x;
|
|
||||||
s->f_mode = s->s.mode;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
if(in){
|
if(in){
|
||||||
|
@ -6329,16 +6384,16 @@ calibrate_fine_buffer (struct scanner *s)
|
||||||
s->u.br_y = old_br_y;
|
s->u.br_y = old_br_y;
|
||||||
s->u.source = old_source;
|
s->u.source = old_source;
|
||||||
|
|
||||||
DBG (10, "calibrate_fine_buffer: finish %d\n",ret);
|
DBG (10, "calibrate_fine_src_hw: finish %d\n",ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* makes several scans, adjusts fine calibration
|
* makes several scans, generates fine calibration data
|
||||||
*/
|
*/
|
||||||
static SANE_Status
|
static SANE_Status
|
||||||
calibrate_fine (struct scanner *s)
|
calibrate_fine_src_scan (struct scanner *s)
|
||||||
{
|
{
|
||||||
SANE_Status ret = SANE_STATUS_GOOD;
|
SANE_Status ret = SANE_STATUS_GOOD;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
@ -6350,12 +6405,7 @@ calibrate_fine (struct scanner *s)
|
||||||
int old_br_y = s->u.br_y;
|
int old_br_y = s->u.br_y;
|
||||||
int old_source = s->u.source;
|
int old_source = s->u.source;
|
||||||
|
|
||||||
DBG (10, "calibrate_fine: start\n");
|
DBG (10, "calibrate_fine_src_scan: start\n");
|
||||||
|
|
||||||
if(!s->need_fcal){
|
|
||||||
DBG (10, "calibrate_fine: not required\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* always cal with a short scan in duplex */
|
/* always cal with a short scan in duplex */
|
||||||
s->u.tl_y = 0;
|
s->u.tl_y = 0;
|
||||||
|
@ -6365,12 +6415,7 @@ calibrate_fine (struct scanner *s)
|
||||||
/* load our own private copy of scan params */
|
/* load our own private copy of scan params */
|
||||||
ret = update_params(s,1);
|
ret = update_params(s,1);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot update_params\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot update_params\n");
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s->f_res == s->s.dpi_x && s->f_mode == s->s.mode){
|
|
||||||
DBG (10, "calibrate_fine: already done\n");
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6384,7 +6429,7 @@ calibrate_fine (struct scanner *s)
|
||||||
/* make buffers to hold the images */
|
/* make buffers to hold the images */
|
||||||
ret = image_buffers(s,1);
|
ret = image_buffers(s,1);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot load buffers\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot load buffers\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6395,28 +6440,28 @@ calibrate_fine (struct scanner *s)
|
||||||
/* need to tell it we want duplex */
|
/* need to tell it we want duplex */
|
||||||
ret = ssm_buffer(s);
|
ret = ssm_buffer(s);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot ssm buffer\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot ssm buffer\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set window command */
|
/* set window command */
|
||||||
ret = set_window(s);
|
ret = set_window(s);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot set window\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot set window\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*handle fifth pass (fine offset), lamp off*/
|
/* first pass (fine offset), lamp off */
|
||||||
DBG (15, "calibrate_fine: offset\n");
|
DBG (15, "calibrate_fine_src_scan: offset\n");
|
||||||
ret = calibration_scan(s,0xff);
|
ret = calibration_scan(s,0xff);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot make offset cal scan\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot make offset cal scan\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = offset_buffers(s,1);
|
ret = offset_buffers(s,1);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot load offset buffers\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot load offset buffers\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6431,17 +6476,17 @@ calibrate_fine (struct scanner *s)
|
||||||
hexdump(15, "off:", s->f_offset[i], s->s.valid_Bpl);
|
hexdump(15, "off:", s->f_offset[i], s->s.valid_Bpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*handle sixth pass (fine gain), lamp on*/
|
/* second pass (fine gain), lamp on */
|
||||||
DBG (15, "calibrate_fine: gain\n");
|
DBG (15, "calibrate_fine_src_scan: gain\n");
|
||||||
ret = calibration_scan(s,0xfe);
|
ret = calibration_scan(s,0xfe);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot make gain cal scan\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot make gain cal scan\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gain_buffers(s,1);
|
ret = gain_buffers(s,1);
|
||||||
if (ret != SANE_STATUS_GOOD) {
|
if (ret != SANE_STATUS_GOOD) {
|
||||||
DBG (5, "calibrate_fine: ERROR: cannot load gain buffers\n");
|
DBG (5, "calibrate_fine_src_scan: ERROR: cannot load gain buffers\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6459,10 +6504,6 @@ calibrate_fine (struct scanner *s)
|
||||||
hexdump(15, "gain:", s->f_gain[i], s->s.valid_Bpl);
|
hexdump(15, "gain:", s->f_gain[i], s->s.valid_Bpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* log current cal type */
|
|
||||||
s->f_res = s->s.dpi_x;
|
|
||||||
s->f_mode = s->s.mode;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
/* recover user settings */
|
/* recover user settings */
|
||||||
|
@ -6470,13 +6511,109 @@ calibrate_fine (struct scanner *s)
|
||||||
s->u.br_y = old_br_y;
|
s->u.br_y = old_br_y;
|
||||||
s->u.source = old_source;
|
s->u.source = old_source;
|
||||||
|
|
||||||
DBG (10, "calibrate_fine: finish %d\n",ret);
|
DBG (10, "calibrate_fine_src_scan: finish %d\n",ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write calibration data to scanner memory and delete from struct */
|
||||||
|
static SANE_Status
|
||||||
|
calibrate_fine_dest_hw (struct scanner *s)
|
||||||
|
{
|
||||||
|
SANE_Status ret = SANE_STATUS_GOOD;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
unsigned char cmd[SEND_len];
|
||||||
|
size_t cmdLen = SEND_len;
|
||||||
|
|
||||||
|
unsigned char * out = NULL;
|
||||||
|
size_t outLen = 0;
|
||||||
|
|
||||||
|
DBG (10, "calibrate_fine_dest_hw: start\n");
|
||||||
|
|
||||||
|
/* calibration buffers in scanner are single color channel, but 16 bit, plus 4 byte header */
|
||||||
|
outLen = s->s.width*2 + 4;
|
||||||
|
|
||||||
|
out = calloc(outLen,1);
|
||||||
|
if (!out) {
|
||||||
|
DBG (5, "calibrate_fine_dest_hw: ERROR: cannot calloc out\n");
|
||||||
|
ret = SANE_STATUS_NO_MEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sides
|
||||||
|
for(i=0;i<2;i++){
|
||||||
|
|
||||||
|
// colors
|
||||||
|
for(j=0;j<3;j++){
|
||||||
|
|
||||||
|
int codes[] = {
|
||||||
|
S_FCAL_id_f_red, S_FCAL_id_f_green, S_FCAL_id_f_blue,
|
||||||
|
S_FCAL_id_b_red, S_FCAL_id_b_green, S_FCAL_id_b_blue};
|
||||||
|
|
||||||
|
// offset
|
||||||
|
memset(cmd,0,cmdLen);
|
||||||
|
set_SCSI_opcode(cmd, SEND_code);
|
||||||
|
set_S_xfer_datatype (cmd, SR_datatype_fineoffset);
|
||||||
|
set_S_xfer_length (cmd, outLen);
|
||||||
|
|
||||||
|
set_S_FCAL_datatype (out, codes[i*3+j]);
|
||||||
|
|
||||||
|
for(k=0; k<s->s.valid_width; k++){
|
||||||
|
out[4+k*2] = 0;
|
||||||
|
|
||||||
|
// TODO: calculate this instead of hardcode
|
||||||
|
out[4+k*2+1] = 140;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = do_cmd (
|
||||||
|
s, 1, 0,
|
||||||
|
cmd, cmdLen,
|
||||||
|
out, outLen,
|
||||||
|
NULL, 0
|
||||||
|
);
|
||||||
|
if (ret != SANE_STATUS_GOOD)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
// gain
|
||||||
|
set_S_FCAL_datatype (out, codes[i*3+j] | 0x40);
|
||||||
|
|
||||||
|
for(k=0; k<s->s.valid_width; k++){
|
||||||
|
out[4+k*2] = 0;
|
||||||
|
|
||||||
|
// TODO: calculate this instead of hardcode
|
||||||
|
out[4+k*2+1] = 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = do_cmd (
|
||||||
|
s, 1, 0,
|
||||||
|
cmd, cmdLen,
|
||||||
|
out, outLen,
|
||||||
|
NULL, 0
|
||||||
|
);
|
||||||
|
if (ret != SANE_STATUS_GOOD)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
/*blast the fine cal data we generated above, so reading code wont apply it*/
|
||||||
|
offset_buffers(s,0);
|
||||||
|
gain_buffers(s,0);
|
||||||
|
|
||||||
|
if(out){
|
||||||
|
free(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG (10, "calibrate_fine_dest_hw: finish %d\n",ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sends AFE params, and ingests entire duplex image into buffers
|
* does a simple scan, ingests entire duplex image into buffers
|
||||||
*/
|
*/
|
||||||
static SANE_Status
|
static SANE_Status
|
||||||
calibration_scan (struct scanner *s, int scan)
|
calibration_scan (struct scanner *s, int scan)
|
||||||
|
@ -7245,7 +7382,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build a USB packet around the SCSI command */
|
/* build a USB packet around the SCSI command */
|
||||||
cmdBuffer[3] = cmdLength-4;
|
set_USB_CMD_xfer_length(cmdBuffer,cmdLength-4);
|
||||||
cmdBuffer[5] = 1;
|
cmdBuffer[5] = 1;
|
||||||
cmdBuffer[6] = 0x90;
|
cmdBuffer[6] = 0x90;
|
||||||
memcpy(cmdBuffer+cmdOffset,cmdBuff,cmdLen);
|
memcpy(cmdBuffer+cmdOffset,cmdBuff,cmdLen);
|
||||||
|
@ -7305,7 +7442,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build a USB packet around the SCSI command */
|
/* build a USB packet around the SCSI command */
|
||||||
outBuffer[3] = outLength-4;
|
set_USB_OUT_xfer_length(outBuffer,outLength-4);
|
||||||
outBuffer[5] = 2;
|
outBuffer[5] = 2;
|
||||||
outBuffer[6] = 0xb0;
|
outBuffer[6] = 0xb0;
|
||||||
memcpy(outBuffer+outOffset,outBuff,outLen);
|
memcpy(outBuffer+outOffset,outBuff,outLen);
|
||||||
|
|
|
@ -167,11 +167,21 @@ struct scanner
|
||||||
int max_y_fb;
|
int max_y_fb;
|
||||||
|
|
||||||
int can_color; /* actually might be in vpd, but which bit? */
|
int can_color; /* actually might be in vpd, but which bit? */
|
||||||
|
|
||||||
int need_ccal; /* scanner needs software to help with afe calibration */
|
int need_ccal; /* scanner needs software to help with afe calibration */
|
||||||
int need_fcal; /* scanner needs software to help with fine calibration */
|
|
||||||
int need_fcal_buffer; /* software to apply calibration stored in scanner*/
|
|
||||||
int ccal_version; /* 0 in most scanners, 3 in newer ones */
|
int ccal_version; /* 0 in most scanners, 3 in newer ones */
|
||||||
|
|
||||||
|
int fcal_src; /* where fine offset/gain calibration data comes from */
|
||||||
|
int fcal_dest; /* where fine offset/gain calibration data is used */
|
||||||
|
|
||||||
|
#define FCAL_SRC_NONE 0 /* scanner does not require fine calibration */
|
||||||
|
#define FCAL_SRC_SCAN 1 /* make calibration scans, store gain/offset in struct */
|
||||||
|
#define FCAL_SRC_HW 2 /* calibration permanently stored in scanner, downloaded into struct */
|
||||||
|
|
||||||
|
#define FCAL_DEST_NONE 0 /* scanner does not require fine calibration */
|
||||||
|
#define FCAL_DEST_SW 1 /* use gain/offset in struct to adjust output in software */
|
||||||
|
#define FCAL_DEST_HW 2 /* send calibration data into scanner for use in hardware */
|
||||||
|
|
||||||
int has_counter;
|
int has_counter;
|
||||||
int has_rif;
|
int has_rif;
|
||||||
int has_adf;
|
int has_adf;
|
||||||
|
@ -456,6 +466,7 @@ enum {
|
||||||
#define DUPLEX_INTERLACE_FBfb 2
|
#define DUPLEX_INTERLACE_FBfb 2
|
||||||
#define DUPLEX_INTERLACE_2510 3
|
#define DUPLEX_INTERLACE_2510 3
|
||||||
#define DUPLEX_INTERLACE_fFBb 4
|
#define DUPLEX_INTERLACE_fFBb 4
|
||||||
|
#define DUPLEX_INTERLACE_PER_CHANNEL 5
|
||||||
|
|
||||||
#define JPEG_INTERLACE_ALT 0
|
#define JPEG_INTERLACE_ALT 0
|
||||||
#define JPEG_INTERLACE_NONE 1
|
#define JPEG_INTERLACE_NONE 1
|
||||||
|
@ -609,7 +620,9 @@ static SANE_Status gain_buffers (struct scanner *s, int setup);
|
||||||
|
|
||||||
static SANE_Status calibrate_AFE(struct scanner *s);
|
static SANE_Status calibrate_AFE(struct scanner *s);
|
||||||
static SANE_Status calibrate_fine(struct scanner *s);
|
static SANE_Status calibrate_fine(struct scanner *s);
|
||||||
static SANE_Status calibrate_fine_buffer(struct scanner *s);
|
static SANE_Status calibrate_fine_src_scan(struct scanner *s);
|
||||||
|
static SANE_Status calibrate_fine_src_hw(struct scanner *s);
|
||||||
|
static SANE_Status calibrate_fine_dest_hw(struct scanner *s);
|
||||||
|
|
||||||
static SANE_Status write_AFE (struct scanner *s);
|
static SANE_Status write_AFE (struct scanner *s);
|
||||||
static SANE_Status calibration_scan (struct scanner *s, int);
|
static SANE_Status calibration_scan (struct scanner *s, int);
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
:backend "canon_dr" ; name of backend
|
:backend "canon_dr" ; name of backend
|
||||||
:url "http://www.thebility.com/canon/"
|
:url "http://www.thebility.com/canon/"
|
||||||
:version "57" ; version of backend
|
:version "59" ; version of backend
|
||||||
:manpage "sane-canon_dr" ; name of manpage (if it exists)
|
:manpage "sane-canon_dr" ; name of manpage (if it exists)
|
||||||
:comment "Backend updated for SANE release 1.0.28, see sane-canon_dr manpage"
|
:comment "Backend updated for SANE release 1.0.32, see sane-canon_dr manpage"
|
||||||
:devicetype :scanner ; start of a list of devices....
|
:devicetype :scanner ; start of a list of devices....
|
||||||
; other types: :stillcam, :vidcam,
|
; other types: :stillcam, :vidcam,
|
||||||
; :meta, :api
|
; :meta, :api
|
||||||
|
@ -283,8 +283,8 @@
|
||||||
:model "DR-C225"
|
:model "DR-C225"
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
:usbid "0x1083" "0x1658"
|
:usbid "0x1083" "0x1658"
|
||||||
:status :untested
|
:status :basic
|
||||||
:comment ""
|
:comment "Calibration is poor, grayscale mode may crash. DR-C225ii is the same device."
|
||||||
|
|
||||||
:model "DR-F120"
|
:model "DR-F120"
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
|
|
Ładowanie…
Reference in New Issue