diff options
Diffstat (limited to 'backend/canon_dr.c')
-rw-r--r-- | backend/canon_dr.c | 432 |
1 files changed, 323 insertions, 109 deletions
diff --git a/backend/canon_dr.c b/backend/canon_dr.c index 17ee7b6..de7ed7e 100644 --- a/backend/canon_dr.c +++ b/backend/canon_dr.c @@ -3,7 +3,7 @@ This file is part of the SANE package, and implements a SANE backend 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 EvriChart, Inc. www.evrichart.com provided funding and loaned equipment @@ -25,9 +25,7 @@ General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + along with this program. If not, see <https://www.gnu.org/licenses/>. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. @@ -126,9 +124,9 @@ - send_panel() can disable too - add cancel() to send d8 command - call cancel() only after final read from scanner - - stop button reqests cancel + - stop button requests cancel v12 2009-01-21, MAN - - dont export private symbols + - don't export private symbols v13 2009-03-06, MAN - new vendor ID for recent machines - add usb ids for several new machines @@ -149,7 +147,7 @@ v18 2009-03-21, MAN - rewrite config file parsing to reset options after each scanner - add config options for vendor, model, version - - dont call inquiry if those 3 options are set + - don't call inquiry if those 3 options are set - remove default config file from code - add initial gray deinterlacing code for DR-2510C - rename do_usb_reset to do_usb_clear @@ -175,8 +173,8 @@ v24 2009-04-02, MAN - fix DR-2510C duplex deinterlacing code - rewrite sane_read helpers to read until EOF - - update sane_start for scanners that dont use object_position - - dont call sanei_usb_clear_halt() if device is not open + - update sane_start for scanners that don't use object_position + - don't call sanei_usb_clear_halt() if device is not open - increase default buffer size to 4 megs - set buffermode on by default - hide modes and resolutions that DR-2510C lies about @@ -206,8 +204,8 @@ - merge x and y resolution options into single option - move scan params into two new structs, s->u and s->s - sane_get_parameters() just returns values from s->u - - dont call wait_scanner() in object_position() - - dont call ssm_*() from option handler + - don't call wait_scanner() in object_position() + - don't call ssm_*() from option handler - refactor sane_start() - read_from_buffer() can workaround missing res, modes and cropping - set most DR-2xxx machines to use the read_from_buffer workarounds @@ -318,7 +316,7 @@ v51 2015-08-25, MAN (SANE 1.0.25) - DR-C125 does not invert_tly, does need sw_lut v52 2015-11-03, MAN - - set can_color=1 by default (recent models dont have 'C' in name) + - set can_color=1 by default (recent models don't have 'C' in name) - enable jpeg for DR-6080 - add must_downsample and must_fully_buffer - improve dropout option handling @@ -340,6 +338,14 @@ - complete support for X-10, including hardware cropping v58 2019-11-10, MAN - 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 + v60 2020-11-28, MAN + - add new gray and color interlacing options for DR-C120 + - initial support for DR-C120 and C130 + - enable fine calibration for P-208 (per @sashacmc in !546) SANE FLOW DIAGRAM @@ -390,7 +396,7 @@ #include "canon_dr.h" #define DEBUG 1 -#define BUILD 58 +#define BUILD 60 /* values for SANE_DEBUG_CANON_DR env var: - errors 5 @@ -1348,7 +1354,8 @@ init_model (struct scanner *s) s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; 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_side = SIDE_BACK; @@ -1372,7 +1379,8 @@ init_model (struct scanner *s) s->duplex_interlace = DUPLEX_INTERLACE_2510; /*s->duplex_offset = 400; now set in config file*/ 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->invert_tly = 1;*/ @@ -1402,7 +1410,8 @@ init_model (struct scanner *s) s->duplex_interlace = DUPLEX_INTERLACE_2510; /*s->duplex_offset = 400; now set in config file*/ 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->invert_tly = 1; @@ -1427,7 +1436,8 @@ init_model (struct scanner *s) s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB; 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->duplex_offset = 840; now set in config file*/ s->sw_lut = 1; @@ -1487,6 +1497,8 @@ init_model (struct scanner *s) s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; s->need_ccal = 1; + s->fcal_src = FCAL_SRC_SCAN; + s->fcal_dest = FCAL_DEST_SW; s->invert_tly = 1; s->unknown_byte2 = 0x88; s->rgb_format = 1; @@ -1592,6 +1604,39 @@ init_model (struct scanner *s) s->can_monochrome=0; } + else if (strstr (s->model_name,"DR-C120") + || strstr (s->model_name,"DR-C130") + ){ + + /*confirmed settings*/ + s->need_ccal = 1; + s->ccal_version = 3; + + s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_C120; + s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_C120; + s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_C120; + s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_C120; + s->duplex_interlace = DUPLEX_INTERLACE_2510; + s->duplex_offset_side = SIDE_BACK; + s->unknown_byte2 = 0x88; + s->fcal_src = FCAL_SRC_SCAN; + s->fcal_dest = FCAL_DEST_SW; + s->sw_lut = 1; + s->rgb_format = 1; + /*s->duplex_offset = 400; now set in config file*/ + + /*only in Y direction, so we trash them in X*/ + s->std_res_x[DPI_100]=0; + s->std_res_x[DPI_150]=0; + s->std_res_x[DPI_200]=0; + s->std_res_x[DPI_240]=0; + s->std_res_x[DPI_400]=0; + + /*suspected settings*/ + s->always_op = 0; + s->fixed_width = 1; + s->valid_x = 8.5 * 1200; + } else if (strstr (s->model_name,"DR-C125")){ /*confirmed settings*/ @@ -1604,7 +1649,8 @@ init_model (struct scanner *s) s->unknown_byte2 = 0x88; s->need_ccal = 1; 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->rgb_format = 1; /*s->duplex_offset = 400; now set in config file*/ @@ -1625,14 +1671,15 @@ init_model (struct scanner *s) else if (strstr (s->model_name,"DR-C225")){ 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->duplex_interlace = DUPLEX_INTERLACE_FBfb; + s->duplex_interlace = DUPLEX_INTERLACE_PER_CHANNEL; s->unknown_byte2 = 0x88; s->need_ccal = 1; 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->rgb_format = 1; /*s->duplex_offset = 400; now set in config file*/ @@ -3019,7 +3066,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); if ( s->started ) { - DBG (5, "sane_control_option: cant set, device busy\n"); + DBG (5, "sane_control_option: can't set, device busy\n"); return SANE_STATUS_DEVICE_BUSY; } @@ -3034,7 +3081,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, return status; } - /* may have been changed by constrain, so dont copy until now */ + /* may have been changed by constrain, so don't copy until now */ val_c = *(SANE_Word *)val; /* @@ -4259,7 +4306,7 @@ update_i_params(struct scanner *s) * * this will be called between sides of a duplex scan, * and at the start of each page of an adf batch. - * hence, we spend alot of time playing with s->started, etc. + * hence, we spend a lot of time playing with s->started, etc. */ SANE_Status sane_start (SANE_Handle handle) @@ -4314,22 +4361,19 @@ sane_start (SANE_Handle handle) } /* 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"); goto errors; } /* 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"); 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 */ s->panel_counter = 0; s->prev_page = 0; @@ -4458,10 +4502,10 @@ sane_start (SANE_Handle handle) } /* set clean defaults with new sheet of paper */ - /* dont reset the transfer vars on backside of duplex page */ + /* don't reset the transfer vars on backside of duplex page */ /* otherwise buffered back page will be lost */ /* ingest paper with adf (no-op for fb) */ - /* dont call object pos or scan on back side of duplex scan */ + /* don't call object pos or scan on back side of duplex scan */ if(s->side == SIDE_FRONT || s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_BACK){ /* clean scan params for new scan */ @@ -5367,6 +5411,23 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = 0; } break; + + case GRAY_INTERLACE_C120: + DBG (17, "copy_simplex: gray, C120\n"); + + /* first read head (third byte of every three) */ + for(j=bwidth-1;j>=0;j-=3){ + line[line_next++] = buf[i+j]; + } + /* second read head (first byte of every three) */ + for(j=bwidth-3;j>=0;j-=3){ + line[line_next++] = buf[i+j]; + } + /* third read head (second byte of every three) */ + for(j=bwidth-2;j>=0;j-=3){ + line[line_next++] = buf[i+j]; + } + break; } } @@ -5451,6 +5512,29 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = 0; } break; + + case COLOR_INTERLACE_C120: + DBG (17, "copy_simplex: color, C120\n"); + + /* first read head (third byte of every three) */ + for(j=t-1;j>=0;j-=3){ + line[line_next++] = buf[i+j]; + line[line_next++] = buf[i+t+j]; + line[line_next++] = buf[i+2*t+j]; + } + /* second read head (first byte of every three) */ + for(j=t-3;j>=0;j-=3){ + line[line_next++] = buf[i+j]; + line[line_next++] = buf[i+t+j]; + line[line_next++] = buf[i+2*t+j]; + } + /* third read head (second byte of every three) */ + for(j=t-2;j>=0;j-=3){ + line[line_next++] = buf[i+j]; + line[line_next++] = buf[i+t+j]; + line[line_next++] = buf[i+2*t+j]; + } + break; } } @@ -5517,6 +5601,7 @@ copy_duplex(struct scanner *s, unsigned char * buf, int len) { SANE_Status ret=SANE_STATUS_GOOD; int i,j; + int pwidth = s->s.width; int bwidth = s->s.Bpl; int dbwidth = 2*bwidth; unsigned char * front; @@ -5568,6 +5653,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 */ else if(s->duplex_interlace == DUPLEX_INTERLACE_FfBb || s->duplex_interlace == DUPLEX_INTERLACE_fFBb){ for(i=0; i<len; i+=dbwidth){ @@ -5944,7 +6044,7 @@ calibrate_AFE (struct scanner *s) goto cleanup; } - /*blast the existing fine cal data so reading code wont apply it*/ + /*blast the existing fine cal data so reading code won't apply it*/ ret = offset_buffers(s,0); ret = gain_buffers(s,0); @@ -6119,10 +6219,68 @@ calibrate_AFE (struct scanner *s) return ret; } +/* + * 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 +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; +} + -/* alternative version- extracts data from scanner memory */ +/* extracts fine calibration data from scanner memory */ static SANE_Status -calibrate_fine_buffer (struct scanner *s) +calibrate_fine_src_hw (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int i, j, k; @@ -6138,12 +6296,7 @@ calibrate_fine_buffer (struct scanner *s) int old_br_y = s->u.br_y; int old_source = s->u.source; - DBG (10, "calibrate_fine_buffer: start\n"); - - if(!s->need_fcal_buffer){ - DBG (10, "calibrate_fine_buffer: not required\n"); - return ret; - } + DBG (10, "calibrate_fine_src_hw: start\n"); /* pretend we are doing a 1 line scan in duplex */ s->u.tl_y = 0; @@ -6153,19 +6306,14 @@ calibrate_fine_buffer (struct scanner *s) /* load our own private copy of scan params */ ret = update_params(s,1); if (ret != SANE_STATUS_GOOD) { - DBG (5, "calibrate_fine_buffer: 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"); + DBG (5, "calibrate_fine_src_hw: ERROR: cannot update_params\n"); goto cleanup; } /* clean scan params for new scan */ ret = clean_params(s); 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; } @@ -6174,7 +6322,7 @@ calibrate_fine_buffer (struct scanner *s) in = malloc(reqLen); 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; goto cleanup; } @@ -6182,11 +6330,11 @@ calibrate_fine_buffer (struct scanner *s) /*fine offset*/ ret = offset_buffers(s,1); 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; } - 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); set_SCSI_opcode(cmd, READ_code); @@ -6196,8 +6344,6 @@ calibrate_fine_buffer (struct scanner *s) inLen = reqLen; - hexdump(15, "cmd:", cmd, cmdLen); - ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -6232,14 +6378,12 @@ calibrate_fine_buffer (struct scanner *s) s->f_offset[i][j] = 1; } } - - hexdump(15, "off:", s->f_offset[i], s->s.valid_Bpl); } /*fine gain*/ ret = gain_buffers(s,1); 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; } @@ -6259,8 +6403,6 @@ calibrate_fine_buffer (struct scanner *s) set_R_xfer_uid (cmd, codes[k]); inLen = reqLen; - hexdump(15, "cmd:", cmd, cmdLen); - ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -6288,8 +6430,6 @@ calibrate_fine_buffer (struct scanner *s) set_R_xfer_uid (cmd, R_FINE_uid_gray); inLen = reqLen; - hexdump(15, "cmd:", cmd, cmdLen); - ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -6310,14 +6450,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: if(in){ @@ -6329,16 +6461,16 @@ calibrate_fine_buffer (struct scanner *s) s->u.br_y = old_br_y; 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; } /* - * makes several scans, adjusts fine calibration + * makes several scans, generates fine calibration data */ static SANE_Status -calibrate_fine (struct scanner *s) +calibrate_fine_src_scan (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int i, j, k; @@ -6350,12 +6482,7 @@ calibrate_fine (struct scanner *s) int old_br_y = s->u.br_y; int old_source = s->u.source; - DBG (10, "calibrate_fine: start\n"); - - if(!s->need_fcal){ - DBG (10, "calibrate_fine: not required\n"); - return ret; - } + DBG (10, "calibrate_fine_src_scan: start\n"); /* always cal with a short scan in duplex */ s->u.tl_y = 0; @@ -6365,12 +6492,7 @@ calibrate_fine (struct scanner *s) /* load our own private copy of scan params */ ret = update_params(s,1); if (ret != SANE_STATUS_GOOD) { - DBG (5, "calibrate_fine: 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"); + DBG (5, "calibrate_fine_src_scan: ERROR: cannot update_params\n"); goto cleanup; } @@ -6384,39 +6506,39 @@ calibrate_fine (struct scanner *s) /* make buffers to hold the images */ ret = image_buffers(s,1); 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; } - /*blast the existing fine cal data so reading code wont apply it*/ + /*blast the existing fine cal data so reading code won't apply it*/ ret = offset_buffers(s,0); ret = gain_buffers(s,0); /* need to tell it we want duplex */ ret = ssm_buffer(s); 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; } /* set window command */ ret = set_window(s); 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; } - /*handle fifth pass (fine offset), lamp off*/ - DBG (15, "calibrate_fine: offset\n"); + /* first pass (fine offset), lamp off */ + DBG (15, "calibrate_fine_src_scan: offset\n"); ret = calibration_scan(s,0xff); 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; } ret = offset_buffers(s,1); 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; } @@ -6431,17 +6553,17 @@ calibrate_fine (struct scanner *s) hexdump(15, "off:", s->f_offset[i], s->s.valid_Bpl); } - /*handle sixth pass (fine gain), lamp on*/ - DBG (15, "calibrate_fine: gain\n"); + /* second pass (fine gain), lamp on */ + DBG (15, "calibrate_fine_src_scan: gain\n"); ret = calibration_scan(s,0xfe); 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; } ret = gain_buffers(s,1); 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; } @@ -6459,10 +6581,6 @@ calibrate_fine (struct scanner *s) 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: /* recover user settings */ @@ -6470,13 +6588,109 @@ calibrate_fine (struct scanner *s) s->u.br_y = old_br_y; 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; } /* - * sends AFE params, and ingests entire duplex image into buffers + * does a simple scan, ingests entire duplex image into buffers */ static SANE_Status calibration_scan (struct scanner *s, int scan) @@ -6701,7 +6915,7 @@ gain_buffers (struct scanner *s, int setup) * handle h is a valid handle) but usually affects long-running * operations only (such as image acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). - * It is important to note that completion of this operaton does not + * It is important to note that completion of this operation does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a @@ -6727,7 +6941,7 @@ sane_cancel (SANE_Handle handle) /* checks started and cancelled flags in scanner struct, * sends cancel command to scanner if required. don't call - * this function asyncronously, wait for pending operation */ + * this function asynchronously, wait for pending operation */ static SANE_Status check_for_cancel(struct scanner *s) { @@ -7245,7 +7459,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, } /* build a USB packet around the SCSI command */ - cmdBuffer[3] = cmdLength-4; + set_USB_CMD_xfer_length(cmdBuffer,cmdLength-4); cmdBuffer[5] = 1; cmdBuffer[6] = 0x90; memcpy(cmdBuffer+cmdOffset,cmdBuff,cmdLen); @@ -7305,7 +7519,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, } /* build a USB packet around the SCSI command */ - outBuffer[3] = outLength-4; + set_USB_OUT_xfer_length(outBuffer,outLength-4); outBuffer[5] = 2; outBuffer[6] = 0xb0; memcpy(outBuffer+outOffset,outBuff,outLen); @@ -7520,7 +7734,7 @@ do_usb_clear(struct scanner *s, int clear, int runRS) DBG (15, "do_usb_clear: clear halt\n"); ret = sanei_usb_clear_halt(s->fd); if(ret != SANE_STATUS_GOOD){ - DBG(5,"do_usb_clear: cant clear halt, returning %d\n", ret); + DBG(5,"do_usb_clear: can't clear halt, returning %d\n", ret); return ret; } } @@ -7680,7 +7894,7 @@ get_page_width(struct scanner *s) return s->max_x_fb; } - /* cant overscan larger than scanner max */ + /* can't overscan larger than scanner max */ if(width > s->valid_x){ return s->valid_x; } @@ -7704,7 +7918,7 @@ get_page_height(struct scanner *s) return s->max_y_fb; } - /* cant overscan larger than scanner max */ + /* can't overscan larger than scanner max */ if(height > s->max_y){ return s->max_y; } |