#ifndef FUJITSU_H #define FUJITSU_H /* * Part of SANE - Scanner Access Now Easy. * * Please see opening comment in fujitsu.c */ /* ------------------------------------------------------------------------- */ static int num_devices; static struct fujitsu *first_dev; /* ------------------------------------------------------------------------- * This option list has to contain all options for all scanners supported by * this driver. If a certain scanner cannot handle a certain option, there's * still the possibility to say so, later. */ enum fujitsu_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_SOURCE, OPT_MODE, OPT_DUPLEX, OPT_X_RES, OPT_Y_RES, OPT_GEOMETRY_GROUP, OPT_TL_X, /* in mm/2^16 */ OPT_TL_Y, /* in mm/2^16 */ OPT_BR_X, /* in mm/2^16 */ OPT_BR_Y, /* in mm/2^16 */ OPT_PAGE_WIDTH, OPT_PAGE_HEIGHT, OPT_ENHANCEMENT_GROUP, OPT_AVERAGING, OPT_BRIGHTNESS, OPT_THRESHOLD, OPT_CONTRAST, OPT_RIF, OPT_COMPRESSION, OPT_DTC_SELECTION, OPT_GAMMA, OPT_OUTLINE_EXTRACTION, OPT_EMPHASIS, OPT_AUTOSEP, OPT_MIRROR_IMAGE, OPT_VARIANCE_RATE, OPT_THRESHOLD_CURVE, OPT_GRADATION, OPT_SMOOTHING_MODE, OPT_FILTERING, OPT_BACKGROUND, OPT_NOISE_REMOVAL, OPT_MATRIX2X2, OPT_MATRIX3X3, OPT_MATRIX4X4, OPT_MATRIX5X5, OPT_WHITE_LEVEL_FOLLOW, OPT_PAPER_SIZE, OPT_PAPER_WIDTH, OPT_PAPER_HEIGHT, OPT_PAPER_ORIENTATION, OPT_DROPOUT_COLOR, OPT_START_BUTTON, OPT_TUNING_GROUP, OPT_LAMP_COLOR, OPT_BLUE_OFFSET, OPT_GREEN_OFFSET, OPT_USE_SWAPFILE, /* must come last: */ NUM_OPTIONS }; struct fujitsu { struct fujitsu *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; SANE_Device sane; /* Immutable values which are set during initial probing of the scanner. */ /* --------------------------------------------------------------------- */ char vendorName[9]; /* raw data as returned by SCSI inquiry. */ char productName[17]; /* raw data as returned by SCSI inquiry. */ char versionName[5]; /* raw data as returned by SCSI inquiry. */ int model; /* The scanner model. */ char *devicename; /* The name of the scanner device. */ int sfd; /* The scanner device file descriptor. */ int color_raster_offset; /* offset between r and b scan line and */ /* between b and g scan line (4 for all */ /* known models) */ int duplex_raster_offset; /* offset between front and rear page when */ /* when scanning duplex */ int can_read_alternate; /* duplex transfer mode front/back/front/back... */ int adf_present; /* true if an ADF has been detected. */ int duplex_present; /* true if a duplex unit has been detected. */ int ipc_present; /* true if ipc2/3 option detected */ int cmp_present; /* true if cmp2 present */ int has_hw_status; /* true for M409X series */ int has_outline; /* ............ */ int has_emphasis; /* ............ */ int has_autosep; /* ............ */ int has_mirroring; /* ............ */ int has_white_level_follow; /* ............ */ int has_subwindow; /* ............ */ int has_dropout_color; /* */ /* User settable values (usually mirrored in SANE options) */ /* --------------------------------------------------------------------- */ int duplex_mode; /* Use DUPLEX_* constants below */ int resolution_x; /* X resolution in dpi */ int resolution_y; /* Y resolution in dpi */ int resolution_linked; /* When true, Y resolution is set whenever */ /* X resolution gets changed. true initially, */ /* becomes false if Y resolution is ever */ /* set independently */ int top_left_x; /* The desired size of the scan, in */ int top_left_y; /* mm/2^16. Notice that there's a second */ int bottom_right_x; /* group of these with the "rounded" */ int bottom_right_y; /* prefix, below. */ /* A note on the scan are size (topLeft/bottomRight) values. When the * user (the front-end) sets one of these, we change the above values * and immediately calculate from it the scan height and width in * 1/1200 inches (the internal scanner unit). Depending on the scan * mode, depth, etc., other rules may be used to change the value, * e.g. in 1bpp scans, the width is always increased until each scan * line has a full number of bytes. * * The results of these calculations are the "top_margin", "left_margin", * "scan_width", and "scan_height" values below. In addition, these * values are now converted back into SANE units (1/2^16mm) and stored * in roundedTopLeft... and roundedBottomRight... - when the front-end * _sets_ the scan area size, the topLeft... and bottomRight... values * will be set, but when the front-end _gets_ the scan area size, * the rounded values will be returned. * * By keeping the original values instead of rounding them "in place", * we can revise our rounded values later. Assume the resolution is set * to 75dpi, and then the scan size is set - it will be rounded to * the nearest 1/75 inch. Later the resolution is changed to 600dpi, * making a better approximation of the original desired size possible. * * All these calculations are done within the "calculateDerivedValues" * function. */ int page_width; /* paper width and height may influence the */ int page_height; /* way the ADF operates - in 1/1200 inch */ int output_depth; /* How many bits per pixel the user wants. */ int scanner_depth; /* How many bpp the scanner will send. */ /* A note on "depth" values. Many colour scanners require you to use * the value "8" for depth if you're doing colour scans even if they * deliver 24. The front-end, when it calls "sane_get_parameters", will * expect to see the value 8 as well. However, internally, we use * scanner_depth as the real number of bits sent per pixel, which is * obvoiusly 24 for coulour scans. * * output_depth uses the same logic and normally both values would be * identical; however it may be desirable to implement, say, a 4-bit * grayscale mode in the backend even if the scanner only supports * 8-bit grayscale. In that case, the backend would to the reduction * "on the fly", and output_depth would be 4, while scanner_depth is 8. */ int color_mode; /* Color/Gray/..., use MODE_* constants */ int use_adf; /* Whether the ADF should be used or not. */ int use_temp_file; /* Whether to use a temp file for duplex. */ int mirror; /* Whether to mirror scan area for rear side */ int lamp_color; /* lamp color to use for monochrome scans */ int green_offset; /* color tuning - green scan line offset */ int blue_offset; /* color tuning - blue scan line offset */ SANE_Range adf_width_range; SANE_Range adf_height_range; SANE_Range x_range; SANE_Range y_range; SANE_Range x_res_range; SANE_Range y_res_range; SANE_Range x_grey_res_range; SANE_Range y_grey_res_range; SANE_String_Const vpd_mode_list[7]; SANE_String_Const compression_mode_list[9]; SANE_Int x_res_list[17]; /* range of x and y resolution */ SANE_Int y_res_list[17]; /* if scanner has only fixed resolutions */ SANE_Int x_res_list_grey[17]; SANE_Int y_res_list_grey[17]; /* Derived values (calculated by calculateDerivedValues from the above) */ /* --------------------------------------------------------------------- */ int rounded_top_left_x; /* Same as topLeft... and bottomRight..., */ int rounded_top_left_y; /* but "rounded" to the nearest 1/1200 */ int rounded_bottom_right_x; /* value, i.e. these are the values really */ int rounded_bottom_right_y; /* used for scanning. */ int top_margin; /* Top margin in 1/1200 inch */ int left_margin; /* Left margin in 1/1200 inch */ int scan_width; /* Width of scan in 1/1200 inch */ int scan_height; /* Height of scan in 1/1200 inch */ int scan_width_pixels; /* Pixels per scan line for this job */ int scan_height_pixels; /* Number of lines in this job */ int bytes_per_scan_line; /* Number of bytes per line in this job */ /* Operational values (contain internal status information etc.) */ /* --------------------------------------------------------------------- */ int default_pipe; /* Pipe between reader process and backend. */ int duplex_pipe; /* Additional pipe for duplex scans. */ int reader_pid; /* Process ID of the reader process. */ int reverse; /* Whether to reverse the image. Not user */ /* settable but required internally. */ int i_transfer_length; /* needed when the scanner returns */ /* compressed data and size of return data */ /* is unknown in advance */ /* This replaced the former "scanning" flag. object_count represents the * number of objects acquired (or being acquired) by the scanner which * haven't been read. Thus, an object_count of != 0 means the scanner is * busy. If the scanner is scanning the first page, it's 1; if the scanner * is scanning the second page of a duplex scan, it's 2. */ int object_count; /* This is set to "true" by sane_read when it encounters the end of a data * stream. */ int eof; unsigned char *buffer; /* Buffer used for SCSI transfers. */ unsigned int scsi_buf_size; /* Max amount of data in one SCSI call. */ /** these can be set */ int brightness; int threshold; int contrast; int rif; int bitorder; int compress_type; int compress_arg; int vendor_id_code; int gamma; int outline; int emphasis; int auto_sep; int mirroring; int var_rate_dyn_thresh; int white_level_follow; int gradation; int smoothing_mode; int filtering; int background; int matrix2x2; int matrix3x3; int matrix4x4; int matrix5x5; int noise_removal; int paper_orientation; int paper_selection; int paper_size; int dtc_threshold_curve; int dtc_selection; int subwindow_list; /***** end of "set window" terms *****/ int dropout_color; }; /** scan only front page */ #define DUPLEX_FRONT 1 /** scan only reverse page */ #define DUPLEX_BACK 2 /** scan both sides and return them in two different image acquisition operations */ #define DUPLEX_BOTH 3 #define MODEL_FORCE 0 /** Fujitsu M3091DCd (300x600dpi, color, duplex, ADF-only) */ #define MODEL_3091 1 /** Fujitsu M3096 (400x400dpi grayscale, simplex, FB and optional ADF) */ #define MODEL_3096 2 /** Fujitsu ScanPartner 15C (....) */ #define MODEL_SP15 3 /** 3093 */ #define MODEL_3093 4 /** 4097 */ #define MODEL_4097 5 /** fi-???? */ #define MODEL_FI 6 /* A note regarding the MODEL... constants. There's a place in * identifyScanner() where the INQUIRY data is parsed and the model * set accordingly. Now while there is, for example, only one 3091 * model (called M3091DCd), there may be different sub-models (e.g. * the 1000abc and the 1000xyz). * * It is suggested that a new MODEL... type be introduced for these if * there are significant differences in capability that have to be * treated differently in the backend. For example, if the "abc" model * has an optional ADF and the "xyz" model has the ADF built-in, we * don't need to distinguish these models, and it's sufficient to set * the "adf_present" variable accordingly. * * The same would apply if two sub-models behave in the same way but * one of them is faster, or has some exotic extra capability that we * don't support anyway. * * If, on the other hand, one model supports a different resolution, * page size, different scan parameters and modes, and such, then it's * probably necessary to create a new MODEL... constant. * * It may also be feasible to introduce a "subModel" member in the * structure above for those cases where subtle, but important, * differences exist - e.g. one model is 100% the same as another but * supports twice the resolution. */ /** Black-and-White (Line Art) - depth always 1 */ #define MODE_LINEART 1 /** Black-and-White (Halftone) - depth always 1 */ #define MODE_HALFTONE 2 /** Grayscale */ #define MODE_GRAYSCALE 3 /** RGB Color */ #define MODE_COLOR 4 /** Binary RGB Color*/ #define MODE_BIN_COLOR 5 /** half-tones RGB Color*/ #define MODE_HALFTONE_COLOR 6 /* ------------------------------------------------------------------------- */ #define MM_PER_INCH 25.4 #define length_quant SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) #define mmToIlu(mm) ((mm) / length_quant) #define iluToMm(ilu) ((ilu) * length_quant) #define FUJITSU_CONFIG_FILE "fujitsu.conf" #define FIXED_MM_TO_SCANNER_UNIT(number) SANE_UNFIX(number) * 1200 / MM_PER_INCH #define SCANNER_UNIT_TO_FIXED_MM(number) SANE_FIX(number * MM_PER_INCH / 1200) #ifndef PATH_MAX # define PATH_MAX 1024 #endif #ifndef PATH_SEP #ifdef HAVE_OS2_H # define PATH_SEP '\\' #else # define PATH_SEP '/' #endif #endif /* ------------------------------------------------------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle); SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking); SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp); const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); SANE_Status sane_start (SANE_Handle handle); SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); void sane_cancel (SANE_Handle h); void sane_close (SANE_Handle h); void sane_exit (void); /* ------------------------------------------------------------------------- */ static void doInquiry (struct fujitsu *s); static SANE_Status attachScanner (const char *devicename, struct fujitsu **devp); static SANE_Status senseHandler (int scsi_fd, u_char * result, void *arg); static int identifyScanner (struct fujitsu *s); static void doInquiry (struct fujitsu *s); static int do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len, unsigned char *out, size_t out_len); static void hexdump (int level, char *comment, unsigned char *p, int l); static SANE_Status initOptions (struct fujitsu *scanner); static int grabScanner (struct fujitsu *s); static int freeScanner (struct fujitsu *s); static int waitScanner (struct fujitsu *s); static int objectPosition (struct fujitsu *s); static SANE_Status doCancel (struct fujitsu *scanner); static int objectDischarge (struct fujitsu *s); static int set_mode_params (struct fujitsu *s); static int setWindowParam (struct fujitsu *s); static size_t maxStringSize (const SANE_String_Const strings[]); static int startScan (struct fujitsu *s); static int reader_process (struct fujitsu *scanner, int fd1, int fd2); static unsigned int reader3091ColorDuplex (struct fujitsu *scanner, FILE * fd, FILE * fd2); static unsigned int reader3091ColorSimplex (struct fujitsu *scanner, FILE * fd); static unsigned int reader3091GrayDuplex (struct fujitsu *scanner, FILE * fd, FILE * fd2); static unsigned int reader_gray_duplex_sequential (struct fujitsu *scanner, FILE * fd, FILE * fd2); static unsigned int reader_gray_duplex_alternate (struct fujitsu *scanner, FILE * fd, FILE * fd2); static unsigned int readerGenericPassthrough (struct fujitsu *scanner, FILE * fd, int i_window_id); static int read_large_data_block (struct fujitsu *s, unsigned char *buffer, unsigned int length, int i_window_id); static SANE_Status attachOne (const char *name); static int modelMatch (const char *product); static void setDefaults3091 (struct fujitsu *scanner); static void setDefaults3096 (struct fujitsu *scanner); static void setDefaultsSP15 (struct fujitsu *scanner); static SANE_Status setMode3091 (struct fujitsu *scanner, int mode); static SANE_Status setMode3096 (struct fujitsu *scanner, int mode); static SANE_Status setModeSP15 (struct fujitsu *scanner, int mode); static void calculateDerivedValues (struct fujitsu *scanner); static int makeTempFile (void); static SANE_Status getHardwareStatus (struct fujitsu *s); static void fujitsu_set_standard_size (SANE_Handle handle); #endif /* FUJITSU_H */