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
m. allan noah 2020-08-11 19:28:11 -04:00
rodzic 588f01526e
commit e46adab4f2
4 zmienionych plików z 260 dodań i 94 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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);

Wyświetl plik

@ -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);

Wyświetl plik

@ -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"