fujitsu backend v136

- add support for fi-800R
- add support for card scanning slot (Return Path)
- fix bug with reading hardware sensors on first invocation
merge-requests/340/head
m. allan noah 2020-02-07 21:06:50 -05:00
rodzic 03ca64a885
commit 336cbdfd4c
6 zmienionych plików z 134 dodań i 34 usunięć

Wyświetl plik

@ -383,6 +383,9 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define get_IN_op_halt(in) getbitfield(in+0x7a, 1, 7)
#define get_IN_return_path(in) getbitfield(in+0x7c, 1, 7)
#define get_IN_energy_star3(in) getbitfield(in+0x7c, 1, 6)
/* ==================================================================== */
/* page codes used by mode_sense and mode_select */
#define MS_pc_unk 0x2c /* Used by iX500 */
@ -763,6 +766,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define get_GHS_fb_open(in) getbitfield(in+0x03, 1, 3)
#define get_GHS_paper_end(in) getbitfield(in+0x03, 1, 2)
#define get_GHS_fb_on(in) getbitfield(in+0x03, 1, 1)
#define get_GHS_exit(in) getbitfield(in+0x03, 1, 0)
#define get_GHS_sleep(in) getbitfield(in+0x04, 1, 7)
#define get_GHS_clean(in) getbitfield(in+0x04, 1, 6)
@ -823,7 +827,8 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define SCANNER_CONTROL_len 10
#define set_SC_ric(icb, val) setbitfield(icb + 1, 1, 4, val)
#define set_SC_function(icb, val) setbitfield(icb + 1, 0xf, 0, val)
#define set_SC_function_1(icb, val) setbitfield(icb + 1, 0xf, 0, val)
#define set_SC_function_2(icb, val) icb[2] = (val >> 4)
#define SC_function_adf 0x00
#define SC_function_fb 0x01
#define SC_function_fb_hs 0x02
@ -836,6 +841,9 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define SC_function_scan_complete 0x09
#define SC_function_eject_complete 0x0a
#define SC_function_manual_feed 0x0c
#define SC_function_mfeed 0x0f
#define SC_function_continuous 0x1f
#define SC_function_rpath 0x2f
/* used with SC_function_panel */
#define set_SC_led_eb(icb, val) setbitfield(icb + 5, 1, 7, val)

Wyświetl plik

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

Wyświetl plik

@ -255,3 +255,6 @@ usb 0x04c5 0x1522
#ScanSnap iX1500
usb 0x04c5 0x159f
#fi-800R
usb 0x04c5 0x15fc

Wyświetl plik

@ -112,6 +112,7 @@ enum fujitsu_Option
OPT_HOPPER,
OPT_OMR,
OPT_ADF_OPEN,
OPT_CARD_LOADED,
OPT_SLEEP,
OPT_SEND_SW,
OPT_MANUAL_FEED,
@ -277,6 +278,7 @@ struct fujitsu
int has_comp_JPG2;
int has_comp_JPG3;
int has_op_halt;
int has_return_path;
/*FIXME: more endorser data? */
int endorser_type_f;
@ -361,7 +363,7 @@ struct fujitsu
/*mode group*/
SANE_String_Const mode_list[7];
SANE_String_Const source_list[5];
SANE_String_Const source_list[8];
SANE_Int res_list[17];
SANE_Range res_range;
@ -599,6 +601,7 @@ struct fujitsu
int hw_hopper;
int hw_omr;
int hw_adf_open;
int hw_card_loaded;
int hw_sleep;
int hw_send_sw;
@ -618,7 +621,7 @@ struct fujitsu
int hw_density_sw;
/* values which are used to track the frontend's access to sensors */
char hw_read[NUM_OPTIONS-OPT_TOP];
char hw_data_avail[NUM_OPTIONS-OPT_TOP];
};
#define CONNECTION_SCSI 0 /* SCSI interface */
@ -631,6 +634,9 @@ struct fujitsu
#define SOURCE_ADF_FRONT 1
#define SOURCE_ADF_BACK 2
#define SOURCE_ADF_DUPLEX 3
#define SOURCE_CARD_FRONT 4
#define SOURCE_CARD_BACK 5
#define SOURCE_CARD_DUPLEX 6
#define COMP_NONE WD_cmp_NONE
#define COMP_JPEG WD_cmp_JPG1

Wyświetl plik

@ -657,3 +657,9 @@
:status :good
:usbid "0x04c5" "0x159f"
:comment "small, current, WiFi not supported."
:model "fi-800R"
:interface "USB"
:status :good
:usbid "0x04c5" "0x15fc"
:comment "small, current, both feed methods are supported."

Wyświetl plik

@ -1,4 +1,4 @@
.TH sane\-fujitsu 5 "08 Apr 2017" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.TH sane\-fujitsu 5 "07 Feb 2020" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.IX sane\-fujitsu
.SH NAME
@ -10,7 +10,7 @@ The
library implements a SANE (Scanner Access Now Easy) backend which
provides access to most Fujitsu flatbed and ADF scanners.
This document describes backend version 134, which shipped with SANE 1.0.28.
This document describes backend version 136, which shipped with SANE 1.0.30.
.SH SUPPORTED HARDWARE
This version supports every known model which speaks the Fujitsu SCSI and
@ -54,7 +54,7 @@ Effort has been made to expose all hardware options, including:
source s
.RS
Selects the source for the scan. Options
may include "Flatbed", "ADF Front", "ADF Back", "ADF Duplex".
may include "Flatbed", "ADF Front", "ADF Back", "ADF Duplex", "Card Front", "Card Back", "Card Duplex".
.RE
.PP
mode m