diff options
Diffstat (limited to 'backend/canon_dr.c')
-rw-r--r-- | backend/canon_dr.c | 743 |
1 files changed, 499 insertions, 244 deletions
diff --git a/backend/canon_dr.c b/backend/canon_dr.c index 3c058ab..64aec31 100644 --- a/backend/canon_dr.c +++ b/backend/canon_dr.c @@ -10,6 +10,7 @@ Canon, USA. www.usa.canon.com loaned equipment HPrint hprint.com.br provided funding and testing for DR-2510 support Stone-IT www.stone-it.com provided funding for DR-2010 and DR-2050 support + Smartmatic www.smartmatic.com provided testing and changes for DR-X10C support -------------------------------------------------------------------------- @@ -165,7 +166,7 @@ - correct rgb padding macro - skip send_panel and ssm_df commands for DR-20xx scanners v22 2009-03-25, MAN - - add deinterlacing code for DR-2510C in duplex and color + - add deinterlacing code for DR-2510C in duplex and color v23 2009-03-27, MAN - rewrite all image data processing code - handle more image interlacing formats @@ -335,6 +336,8 @@ - rename all DUPLEX_INTERLACE_* to indicate start and end of line v56 2016-08-23, MAN - initial support for P-150 + v57 2019-02-24, manuarg + - complete support for X-10, including hardware cropping SANE FLOW DIAGRAM @@ -352,7 +355,7 @@ . . - sane_start() : start image acquisition . . - sane_get_parameters() : returns actual scan parameters . . - sane_read() : read image data (from pipe) - . . (sane_read called multiple times; after sane_read returns EOF, + . . (sane_read called multiple times; after sane_read returns EOF, . . loop may continue with sane_start which may return a 2nd page . . when doing duplex scans, or load the next page from the ADF) . . @@ -385,14 +388,14 @@ #include "canon_dr.h" #define DEBUG 1 -#define BUILD 56 +#define BUILD 57 /* values for SANE_DEBUG_CANON_DR env var: - errors 5 - function trace 10 - function detail 15 - get/setopt cmds 20 - - scsi/usb trace 25 + - scsi/usb trace 25 - scsi/usb writes 30 - scsi/usb reads 31 - useless noise 35 @@ -455,7 +458,7 @@ static struct scanner *scanner_devList = NULL; /* * Called by SANE initially. - * + * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this @@ -487,7 +490,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) /* * Called by SANE to find out about supported devices. - * + * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a @@ -500,7 +503,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. - * + * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and @@ -544,42 +547,42 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) CANON_DR_CONFIG_FILE); while (sanei_config_read (line, PATH_MAX, fp)) { - + lp = line; - + /* ignore comments */ if (*lp == '#') continue; - + /* skip empty lines */ if (*lp == 0) continue; - + if (!strncmp ("option", lp, 6) && isspace (lp[6])) { - + lp += 6; lp = sanei_config_skip_whitespace (lp); - + /* BUFFERSIZE: > 4K */ if (!strncmp (lp, "buffer-size", 11) && isspace (lp[11])) { - + int buf; lp += 11; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); - + if (buf < 4096) { DBG (5, "sane_get_devices: config option \"buffer-size\" " "(%d) is < 4096, ignoring!\n", buf); continue; } - + if (buf > global_buffer_size_default) { DBG (5, "sane_get_devices: config option \"buffer-size\" " "(%d) is > %d, scanning problems may result\n", buf, global_buffer_size_default); } - + DBG (15, "sane_get_devices: setting \"buffer-size\" to %d\n", buf); @@ -588,24 +591,24 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) /* PADDED READ: we clamp to 0 or 1 */ else if (!strncmp (lp, "padded-read", 11) && isspace (lp[11])) { - + int buf; lp += 11; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); - + if (buf < 0) { DBG (5, "sane_get_devices: config option \"padded-read\" " "(%d) is < 0, ignoring!\n", buf); continue; } - + if (buf > 1) { DBG (5, "sane_get_devices: config option \"padded-read\" " "(%d) is > 1, ignoring!\n", buf); continue; } - + DBG (15, "sane_get_devices: setting \"padded-read\" to %d\n", buf); @@ -614,24 +617,24 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) /* EXTRA STATUS: we clamp to 0 or 1 */ else if (!strncmp (lp, "extra-status", 12) && isspace (lp[12])) { - + int buf; lp += 12; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); - + if (buf < 0) { DBG (5, "sane_get_devices: config option \"extra-status\" " "(%d) is < 0, ignoring!\n", buf); continue; } - + if (buf > 1) { DBG (5, "sane_get_devices: config option \"extra-status\" " "(%d) is > 1, ignoring!\n", buf); continue; } - + DBG (15, "sane_get_devices: setting \"extra-status\" to %d\n", buf); @@ -640,18 +643,18 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) /* DUPLEXOFFSET: < 2400 */ else if (!strncmp (lp, "duplex-offset", 13) && isspace (lp[13])) { - + int buf; lp += 13; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); - + if (buf > 2400) { DBG (5, "sane_get_devices: config option \"duplex-offset\" " "(%d) is > 2400, ignoring!\n", buf); continue; } - + if (buf < 0) { DBG (5, "sane_get_devices: config option \"duplex-offset\" " "(%d) is < 0, ignoring!\n", buf); @@ -671,7 +674,7 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) lp = sanei_config_skip_whitespace (lp); strncpy(global_vendor_name, lp, 8); global_vendor_name[8] = 0; - + DBG (15, "sane_get_devices: setting \"vendor-name\" to %s\n", global_vendor_name); } @@ -683,7 +686,7 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) lp = sanei_config_skip_whitespace (lp); strncpy(global_model_name, lp, 16); global_model_name[16] = 0; - + DBG (15, "sane_get_devices: setting \"model-name\" to %s\n", global_model_name); } @@ -695,7 +698,7 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) lp = sanei_config_skip_whitespace (lp); strncpy(global_version_name, lp, 4); global_version_name[4] = 0; - + DBG (15, "sane_get_devices: setting \"version-name\" to %s\n", global_version_name); } @@ -801,8 +804,8 @@ attach_one_usb (const char *device_name) return attach_one(device_name,CONNECTION_USB); } -/* build the scanner struct and link to global list - * unless struct is already loaded, then pretend +/* build the scanner struct and link to global list + * unless struct is already loaded, then pretend */ static SANE_Status attach_one (const char *device_name, int connType) @@ -974,8 +977,8 @@ connect_fd (struct scanner *s) if(ret == SANE_STATUS_GOOD){ - /* first generation usb scanners can get flaky if not closed - * properly after last use. very first commands sent to device + /* first generation usb scanners can get flaky if not closed + * properly after last use. very first commands sent to device * must be prepared to correct this- see wait_scanner() */ ret = wait_scanner(s); if (ret != SANE_STATUS_GOOD) { @@ -1016,9 +1019,9 @@ init_inquire (struct scanner *s) set_IN_return_size (cmd, inLen); set_IN_evpd (cmd, 0); set_IN_page_code (cmd, 0); - + ret = do_cmd ( - s, 1, 0, + s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen @@ -1323,7 +1326,7 @@ init_model (struct scanner *s) s->std_res_y[DPI_400]=1; s->std_res_x[DPI_600]=1; s->std_res_y[DPI_600]=1; - + /*weirdness*/ s->has_ssm = 0; s->has_ssm2 = 1; @@ -1522,7 +1525,7 @@ init_model (struct scanner *s) s->std_res_y[DPI_400]=1; s->std_res_x[DPI_600]=1; s->std_res_y[DPI_600]=1; - + s->has_comp_JPEG = 1; s->rgb_format = 1; s->has_df_ultra = 1; @@ -1562,7 +1565,7 @@ init_model (struct scanner *s) s->std_res_y[DPI_400]=1; s->std_res_x[DPI_600]=1; s->std_res_y[DPI_600]=1; - + s->has_comp_JPEG = 1; s->rgb_format = 1; s->has_df_ultra = 1; @@ -1690,6 +1693,31 @@ 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->has_hwcrop = 1; + } + DBG (10, "init_model: finish\n"); return SANE_STATUS_GOOD; @@ -1801,9 +1829,9 @@ init_options (struct scanner *s) s->opt[i].cap = SANE_CAP_INACTIVE; } - /* go ahead and setup the first opt, because - * frontend may call control_option on it - * before calling get_option_descriptor + /* go ahead and setup the first opt, because + * frontend may call control_option on it + * before calling get_option_descriptor */ s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; @@ -1831,7 +1859,7 @@ sane_open (SANE_String_Const name, SANE_Handle * handle) struct scanner *dev = NULL; struct scanner *s = NULL; SANE_Status ret; - + DBG (10, "sane_open: start\n"); if(scanner_devList){ @@ -1852,7 +1880,7 @@ sane_open (SANE_String_Const name, SANE_Handle * handle) } else{ DBG (15, "sane_open: device %s requested\n", name); - + for (dev = scanner_devList; dev; dev = dev->next) { if (strcmp (dev->sane.name, name) == 0 || strcmp (dev->device_name, name) == 0) { /*always allow sanei devname*/ @@ -1928,7 +1956,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) } if(s->has_adf){ s->source_list[i++]=STRING_ADFFRONT; - + if(s->has_back){ s->source_list[i++]=STRING_ADFBACK; } @@ -1938,7 +1966,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) } if(s->has_card){ s->source_list[i++]=STRING_CARDFRONT; - + if(s->has_back){ s->source_list[i++]=STRING_CARDBACK; } @@ -1974,7 +2002,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->mode_list[i++]=STRING_COLOR; } s->mode_list[i]=NULL; - + opt->name = SANE_NAME_SCAN_MODE; opt->title = SANE_TITLE_SCAN_MODE; opt->desc = SANE_DESC_SCAN_MODE; @@ -2041,14 +2069,14 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->res_list[++i] = 1200; } s->res_list[0] = i; - + opt->name = SANE_NAME_SCAN_RESOLUTION; opt->title = SANE_TITLE_SCAN_RESOLUTION; opt->desc = SANE_DESC_SCAN_RESOLUTION; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_DPI; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; - + if(s->step_y_res){ s->res_range.min = s->min_y_res; s->res_range.max = s->max_y_res; @@ -2078,7 +2106,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->tl_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->tl_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); s->tl_x_range.quant = MM_PER_UNIT_FIX; - + opt->name = SANE_NAME_SCAN_TL_X; opt->title = SANE_TITLE_SCAN_TL_X; opt->desc = SANE_DESC_SCAN_TL_X; @@ -2096,7 +2124,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->tl_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->tl_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->tl_y_range.quant = MM_PER_UNIT_FIX; - + opt->name = SANE_NAME_SCAN_TL_Y; opt->title = SANE_TITLE_SCAN_TL_Y; opt->desc = SANE_DESC_SCAN_TL_Y; @@ -2114,7 +2142,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->br_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->br_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); s->br_x_range.quant = MM_PER_UNIT_FIX; - + opt->name = SANE_NAME_SCAN_BR_X; opt->title = SANE_TITLE_SCAN_BR_X; opt->desc = SANE_DESC_SCAN_BR_X; @@ -2132,7 +2160,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->br_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->br_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->br_y_range.quant = MM_PER_UNIT_FIX; - + opt->name = SANE_NAME_SCAN_BR_Y; opt->title = SANE_TITLE_SCAN_BR_Y; opt->desc = SANE_DESC_SCAN_BR_Y; @@ -2370,7 +2398,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) /*double feed by thickness */ if(option==OPT_DF_THICKNESS){ - + opt->name = "df-thickness"; opt->title = "DF by thickness"; opt->desc = "Detect double feeds using thickness sensor"; @@ -2482,7 +2510,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->do_color_list[5] = STRING_EN_GREEN; s->do_color_list[6] = STRING_EN_BLUE; s->do_color_list[7] = NULL; - + opt->name = "dropout-front"; opt->title = "Dropout color front"; opt->desc = "One-pass scanners use only one color during gray or binary scanning, useful for colored paper or ink"; @@ -2510,7 +2538,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->do_color_list[5] = STRING_EN_GREEN; s->do_color_list[6] = STRING_EN_BLUE; s->do_color_list[7] = NULL; - + opt->name = "dropout-back"; opt->title = "Dropout color back"; opt->desc = "One-pass scanners use only one color during gray or binary scanning, useful for colored paper or ink"; @@ -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; @@ -2671,7 +2711,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) /** * Gets or sets an option value. - * + * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which @@ -2682,7 +2722,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). - * + * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon @@ -2918,6 +2958,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option, *val_p = s->side; return SANE_STATUS_GOOD; + case OPT_HW_CROP: + *val_p = s->hwcrop; + return SANE_STATUS_GOOD; + /* Sensor Group */ case OPT_START: ret = read_panel(s,OPT_START); @@ -2999,7 +3043,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, * below. */ switch (option) { - + /* Mode Group */ case OPT_SOURCE: if (!strcmp (val, STRING_ADFFRONT)) { @@ -3024,7 +3068,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, tmp = SOURCE_FLATBED; } - if (s->u.source == tmp) + if (s->u.source == tmp) return SANE_STATUS_GOOD; s->u.source = tmp; @@ -3056,7 +3100,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, case OPT_RES: - if (s->u.dpi_x == val_c && s->u.dpi_y == val_c) + if (s->u.dpi_x == val_c && s->u.dpi_y == val_c) return SANE_STATUS_GOOD; s->u.dpi_x = val_c; @@ -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 */ @@ -3251,25 +3299,25 @@ ssm_buffer (struct scanner *s) DBG (10, "ssm_buffer: start\n"); if(s->has_ssm){ - + unsigned char cmd[SET_SCAN_MODE_len]; size_t cmdLen = SET_SCAN_MODE_len; - + unsigned char out[SSM_PAY_len]; size_t outLen = SSM_PAY_len; - + memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE_code); set_SSM_pf(cmd, 1); set_SSM_pay_len(cmd, outLen); - + memset(out,0,outLen); if(s->has_ssm_pay_head_len){ set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); } set_SSM_page_code(out, SM_pc_buffer); set_SSM_page_len(out, SSM_PAGE_len); - + if(s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX){ set_SSM_BUFF_duplex(out, 1); } @@ -3288,7 +3336,7 @@ ssm_buffer (struct scanner *s) if(0){ set_SSM_BUFF_unk(out,1); } - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -3301,20 +3349,20 @@ ssm_buffer (struct scanner *s) 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_buffer); set_SSM2_pay_len(cmd, outLen); - + memset(out,0,outLen); set_SSM2_BUFF_unk(out, !s->buffermode); set_SSM2_BUFF_unk2(out, 0x40); set_SSM2_BUFF_sync(out, !s->buffermode); - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -3338,52 +3386,52 @@ ssm_df (struct scanner *s) SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "ssm_df: start\n"); - + if(!s->has_df){ DBG (10, "ssm_df: unsupported, finishing\n"); return ret; } - + if(s->has_ssm){ unsigned char cmd[SET_SCAN_MODE_len]; size_t cmdLen = SET_SCAN_MODE_len; - + unsigned char out[SSM_PAY_len]; size_t outLen = SSM_PAY_len; - + memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE_code); set_SSM_pf(cmd, 1); set_SSM_pay_len(cmd, outLen); - + memset(out,0,outLen); if(s->has_ssm_pay_head_len){ set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); } set_SSM_page_code(out, SM_pc_df); set_SSM_page_len(out, SSM_PAGE_len); - + /* deskew by roller */ if(s->rollerdeskew){ set_SSM_DF_deskew_roll(out, 1); } - + /* staple detection */ if(s->stapledetect){ set_SSM_DF_staple(out, 1); } - + /* thickness */ if(s->df_thickness){ set_SSM_DF_thick(out, 1); } - + /* length */ if(s->df_length){ set_SSM_DF_len(out, 1); } - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -3397,7 +3445,7 @@ ssm_df (struct scanner *s) 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; @@ -3407,11 +3455,11 @@ ssm_df (struct scanner *s) set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); set_SSM2_page_code(cmd, SM2_pc_ultra); set_SSM2_pay_len(cmd, outLen); - + memset(out,0,outLen); set_SSM2_ULTRA_top(out, 0); set_SSM2_ULTRA_bot(out, 0); - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -3424,19 +3472,24 @@ ssm_df (struct scanner *s) set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); set_SSM2_page_code(cmd, SM2_pc_df); set_SSM2_pay_len(cmd, outLen); - + memset(out,0,outLen); - + /* thickness */ if(s->df_thickness){ set_SSM2_DF_thick(out, 1); } - + /* length */ if(s->df_length){ 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, @@ -3456,6 +3509,53 @@ ssm_df (struct scanner *s) } 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) { SANE_Status ret = SANE_STATUS_GOOD; @@ -3466,7 +3566,7 @@ ssm_do (struct scanner *s) DBG (10, "ssm_do: unsupported, finishing\n"); return ret; } - + if(s->s.mode == MODE_COLOR){ DBG (10, "ssm_do: unneeded, finishing\n"); return ret; @@ -3476,24 +3576,24 @@ ssm_do (struct scanner *s) unsigned char cmd[SET_SCAN_MODE_len]; size_t cmdLen = SET_SCAN_MODE_len; - + unsigned char out[SSM_PAY_len]; size_t outLen = SSM_PAY_len; - + memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE_code); set_SSM_pf(cmd, 1); set_SSM_pay_len(cmd, outLen); - + memset(out,0,outLen); if(s->has_ssm_pay_head_len){ set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); } set_SSM_page_code(out, SM_pc_dropout); set_SSM_page_len(out, SSM_PAGE_len); - + set_SSM_DO_unk1(out, 0x03); - + switch(s->dropout_color[SIDE_FRONT]){ case COLOR_RED: set_SSM_DO_unk2(out, 0x05); @@ -3520,7 +3620,7 @@ ssm_do (struct scanner *s) set_SSM_DO_f_en(out,SSM_DO_blue); break; } - + switch(s->dropout_color[SIDE_BACK]){ case COLOR_RED: set_SSM_DO_unk2(out, 0x05); @@ -3547,7 +3647,7 @@ ssm_do (struct scanner *s) set_SSM_DO_b_en(out,SSM_DO_blue); break; } - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -3561,17 +3661,17 @@ ssm_do (struct scanner *s) 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_dropout); set_SSM2_pay_len(cmd, outLen); - + memset(out,0,outLen); - + switch(s->dropout_color[SIDE_FRONT]){ case COLOR_RED: set_SSM2_DO_do(out,SSM_DO_red); @@ -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{ @@ -3622,7 +3762,7 @@ read_sensors(struct scanner *s,SANE_Int option) size_t inLen = R_SENSORS_len; DBG (10, "read_sensors: start %d\n", option); - + if(!s->can_read_sensors){ DBG (10, "read_sensors: unsupported, finishing\n"); return ret; @@ -3638,14 +3778,14 @@ read_sensors(struct scanner *s,SANE_Int option) set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_sensors); set_R_xfer_length (cmd, inLen); - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); - + if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { /*set flags indicating there is data to read*/ memset(s->sensors_read,1,sizeof(s->sensors_read)); @@ -3656,12 +3796,12 @@ read_sensors(struct scanner *s,SANE_Int option) ret = SANE_STATUS_GOOD; } } - + if(option) s->sensors_read[option-OPT_ADF_LOADED] = 0; DBG (10, "read_sensors: finish\n"); - + return ret; } @@ -3677,7 +3817,7 @@ read_panel(struct scanner *s,SANE_Int option) size_t inLen = R_PANEL_len; DBG (10, "read_panel: start %d\n", option); - + if(!s->can_read_panel){ DBG (10, "read_panel: unsupported, finishing\n"); return ret; @@ -3693,14 +3833,14 @@ read_panel(struct scanner *s,SANE_Int option) set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_panel); set_R_xfer_length (cmd, inLen); - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); - + if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { /*set flags indicating there is data to read*/ memset(s->panel_read,1,sizeof(s->panel_read)); @@ -3717,12 +3857,12 @@ read_panel(struct scanner *s,SANE_Int option) ret = SANE_STATUS_GOOD; } } - + if(option) s->panel_read[option-OPT_START] = 0; DBG (10, "read_panel: finish %d\n",s->panel_counter); - + return ret; } @@ -3752,24 +3892,112 @@ send_panel(struct scanner *s) memset(out,0,outLen); set_S_PANEL_enable_led(out,s->panel_enable_led); set_S_PANEL_counter(out,s->panel_counter); - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); - + if (ret == SANE_STATUS_EOF) { ret = SANE_STATUS_GOOD; } - + DBG (10, "send_panel: finish %d\n", ret); - + return ret; } /* + * Request the size of the scanned image + */ +/* we should really be updating s->s and s->i instead */ +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); + + /* + * Round up to byte boundary if needed. + * For 1 bpp the resulting size may not fit in a byte boundary. + */ + int remainder = (get_R_PSIZE_width(in) * s->u.dpi_x / 1200) % 8; + + if (s->u.mode < MODE_GRAYSCALE && remainder) + { + int rounded_up = (8 - remainder) + (get_R_PSIZE_width(in) * s->u.dpi_x / 1200); + + s->u.br_x = rounded_up * 1200 / s->u.dpi_x; + } + else{ + 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; + + s->u.page_x = s->u.br_x; + s->u.page_y = s->u.br_y; + + 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 */ /* @@ -3783,7 +4011,7 @@ send_panel(struct scanner *s) * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. - * + * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle h of the @@ -3795,7 +4023,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SANE_Status ret = SANE_STATUS_GOOD; struct scanner *s = (struct scanner *) handle; - + DBG (10, "sane_get_parameters: start\n"); if(!s->started){ @@ -3825,14 +4053,14 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) DBG(15,"sane_get_parameters: area: tlx=%d, brx=%d, tly=%d, bry=%d\n", s->i.tl_x, s->i.br_x, s->i.tl_y, s->i.br_y); - DBG (15, "sane_get_parameters: params: ppl=%d, Bpl=%d, lines=%d\n", + DBG (15, "sane_get_parameters: params: ppl=%d, Bpl=%d, lines=%d\n", params->pixels_per_line, params->bytes_per_line, params->lines); - DBG (15, "sane_get_parameters: params: format=%d, depth=%d, last=%d\n", + DBG (15, "sane_get_parameters: params: format=%d, depth=%d, last=%d\n", params->format, params->depth, params->last_frame); DBG (10, "sane_get_parameters: finish\n"); - + return ret; } @@ -3840,9 +4068,9 @@ SANE_Status update_params(struct scanner *s, int calib) { SANE_Status ret = SANE_STATUS_GOOD; - + DBG (10, "update_params: start\n"); - + s->u.width = (s->u.br_x - s->u.tl_x) * s->u.dpi_x / 1200; s->u.height = (s->u.br_y - s->u.tl_y) * s->u.dpi_y / 1200; @@ -3884,7 +4112,7 @@ update_params(struct scanner *s, int calib) s->u.br_x, s->u.tl_x, s->u.dpi_x, s->u.br_y, s->u.tl_y, s->u.dpi_y); /* some scanners are limited in their valid scan params - * make a second version of the params struct, but + * make a second version of the params struct, but * override the user's values with what the scanner can actually do */ memcpy(&s->s,&s->u,sizeof(struct img_params)); @@ -3971,7 +4199,7 @@ update_params(struct scanner *s, int calib) /* round lines up to even number */ s->s.height += s->s.height % 2; - + DBG (15, "update_params: scan params: w:%d h:%d m:%d f:%d b:%d\n", s->s.width, s->s.height, s->s.mode, s->s.format, s->s.bpp); DBG (15, "update_params: scan params: B:%d vB:%d vw:%d\n", @@ -4011,12 +4239,12 @@ SANE_Status update_i_params(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; - + DBG (10, "update_i_params: start\n"); s->i.width = s->u.width; s->i.Bpl = s->u.Bpl; - + DBG (10, "update_i_params: finish\n"); return ret; } @@ -4105,6 +4333,16 @@ sane_start (SANE_Handle handle) DBG (5, "sane_start: ERROR: cannot send panel\n"); } + /* we should really be updating s->s and s->i instead */ + if(s->hwcrop){ + s->u.br_x = s->max_x; + s->u.tl_x = 0; + s->u.br_y = s->max_y; + s->u.tl_y = 0; + s->u.page_x = s->max_x; + s->u.page_y = s->max_y; + } + /* load our own private copy of scan params */ ret = update_params(s,0); if (ret != SANE_STATUS_GOOD) { @@ -4140,6 +4378,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) { @@ -4169,7 +4413,7 @@ sane_start (SANE_Handle handle) DBG (5, "sane_start: ERROR: cannot load page\n"); goto errors; } - + /* wait for scanner to finish load */ ret = wait_scanner (s); if (ret != SANE_STATUS_GOOD) { @@ -4185,6 +4429,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; } @@ -4235,7 +4485,7 @@ sane_start (SANE_Handle handle) } } } - + /* small, buffering scanners check for more pages by reading counter */ else{ ret = read_panel (s, OPT_COUNTER); @@ -4251,6 +4501,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; + } } } @@ -4261,9 +4517,9 @@ sane_start (SANE_Handle handle) DBG (15, "started=%d, side=%d, source=%d\n", s->started, s->side, s->u.source); - /* certain options require the entire image to + /* certain options require the entire image to * be collected from the scanner before we can - * tell the user the size of the image. the sane + * tell the user the size of the image. the sane * API has no way to inform the frontend of this, * so we block and buffer. yuck */ if(must_fully_buffer(s)){ @@ -4294,7 +4550,7 @@ sane_start (SANE_Handle handle) } if(s->swskip){ /* Skipping means throwing out this image. - * Pretend the user read the whole thing + * Pretend the user read the whole thing * and call sane_start again. * This assumes we are running in batch mode. */ if(buffer_isblank(s,s->side)){ @@ -4349,7 +4605,7 @@ clean_params (struct scanner *s) s->s.bytes_tot[0]=0; s->s.bytes_tot[1]=0; - /* store the number of front bytes */ + /* store the number of front bytes */ if ( s->u.source != SOURCE_ADF_BACK && s->u.source != SOURCE_CARD_BACK ) s->u.bytes_tot[SIDE_FRONT] = s->u.Bpl * s->u.height; @@ -4359,8 +4615,8 @@ clean_params (struct scanner *s) if ( s->s.source != SOURCE_ADF_BACK && s->s.source != SOURCE_CARD_BACK ) s->s.bytes_tot[SIDE_FRONT] = s->s.Bpl * s->s.height; - /* store the number of back bytes */ - if ( s->u.source == SOURCE_ADF_DUPLEX || s->u.source == SOURCE_ADF_BACK + /* store the number of back bytes */ + if ( s->u.source == SOURCE_ADF_DUPLEX || s->u.source == SOURCE_ADF_BACK || s->u.source == SOURCE_CARD_DUPLEX || s->u.source == SOURCE_CARD_BACK ) s->u.bytes_tot[SIDE_BACK] = s->u.Bpl * s->u.height; @@ -4421,14 +4677,14 @@ set_window (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; - /* The command specifies the number of bytes in the data phase - * the data phase has a header, followed by 1 window desc block + /* The command specifies the number of bytes in the data phase + * the data phase has a header, followed by 1 window desc block * the header specifies the number of bytes in 1 window desc block */ unsigned char cmd[SET_WINDOW_len]; size_t cmdLen = SET_WINDOW_len; - + unsigned char out[SW_header_len + SW_desc_len]; size_t outLen = SW_header_len + SW_desc_len; @@ -4484,9 +4740,9 @@ set_window (struct scanner *s) /*convert our common -127 to +127 range into HW's range *FIXME: this code assumes hardware range of 0-255 */ set_WD_brightness (desc1, s->brightness+128); - + set_WD_threshold (desc1, s->threshold); - + /*convert our common -127 to +127 range into HW's range *FIXME: this code assumes hardware range of 0-255 */ set_WD_contrast (desc1, s->contrast+128); @@ -4593,7 +4849,7 @@ object_position (struct scanner *s, int i_load) /* * Issues SCAN command. - * + * * (This doesn't actually read anything, it just tells the scanner * to start scanning.) */ @@ -4641,7 +4897,7 @@ start_scan (struct scanner *s, int type) /* * Called by SANE to read data. - * + * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory @@ -4649,7 +4905,7 @@ start_scan (struct scanner *s, int type) * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). - * + * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. */ @@ -4698,7 +4954,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len } } } - + /* simplex or non-alternating duplex */ else{ if(!s->s.eof[s->side]){ @@ -4719,7 +4975,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len ret = read_from_buffer(s,buf,max_len,len,s->side); if(ret) goto errors; - + ret = check_for_cancel(s); s->reading = 0; @@ -4813,13 +5069,13 @@ read_from_scanner(struct scanner *s, int side, int exact) size_t i; for(i=0;i<inLen;i++){ - + /* about to change stage */ if(s->jpeg_stage == JPEG_STAGE_NONE && in[i] == 0xff){ s->jpeg_ff_offset=0; continue; } - + s->jpeg_ff_offset++; /* last byte was an ff, this byte is SOF */ @@ -4827,7 +5083,7 @@ read_from_scanner(struct scanner *s, int side, int exact) s->jpeg_stage = JPEG_STAGE_SOF; continue; } - + if(s->jpeg_stage == JPEG_STAGE_SOF){ /* lines in start of frame, overwrite it */ @@ -4839,7 +5095,7 @@ read_from_scanner(struct scanner *s, int side, int exact) in[i] = s->s.height & 0xff; continue; } - + /* width in start of frame, overwrite it */ if(s->jpeg_ff_offset == 7){ in[i] = (s->s.width >> 8) & 0xff; @@ -4883,7 +5139,7 @@ read_from_scanner(struct scanner *s, int side, int exact) s->s.bytes_tot[side] = s->s.bytes_sent[side]; s->i.bytes_tot[side] = s->i.bytes_sent[side]; s->u.bytes_tot[side] = s->i.bytes_sent[side]; - } + } /* this is non-jpeg data, fill remainder, change rx'd size */ else{ @@ -5025,7 +5281,7 @@ read_from_scanner_duplex(struct scanner *s,int exact) return ret; } -/* these functions copy image data from input buffer to scanner struct +/* these functions copy image data from input buffer to scanner struct * descrambling it, and putting it in the right side buffer */ /* NOTE: they assume buffer is scanline aligned */ static SANE_Status @@ -5051,7 +5307,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) s->s.bytes_sent[side] += len; return ret; } - + DBG (15, "copy_simplex: per-line copy\n"); line = malloc(bwidth); @@ -5061,7 +5317,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) for(i=0; i<len; i+=bwidth){ int lineNum = s->s.bytes_sent[side] / bwidth; - + /*increment number of bytes rx'd from scanner*/ s->s.bytes_sent[side] += bwidth; @@ -5075,9 +5331,9 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line_next = 0; if(s->s.format == SANE_FRAME_GRAY){ - + switch (s->gray_interlace[side]) { - + /* one line has the following format: ggg...GGG * where the 'capital' letters are the beginning of the line */ case GRAY_INTERLACE_gG: @@ -5086,10 +5342,10 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = buf[i+j]; } break; - + case GRAY_INTERLACE_2510: DBG (17, "copy_simplex: gray, 2510\n"); - + /* first read head (third byte of every three) */ for(j=bwidth-1;j>=0;j-=3){ line[line_next++] = buf[i+j]; @@ -5109,11 +5365,11 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) break; } } - + else if (s->s.format == SANE_FRAME_RGB){ - + switch (inter) { - + /* scanner returns color data as bgrbgr... */ case COLOR_INTERLACE_BGR: DBG (17, "copy_simplex: color, BGR\n"); @@ -5123,7 +5379,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = buf[i+j*3]; } break; - + /* scanner returns color data as gbrgbr... */ case COLOR_INTERLACE_GBR: DBG (17, "copy_simplex: color, GBR\n"); @@ -5133,7 +5389,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = buf[i+j*3+1]; } break; - + /* scanner returns color data as brgbrg... */ case COLOR_INTERLACE_BRG: DBG (17, "copy_simplex: color, BRG\n"); @@ -5143,7 +5399,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = buf[i+j*3]; } break; - + /* one line has the following format: RRR...rrrGGG...gggBBB...bbb */ case COLOR_INTERLACE_RRGGBB: DBG (17, "copy_simplex: color, RRGGBB\n"); @@ -5153,7 +5409,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = buf[i+2*pwidth+j]; } break; - + /* one line has the following format: rrr...RRRggg...GGGbbb...BBB * where the 'capital' letters are the beginning of the line */ case COLOR_INTERLACE_rRgGbB: @@ -5164,10 +5420,10 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[line_next++] = buf[i+2*pwidth+j]; } break; - + case COLOR_INTERLACE_2510: DBG (17, "copy_simplex: color, 2510\n"); - + /* first read head (third byte of every three) */ for(j=t-1;j>=0;j-=3){ line[line_next++] = buf[i+j]; @@ -5193,7 +5449,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) break; } } - + /* nothing sent above? just copy one line of the block */ /* used by uninterlaced gray/color */ if(!line_next){ @@ -5201,14 +5457,14 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) memcpy(line+line_next,buf+i,bwidth); line_next = bwidth; } - + /* invert image if scanner needs it for this mode */ if(s->reverse_by_mode[s->s.mode]){ for(j=0; j<line_next; j++){ line[j] ^= 0xff; } } - + /* apply calibration if we have it */ if(s->f_offset[side]){ DBG (17, "copy_simplex: apply offset\n"); @@ -5227,7 +5483,7 @@ copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) line[j] = curr; } } - + /* apply brightness and contrast if hardware cannot do it */ if(s->sw_lut && (s->s.mode == MODE_COLOR || s->s.mode == MODE_GRAYSCALE)){ DBG (17, "copy_simplex: apply brightness/contrast\n"); @@ -5283,7 +5539,7 @@ copy_duplex(struct scanner *s, unsigned char * buf, int len) DBG (10, "copy_duplex: 2510\n"); for(i=0; i<len; i+=dbwidth){ - + for(j=0;j<dbwidth;j+=6){ /* we are actually only partially descrambling, @@ -5473,7 +5729,7 @@ copy_line(struct scanner *s, unsigned char * buff, int side) line[i*3+2] = line[source+2]; } } - + /* scan is wider than user wanted, skip some pixels on left side */ if(s->i.width != s->s.width){ offset = ((s->valid_x-s->i.page_x) / 2 + s->i.tl_x) * s->i.dpi_x/1200; @@ -5481,12 +5737,12 @@ copy_line(struct scanner *s, unsigned char * buff, int side) /* change mode, store line in buffer */ switch (s->i.mode) { - + case MODE_COLOR: memcpy(s->buffers[side]+s->i.bytes_sent[side], line+(offset*3), ibwidth); s->i.bytes_sent[side] += ibwidth; break; - + case MODE_GRAYSCALE: for(i=0;i<ibwidth;i++){ int source = (offset+i)*3; @@ -5494,7 +5750,7 @@ copy_line(struct scanner *s, unsigned char * buff, int side) = ((int)line[source] + line[source+1] + line[source+2])/3; } break; - + default: /*loop over output bytes*/ for(i=0;i<ibwidth;i++){ @@ -5506,7 +5762,7 @@ copy_line(struct scanner *s, unsigned char * buff, int side) for(j=0;j<8;j++){ int source = offset*3 + i*24 + j*3; if( (line[source] + line[source+1] + line[source+2]) < thresh ){ - curr |= 1 << (7-j); + curr |= 1 << (7-j); } } @@ -5535,15 +5791,15 @@ read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, /* figure out the max amount to transfer */ if(bytes > remain) bytes = remain; - + *len = bytes; - + /*FIXME this needs to timeout eventually */ if(!bytes){ DBG(5,"read_from_buffer: nothing to do\n"); return SANE_STATUS_GOOD; } - + DBG(15, "read_from_buffer: si:%d to:%d tx:%d bu:%d pa:%d\n", side, s->i.bytes_tot[side], s->u.bytes_sent[side], max_len, bytes); @@ -5701,7 +5957,7 @@ calibrate_AFE (struct scanner *s) DBG (5, "calibrate_AFE: ERROR: cannot set window\n"); goto cleanup; } - + /* first pass (black offset), lamp off, no offset/gain/exposure */ DBG (15, "calibrate_AFE: offset\n"); @@ -5925,7 +6181,7 @@ calibrate_fine_buffer (struct scanner *s) DBG (5, "calibrate_fine_buffer: 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); memset(cmd,0,cmdLen); @@ -5952,13 +6208,13 @@ calibrate_fine_buffer (struct scanner *s) /*color mode, expand offset across all three channels? */ if(s->s.format == SANE_FRAME_RGB){ for(j=0; j<s->s.valid_width; j++){ - - /*red*/ + + /*red*/ s->f_offset[i][j*3] = in[j*2+i]; if(s->f_offset[i][j*3] < 1) s->f_offset[i][j*3] = 1; - /*green and blue, same as red*/ + /*green and blue, same as red*/ s->f_offset[i][j*3+1] = s->f_offset[i][j*3+2] = s->f_offset[i][j*3]; } } @@ -5995,10 +6251,10 @@ calibrate_fine_buffer (struct scanner *s) int codes[] = {R_FINE_uid_red,R_FINE_uid_green,R_FINE_uid_blue}; for(k=0;k<3;k++){ - + set_R_xfer_uid (cmd, codes[k]); inLen = reqLen; - + hexdump(15, "cmd:", cmd, cmdLen); ret = do_cmd ( @@ -6009,12 +6265,12 @@ calibrate_fine_buffer (struct scanner *s) ); if (ret != SANE_STATUS_GOOD) goto cleanup; - + for(i=0;i<2;i++){ for(j=0; j<s->s.valid_width; j++){ - + s->f_gain[i][j*3+k] = in[j*2+i]*3/4; - + if(s->f_gain[i][j*3+k] < 1) s->f_gain[i][j*3+k] = 1; } @@ -6027,7 +6283,7 @@ 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 ( @@ -6038,12 +6294,12 @@ calibrate_fine_buffer (struct scanner *s) ); if (ret != SANE_STATUS_GOOD) goto cleanup; - + for(i=0;i<2;i++){ for(j=0; j<s->s.valid_width; j++){ - + s->f_gain[i][j] = in[j*2+i]*3/4; - + if(s->f_gain[i][j] < 1) s->f_gain[i][j] = 1; } @@ -6127,7 +6383,7 @@ calibrate_fine (struct scanner *s) DBG (5, "calibrate_fine: ERROR: cannot load buffers\n"); goto cleanup; } - + /*blast the existing fine cal data so reading code wont apply it*/ ret = offset_buffers(s,0); ret = gain_buffers(s,0); @@ -6138,14 +6394,14 @@ calibrate_fine (struct scanner *s) DBG (5, "calibrate_fine: 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"); goto cleanup; } - + /*handle fifth pass (fine offset), lamp off*/ DBG (15, "calibrate_fine: offset\n"); ret = calibration_scan(s,0xff); @@ -6159,7 +6415,7 @@ calibrate_fine (struct scanner *s) DBG (5, "calibrate_fine: ERROR: cannot load offset buffers\n"); goto cleanup; } - + for(i=0;i<2;i++){ for(j=0; j<s->s.valid_Bpl; j++){ min = 0; @@ -6184,7 +6440,7 @@ calibrate_fine (struct scanner *s) DBG (5, "calibrate_fine: ERROR: cannot load gain buffers\n"); goto cleanup; } - + for(i=0;i<2;i++){ for(j=0; j<s->s.valid_Bpl; j++){ max = 0; @@ -6231,14 +6487,14 @@ calibration_scan (struct scanner *s, int scan) DBG (5, "calibration_scan: ERROR: cannot clean_params\n"); return ret; } - + /* start scanning */ ret = start_scan (s,scan); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibration_scan: ERROR: cannot start_scan\n"); return ret; } - + while(!s->s.eof[SIDE_FRONT] && !s->s.eof[SIDE_BACK]){ ret = read_from_scanner_duplex(s,1); } @@ -6260,7 +6516,7 @@ write_AFE(struct scanner *s) size_t cmdLen = COR_CAL_len; /*use the longest payload for buffer*/ - unsigned char pay[CC3_pay_len]; + unsigned char pay[CC3_pay_len]; size_t payLen = CC3_pay_len; DBG (10, "write_AFE: start\n"); @@ -6272,7 +6528,7 @@ write_AFE(struct scanner *s) set_SCSI_opcode(cmd, COR_CAL_code); set_CC_version(cmd,CC3_pay_ver); set_CC_xferlen(cmd,payLen); - + memset(pay,0,payLen); set_CC3_gain_f_r(pay,s->c_gain[SIDE_FRONT]); @@ -6282,7 +6538,7 @@ write_AFE(struct scanner *s) set_CC3_off_f_r(pay,s->c_offset[SIDE_FRONT]); set_CC3_off_f_g(pay,s->c_offset[SIDE_FRONT]); set_CC3_off_f_b(pay,s->c_offset[SIDE_FRONT]); - + set_CC3_exp_f_r(pay,s->c_exposure[SIDE_FRONT][CHAN_RED]); set_CC3_exp_f_g(pay,s->c_exposure[SIDE_FRONT][CHAN_GREEN]); set_CC3_exp_f_b(pay,s->c_exposure[SIDE_FRONT][CHAN_BLUE]); @@ -6307,7 +6563,7 @@ write_AFE(struct scanner *s) set_SCSI_opcode(cmd, COR_CAL_code); set_CC_version(cmd,CC_pay_ver); set_CC_xferlen(cmd,payLen); - + memset(pay,0,payLen); set_CC_f_gain(pay,s->c_gain[SIDE_FRONT]); set_CC_unk1(pay,1); @@ -6319,7 +6575,7 @@ write_AFE(struct scanner *s) set_CC_exp_f_r2(pay,s->c_exposure[SIDE_FRONT][CHAN_RED]); set_CC_exp_f_g2(pay,s->c_exposure[SIDE_FRONT][CHAN_GREEN]); set_CC_exp_f_b2(pay,s->c_exposure[SIDE_FRONT][CHAN_BLUE]); - + set_CC_b_gain(pay,s->c_gain[SIDE_BACK]); set_CC_b_offset(pay,s->c_offset[SIDE_BACK]); set_CC_exp_b_r1(pay,s->c_exposure[SIDE_BACK][CHAN_RED]); @@ -6414,26 +6670,26 @@ gain_buffers (struct scanner *s, int setup) * @@ Section 6 - SANE cleanup functions */ /* - * Cancels a scan. + * Cancels a scan. * * It has been said on the mailing list that sane_cancel is a bit of a * misnomer because it is routinely called to signal the end of a * batch - quoting David Mosberger-Tang: - * + * * > In other words, the idea is to have sane_start() be called, and * > collect as many images as the frontend wants (which could in turn * > consist of multiple frames each as indicated by frame-type) and - * > when the frontend is done, it should call sane_cancel(). + * > when the frontend is done, it should call sane_cancel(). * > Sometimes it's better to think of sane_cancel() as "sane_stop()" * > but that name would have had some misleading connotations as * > well, that's why we stuck with "cancel". - * + * * The current consensus regarding duplex and ADF scans seems to be * the following call sequence: sane_start; sane_read (repeat until * EOF); sane_start; sane_read... and then call sane_cancel if the * batch is at an end. I.e. do not call sane_cancel during the run but * as soon as you get a SANE_STATUS_NO_DOCS. - * + * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by @@ -6478,13 +6734,13 @@ check_for_cancel(struct scanner *s) if(s->started && s->cancelled){ unsigned char cmd[CANCEL_len]; size_t cmdLen = CANCEL_len; - + DBG (15, "check_for_cancel: cancelling\n"); - + /* cancel scan */ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, CANCEL_code); - + ret = do_cmd ( s, 1, 0, cmd, cmdLen, @@ -6494,7 +6750,7 @@ check_for_cancel(struct scanner *s) if(ret){ DBG (5, "check_for_cancel: ignoring bad cancel: %d\n",ret); } - + ret = object_position(s,SANE_FALSE); if(ret){ DBG (5, "check_for_cancel: ignoring bad eject: %d\n",ret); @@ -6516,7 +6772,7 @@ check_for_cancel(struct scanner *s) /* * Ends use of the scanner. - * + * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is @@ -6560,7 +6816,7 @@ disconnect_fd (struct scanner *s) /* * Terminates the backend. - * + * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be @@ -6983,19 +7239,19 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, DBG(5,"cmd: no mem\n"); return SANE_STATUS_NO_MEM; } - + /* build a USB packet around the SCSI command */ cmdBuffer[3] = cmdLength-4; cmdBuffer[5] = 1; cmdBuffer[6] = 0x90; memcpy(cmdBuffer+cmdOffset,cmdBuff,cmdLen); - + /* write the command out */ DBG(25, "cmd: writing %d bytes, timeout %d\n", (int)cmdLength, cmdTimeout); hexdump(30, "cmd: >>", cmdBuffer, cmdLength); ret = sanei_usb_write_bulk(s->fd, cmdBuffer, &cmdActual); DBG(25, "cmd: wrote %d bytes, retVal %d\n", (int)cmdActual, ret); - + if(cmdLength != cmdActual){ DBG(5,"cmd: wrong size %d/%d\n", (int)cmdLength, (int)cmdActual); free(cmdBuffer); @@ -7043,19 +7299,19 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, DBG(5,"out: no mem\n"); return SANE_STATUS_NO_MEM; } - + /* build a USB packet around the SCSI command */ outBuffer[3] = outLength-4; outBuffer[5] = 2; outBuffer[6] = 0xb0; memcpy(outBuffer+outOffset,outBuff,outLen); - + /* write the command out */ DBG(25, "out: writing %d bytes, timeout %d\n", (int)outLength, outTimeout); hexdump(30, "out: >>", outBuffer, outLength); ret = sanei_usb_write_bulk(s->fd, outBuffer, &outActual); DBG(25, "out: wrote %d bytes, retVal %d\n", (int)outActual, ret); - + if(outLength != outActual){ DBG(5,"out: wrong size %d/%d\n", (int)outLength, (int)outActual); free(outBuffer); @@ -7102,7 +7358,7 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, DBG(5,"in: no mem\n"); return SANE_STATUS_NO_MEM; } - + DBG(25, "in: reading %d bytes, timeout %d\n", (int)inActual, inTimeout); ret = sanei_usb_read_bulk(s->fd, inBuffer, &inActual); DBG(25, "in: read %d bytes, retval %d\n", (int)inActual, ret); @@ -7161,11 +7417,11 @@ do_usb_cmd(struct scanner *s, int runRS, int shortTime, ret = SANE_STATUS_EOF; DBG(5,"in: short read, %d/%d\n", (int)inLength,(int)inActual); } - + /* ignore the USB packet around the SCSI command */ *inLen = inActual - inOffset; memcpy(inBuff,inBuffer+inOffset,*inLen); - + free(inBuffer); } @@ -7214,12 +7470,12 @@ do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength) DBG(5,"stat: no mem\n"); return SANE_STATUS_NO_MEM; } - + DBG(25, "stat: reading %d bytes, timeout %d\n", (int)statLength, statTimeout); ret = sanei_usb_read_bulk(s->fd, statBuffer, &statActual); DBG(25, "stat: read %d bytes, retval %d\n", (int)statActual, ret); hexdump(30, "stat: <<", statBuffer, statActual); - + /*weird status*/ if(ret != SANE_STATUS_GOOD){ DBG(5,"stat: clearing error '%s'\n",sane_strstatus(ret)); @@ -7232,7 +7488,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); } @@ -7286,7 +7542,7 @@ do_usb_clear(struct scanner *s, int clear, int runRS) rs_in, &rs_inLen ); DBG(25,"rs sub call <<\n"); - + if(ret2 == SANE_STATUS_EOF){ DBG(5,"rs: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; @@ -7309,7 +7565,7 @@ do_usb_clear(struct scanner *s, int clear, int runRS) } static SANE_Status -wait_scanner(struct scanner *s) +wait_scanner(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; @@ -7360,11 +7616,11 @@ wait_scanner(struct scanner *s) /* Some scanners have per-resolution * color interlacing values, but most - * don't. This helper can tell the + * don't. This helper can tell the * difference. */ static int -get_color_inter(struct scanner *s, int side, int res) +get_color_inter(struct scanner *s, int side, int res) { int i; for(i=0;i<DPI_1200;i++){ @@ -7384,7 +7640,7 @@ get_color_inter(struct scanner *s, int side, int res) * due to using FB or overscan. */ static int -get_page_width(struct scanner *s) +get_page_width(struct scanner *s) { int width = s->u.page_x; @@ -7408,7 +7664,7 @@ get_page_width(struct scanner *s) * due to using FB or overscan. */ static int -get_page_height(struct scanner *s) +get_page_height(struct scanner *s) { int height = s->u.page_y; @@ -7600,7 +7856,7 @@ buffer_crop(struct scanner *s, int side) /* if we will later binarize this image, make sure the width * is a multiple of 8 pixels, by adjusting the right side */ - if ( must_downsample(s) && s->u.mode < MODE_GRAYSCALE ){ + if ( must_downsample(s) && s->u.mode < MODE_GRAYSCALE ){ s->crop_vals[3] -= (s->crop_vals[3]-s->crop_vals[2]) % 8; } @@ -7618,13 +7874,13 @@ buffer_crop(struct scanner *s, int side) s->i.width = s->s_params.pixels_per_line; s->i.height = s->s_params.lines; s->i.Bpl = s->s_params.bytes_per_line; - + /* update image size counter to new, smaller size */ s->i.bytes_tot[side] = s->s_params.lines * s->s_params.bytes_per_line; s->i.bytes_sent[side] = s->i.bytes_tot[side]; s->u.bytes_sent[side] = 0; - - cleanup: + + cleanup: DBG (10, "buffer_crop: finish\n"); return ret; } @@ -7679,7 +7935,7 @@ buffer_isblank(struct scanner *s, int side) return status; } -/* certain options require the entire image to +/* certain options require the entire image to * be collected from the scanner before we can * tell the user the size of the image. */ static int @@ -7696,7 +7952,7 @@ must_fully_buffer(struct scanner *s) return 0; } -/* certain scanners require the mode of the +/* certain scanners require the mode of the * image to be changed in software. */ static int must_downsample(struct scanner *s) @@ -7714,7 +7970,7 @@ must_downsample(struct scanner *s) used by scanners to implement brightness/contrast/gamma or by backends to speed binarization/thresholding - offset and slope inputs are -127 to +127 + offset and slope inputs are -127 to +127 slope rotates line around central input/output val, 0 makes horizontal line @@ -7730,9 +7986,9 @@ must_downsample(struct scanner *s) offset moves line vertically, and clamps to output range 0 keeps the line crossing the center of the table - pos zero neg + pos zero neg . xxxxxxxx . xx . - . x . x . + . x . x . out x . x . x . . x . x ............ xx.......... xxxxxxxx.... @@ -7761,7 +8017,7 @@ load_lut (unsigned char * lut, * first [-127,127] to [-.999,.999] * then to [-PI/4,PI/4] then [0,PI/2] * then take the tangent (T.O.A) - * then multiply by the normal linear slope + * then multiply by the normal linear slope * because the table may not be square, i.e. 1024x256*/ rise = tan((double)slope/128 * M_PI_4 + M_PI_4) * max_out_val / max_in_val; @@ -7793,4 +8049,3 @@ load_lut (unsigned char * lut, DBG (10, "load_lut: finish\n"); return ret; } - |