diff options
Diffstat (limited to 'backend/fujitsu.c')
-rw-r--r-- | backend/fujitsu.c | 133 |
1 files changed, 105 insertions, 28 deletions
diff --git a/backend/fujitsu.c b/backend/fujitsu.c index 5dc466c..d24975e 100644 --- a/backend/fujitsu.c +++ b/backend/fujitsu.c @@ -603,8 +603,12 @@ v134 2019-02-23, MAN - rewrite init_vpd for scanners which fail to report overscan correctly - v135 2019-11-10, MAN + v135 2019-11-10, MAN (SANE 1.0.29) - set has_MS_lamp=0 for fi-72x0, bug #134 + v136 2020-02-07, MAN + - add support for fi-800R + - add support for card scanning slot (Return Path) + - fix bug with reading hardware sensors on first invocation SANE FLOW DIAGRAM @@ -654,7 +658,7 @@ #include "fujitsu.h" #define DEBUG 1 -#define BUILD 134 +#define BUILD 136 /* values for SANE_DEBUG_FUJITSU env var: - errors 5 @@ -678,6 +682,9 @@ #define STRING_ADFFRONT SANE_I18N("ADF Front") #define STRING_ADFBACK SANE_I18N("ADF Back") #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") +#define STRING_CARDFRONT SANE_I18N("Card Front") +#define STRING_CARDBACK SANE_I18N("Card Back") +#define STRING_CARDDUPLEX SANE_I18N("Card Duplex") #define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART #define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE @@ -1821,6 +1828,12 @@ init_vpd (struct fujitsu *s) DBG (15, " object position halt: %d\n", s->has_op_halt); } + if (payload_off >= 0x7c) { + s->has_return_path = get_IN_return_path(in); + DBG (15, " return path (card) scanning: %d\n", s->has_return_path); + DBG (15, " energy star 3: %d\n", get_IN_energy_star3(in)); + } + DBG (10, "init_vpd: finish\n"); return SANE_STATUS_GOOD; @@ -2498,6 +2511,8 @@ init_user (struct fujitsu *s) s->source = SOURCE_FLATBED; else if(s->has_adf) s->source = SOURCE_ADF_FRONT; + else if(s->has_return_path) + s->source = SOURCE_CARD_FRONT; /* scan mode */ if(s->can_mode[MODE_LINEART]) @@ -2875,6 +2890,16 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) s->source_list[i++]=STRING_ADFDUPLEX; } } + if(s->has_return_path){ + s->source_list[i++]=STRING_CARDFRONT; + + if(s->has_back){ + s->source_list[i++]=STRING_CARDBACK; + } + if(s->has_duplex){ + s->source_list[i++]=STRING_CARDDUPLEX; + } + } s->source_list[i]=NULL; opt->name = SANE_NAME_SCAN_SOURCE; @@ -3049,7 +3074,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_x_range; - if(s->has_adf){ + if(s->has_adf || s->has_return_path){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; @@ -3076,7 +3101,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_y_range; - if(s->has_adf){ + if(s->has_adf || s->has_return_path){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; @@ -4474,6 +4499,18 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->cap = SANE_CAP_INACTIVE; } + if(option==OPT_CARD_LOADED){ + opt->name = "card-loaded"; + opt->title = SANE_I18N ("Card loaded"); + opt->desc = SANE_I18N ("Card slot contains paper"); + opt->type = SANE_TYPE_BOOL; + opt->unit = SANE_UNIT_NONE; + if (s->has_cmd_hw_status && s->has_return_path) + opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + else + opt->cap = SANE_CAP_INACTIVE; + } + if(option==OPT_SLEEP){ opt->name = "power-save"; opt->title = SANE_I18N ("Power saving"); @@ -4697,6 +4734,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option, else if(s->source == SOURCE_ADF_DUPLEX){ strcpy (val, STRING_ADFDUPLEX); } + else if(s->source == SOURCE_CARD_FRONT){ + strcpy (val, STRING_CARDFRONT); + } + else if(s->source == SOURCE_CARD_BACK){ + strcpy (val, STRING_CARDBACK); + } + else if(s->source == SOURCE_CARD_DUPLEX){ + strcpy (val, STRING_CARDDUPLEX); + } return SANE_STATUS_GOOD; case OPT_MODE: @@ -5215,6 +5261,11 @@ sane_control_option (SANE_Handle handle, SANE_Int option, *val_p = s->hw_adf_open; return ret; + case OPT_CARD_LOADED: + ret = get_hardware_status(s,option); + *val_p = s->hw_card_loaded; + return ret; + case OPT_SLEEP: ret = get_hardware_status(s,option); *val_p = s->hw_sleep; @@ -5323,6 +5374,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option, else if (!strcmp (val, STRING_ADFDUPLEX)) { tmp = SOURCE_ADF_DUPLEX; } + else if (!strcmp (val, STRING_CARDFRONT)) { + tmp = SOURCE_CARD_FRONT; + } + else if (!strcmp (val, STRING_CARDBACK)) { + tmp = SOURCE_CARD_BACK; + } + else if (!strcmp (val, STRING_CARDDUPLEX)) { + tmp = SOURCE_CARD_DUPLEX; + } else{ tmp = SOURCE_FLATBED; } @@ -5912,12 +5972,12 @@ get_hardware_status (struct fujitsu *s, SANE_Int option) /* only run this if frontend has already read the last time we got it */ /* or if we don't care for such bookkeeping (private use) */ - if (!option || s->hw_read[option-OPT_TOP]) { + if (!option || !s->hw_data_avail[option-OPT_TOP]) { DBG (15, "get_hardware_status: running\n"); - /* mark all values as unread */ - memset(s->hw_read,0,sizeof(s->hw_read)); + /* mark all values as available */ + memset(s->hw_data_avail,1,sizeof(s->hw_data_avail)); if (s->has_cmd_hw_status){ unsigned char cmd[GET_HW_STATUS_len]; @@ -5950,6 +6010,7 @@ get_hardware_status (struct fujitsu *s, SANE_Int option) s->hw_hopper = get_GHS_hopper(in); s->hw_omr = get_GHS_omr(in); s->hw_adf_open = get_GHS_adf_open(in); + s->hw_card_loaded = get_GHS_exit(in); s->hw_sleep = get_GHS_sleep(in); s->hw_send_sw = get_GHS_send_sw(in); @@ -6015,7 +6076,7 @@ get_hardware_status (struct fujitsu *s, SANE_Int option) } if(option) - s->hw_read[option-OPT_TOP] = 1; + s->hw_data_avail[option-OPT_TOP] = 0; DBG (10, "get_hardware_status: finish\n"); @@ -6905,8 +6966,8 @@ sane_start (SANE_Handle handle) } /* low mem mode messes up the side marker, reset it */ - if(s->source == SOURCE_ADF_DUPLEX && s->low_mem - && s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK] + if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) + && s->low_mem && s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK] ){ s->side = SIDE_BACK; } @@ -6915,7 +6976,7 @@ sane_start (SANE_Handle handle) if(!s->started){ /* load side marker */ - if(s->source == SOURCE_ADF_BACK){ + if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){ s->side = SIDE_BACK; } else{ @@ -6936,6 +6997,12 @@ sane_start (SANE_Handle handle) DBG (5, "sane_start: ERROR: cannot control fb, ignoring\n"); } } + else if(s->source == SOURCE_CARD_FRONT || s->source == SOURCE_CARD_BACK || s->source == SOURCE_CARD_DUPLEX){ + ret = scanner_control(s, SC_function_rpath); + if (ret != SANE_STATUS_GOOD) { + DBG (5, "sane_start: ERROR: cannot control rp, ignoring\n"); + } + } else{ ret = scanner_control(s, SC_function_adf); if (ret != SANE_STATUS_GOOD) { @@ -7038,7 +7105,7 @@ sane_start (SANE_Handle handle) } } /* if already running, duplex needs to switch sides */ - else if(s->source == SOURCE_ADF_DUPLEX){ + else if(s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX){ s->side = !s->side; } @@ -7047,7 +7114,7 @@ sane_start (SANE_Handle handle) /* 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 */ - if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK){ + if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){ s->bytes_rx[0]=0; s->bytes_rx[1]=0; @@ -7095,7 +7162,7 @@ sane_start (SANE_Handle handle) } /* store the number of front bytes */ - if ( s->source != SOURCE_ADF_BACK ){ + if ( s->source != SOURCE_ADF_BACK && s->source != SOURCE_CARD_BACK ){ s->bytes_tot[SIDE_FRONT] = s->s_params.bytes_per_line * s->s_params.lines; s->buff_tot[SIDE_FRONT] = s->buffer_size; @@ -7114,13 +7181,14 @@ sane_start (SANE_Handle handle) } /* store the number of back bytes */ - if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK ){ + if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK + || s->source == SOURCE_CARD_DUPLEX || s->source == SOURCE_CARD_BACK ){ s->bytes_tot[SIDE_BACK] = s->s_params.bytes_per_line * s->s_params.lines; s->buff_tot[SIDE_BACK] = s->bytes_tot[SIDE_BACK]; /* the back buffer is normally very large, but some scanners or * option combinations dont need it, so we make a small one */ - if(s->low_mem || s->source == SOURCE_ADF_BACK + if(s->low_mem || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK || s->duplex_interlace == DUPLEX_INTERLACE_NONE) s->buff_tot[SIDE_BACK] = s->buffer_size; } @@ -7308,13 +7376,14 @@ scanner_control (struct fujitsu *s, int function) memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SCANNER_CONTROL_code); - set_SC_function (cmd, function); + set_SC_function_1 (cmd, function); + set_SC_function_2 (cmd, function); DBG (15, "scanner_control: function %d\n",function); /* don't really need to ask for adf if that's the only option */ /* doing so causes the 3091 to complain */ - if(function == SC_function_adf && !s->has_flatbed){ + if(function == SC_function_adf && !s->has_flatbed && !s->has_return_path){ DBG (10, "scanner_control: adf function not required\n"); return ret; } @@ -7486,7 +7555,7 @@ set_window (struct fujitsu *s) set_WPDB_wdblen(header, SW_desc_len); /* init the window block */ - if (s->source == SOURCE_ADF_BACK) { + if (s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) { set_WD_wid (desc1, WD_wid_back); } else{ @@ -7675,7 +7744,7 @@ set_window (struct fujitsu *s) } /* when in duplex mode, copy first desc block into second */ - if (s->source == SOURCE_ADF_DUPLEX) { + if (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) { memcpy (desc2, desc1, SW_desc_len); set_WD_wid (desc2, WD_wid_back); @@ -7823,7 +7892,7 @@ get_pixelsize(struct fujitsu *s, int actual) } /* - * Issues the SCSI OBJECT POSITION command if an ADF is in use. + * Issues the SCSI OBJECT POSITION command if an ADF or card scanner is in use. */ static SANE_Status object_position (struct fujitsu *s, int action) @@ -7880,9 +7949,9 @@ start_scan (struct fujitsu *s) DBG (10, "start_scan: start\n"); - if (s->source != SOURCE_ADF_DUPLEX) { + if (s->source != SOURCE_ADF_DUPLEX && s->source != SOURCE_CARD_DUPLEX) { outLen--; - if(s->source == SOURCE_ADF_BACK) { + if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) { out[0] = WD_wid_back; } } @@ -7983,7 +8052,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len /* swap sides if user asked for low-mem mode, we are duplexing, * and there is data waiting on the other side */ - if(s->low_mem && s->source == SOURCE_ADF_DUPLEX + if(s->low_mem + && (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) && (s->bytes_rx[!s->side] > s->bytes_tx[!s->side] || (s->eof_rx[!s->side] && !s->eof_tx[!s->side]) ) @@ -8013,7 +8083,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len } /* end 3091 */ /* alternating jpeg duplex interlacing */ - else if(s->source == SOURCE_ADF_DUPLEX + else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) && s->s_params.format == SANE_FRAME_JPEG && s->jpeg_interlace == JPEG_INTERLACE_ALT ){ @@ -8025,7 +8095,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len } /* end alt jpeg */ /* alternating pnm duplex interlacing */ - else if(s->source == SOURCE_ADF_DUPLEX + else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) && s->s_params.format != SANE_FRAME_JPEG && s->duplex_interlace == DUPLEX_INTERLACE_ALT ){ @@ -8080,7 +8150,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len /* swap sides if user asked for low-mem mode, we are duplexing, * and there is data waiting on the other side */ - if(s->low_mem && s->source == SOURCE_ADF_DUPLEX + if(s->low_mem + && (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) && (s->bytes_rx[!s->side] > s->bytes_tx[!s->side] || (s->eof_rx[!s->side] && !s->eof_tx[!s->side]) ) @@ -9291,6 +9362,10 @@ sense_handler (int fd, unsigned char * sensed_data, void *arg) DBG (5, "Medium error: Carrier sheet\n"); return SANE_STATUS_JAMMED; } + if (0x0c == ascq) { + DBG (5, "Medium error: ADF blocked by card\n"); + return SANE_STATUS_JAMMED; + } if (0x10 == ascq) { DBG (5, "Medium error: no ink cartridge\n"); return SANE_STATUS_IO_ERROR; @@ -10092,7 +10167,9 @@ buffer_deskew(struct fujitsu *s, int side) DBG (10, "buffer_deskew: start\n"); /*only find skew on first image from a page, or if first image had error */ - if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->deskew_stat){ + if(s->side == SIDE_FRONT + || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK + || s->deskew_stat){ s->deskew_stat = sanei_magic_findSkew( &s->s_params,s->buffers[side],s->resolution_x,s->resolution_y, |