1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci This file is part of the SANE package, and implements a SANE backend 4141cc406Sopenharmony_ci for various Fujitsu scanners. 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci Copyright (C) 2000 Randolph Bentson 7141cc406Sopenharmony_ci Copyright (C) 2001 Frederik Ramm 8141cc406Sopenharmony_ci Copyright (C) 2001-2004 Oliver Schirrmeister 9141cc406Sopenharmony_ci Copyright (C) 2003-2022 m. allan noah 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci JPEG output and low memory usage support funded by: 12141cc406Sopenharmony_ci Archivista GmbH, www.archivista.ch 13141cc406Sopenharmony_ci Endorser support funded by: 14141cc406Sopenharmony_ci O A S Oilfield Accounting Service Ltd, www.oas.ca 15141cc406Sopenharmony_ci Automatic length detection support funded by: 16141cc406Sopenharmony_ci Martin G. Miller, mgmiller at optonline.net 17141cc406Sopenharmony_ci Software image enhancement routines and recent scanner support funded by: 18141cc406Sopenharmony_ci PFU America, Inc., fujitsuscanners.com 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci -------------------------------------------------------------------------- 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 23141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 24141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 25141cc406Sopenharmony_ci License, or (at your option) any later version. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 28141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 29141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30141cc406Sopenharmony_ci General Public License for more details. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 33141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 36141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 39141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 40141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 41141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 42141cc406Sopenharmony_ci account of linking the SANE library code into it. 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 45141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 46141cc406Sopenharmony_ci License. 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 49141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 50141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 53141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 54141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci -------------------------------------------------------------------------- 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci The source code is divided in sections which you can easily find by 59141cc406Sopenharmony_ci searching for the tag "@@". 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci Section 1 - Boilerplate: Init & static stuff 62141cc406Sopenharmony_ci Section 2 - Init: sane_init, _get_devices, _open ... 63141cc406Sopenharmony_ci Section 3 - Options: sane_*_option functions 64141cc406Sopenharmony_ci Section 4 - Scanning: sane_start, _get_param, _read ... 65141cc406Sopenharmony_ci Section 5 - Cleanup: sane_cancel, ... 66141cc406Sopenharmony_ci Section 6 - Misc: sense_handler, hexdump, ... 67141cc406Sopenharmony_ci Section 7 - Image processing: deskew, crop, despeck 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci Changes: 70141cc406Sopenharmony_ci v1, 2002-05-05, OS 71141cc406Sopenharmony_ci - release memory allocated by sane_get_devices 72141cc406Sopenharmony_ci - several bugfixes 73141cc406Sopenharmony_ci - supports the M3097 74141cc406Sopenharmony_ci - get threshold, contrast and brightness from vpd 75141cc406Sopenharmony_ci - imprinter support 76141cc406Sopenharmony_ci - get_hardware_status now works before calling sane_start 77141cc406Sopenharmony_ci - avoid unnecessary reload of options when using source=fb 78141cc406Sopenharmony_ci v2, 2002-08-08, OS 79141cc406Sopenharmony_ci - bugfix. Imprinter didn't print the first time after 80141cc406Sopenharmony_ci switching on the scanner 81141cc406Sopenharmony_ci - bugfix. reader_generic_passthrough ignored the number of bytes 82141cc406Sopenharmony_ci returned by the scanner 83141cc406Sopenharmony_ci v3, 2002-09-13, OS 84141cc406Sopenharmony_ci - 3092 support (mgoppold a t tbz-pariv.de) 85141cc406Sopenharmony_ci - tested 4097 support 86141cc406Sopenharmony_ci - changed some functions to receive compressed data 87141cc406Sopenharmony_ci v4, 2003-02-13, OS 88141cc406Sopenharmony_ci - fi-4220C support (ron a t roncemer.com) 89141cc406Sopenharmony_ci - SCSI over USB support (ron a t roncemer.com) 90141cc406Sopenharmony_ci v5, 2003-02-20, OS 91141cc406Sopenharmony_ci - set availability of options THRESHOLD und VARIANCE 92141cc406Sopenharmony_ci - option RIF is available for 3091 and 3092 93141cc406Sopenharmony_ci v6, 2003-03-04, OS 94141cc406Sopenharmony_ci - renamed some variables 95141cc406Sopenharmony_ci - bugfix: duplex scanning now works when disconnect is enabled 96141cc406Sopenharmony_ci v7, 2003-03-10, OS 97141cc406Sopenharmony_ci - displays the offending byte in the window descriptor block 98141cc406Sopenharmony_ci v8, 2003-03-28, OS 99141cc406Sopenharmony_ci - fi-4120C support, MAN 100141cc406Sopenharmony_ci - display information about gamma in vital_product_data 101141cc406Sopenharmony_ci v9 2003-06-04, MAN 102141cc406Sopenharmony_ci - separated the 4120 and 4220 into another model 103141cc406Sopenharmony_ci - color support for the 4x20 104141cc406Sopenharmony_ci v10 2003-06-04, MAN 105141cc406Sopenharmony_ci - removed SP15 code 106141cc406Sopenharmony_ci - sane_open actually opens the device you request 107141cc406Sopenharmony_ci v11 2003-06-11, MAN 108141cc406Sopenharmony_ci - fixed bug in that code when a scanner is disconnected 109141cc406Sopenharmony_ci v12 2003-10-06, MAN 110141cc406Sopenharmony_ci - added code to support color modes of more recent scanners 111141cc406Sopenharmony_ci v13 2003-11-07, OS 112141cc406Sopenharmony_ci - Bugfix. If a scanner returned a color image 113141cc406Sopenharmony_ci in format rr...r gg...g bb...b the reader process crashed 114141cc406Sopenharmony_ci - Bugfix. Disable option gamma was for the fi-4120 115141cc406Sopenharmony_ci v14 2003-12-15, OS 116141cc406Sopenharmony_ci - Bugfix: set default threshold range to 0..255 There is a problem 117141cc406Sopenharmony_ci with the M3093 when you are not allows to set the threshold to 0 118141cc406Sopenharmony_ci - Bugfix: set the allowable x- and y-DPI values from VPD. Scanning 119141cc406Sopenharmony_ci with x=100 and y=100 dpi with an fi4120 resulted in an image 120141cc406Sopenharmony_ci with 100,75 dpi 121141cc406Sopenharmony_ci - Bugfix: Set the default value of gamma to 0x80 for all scanners 122141cc406Sopenharmony_ci that don't have built in gamma patterns 123141cc406Sopenharmony_ci - Bugfix: fi-4530 and fi-4210 don't support standard paper size 124141cc406Sopenharmony_ci v15 2003-12-16, OS 125141cc406Sopenharmony_ci - Bugfix: pagewidth and pageheight were disabled for the fi-4530C 126141cc406Sopenharmony_ci v16 2004-02-20, OS 127141cc406Sopenharmony_ci - merged the 3092-routines with the 3091-routines 128141cc406Sopenharmony_ci - inverted the image in mode color and grayscale 129141cc406Sopenharmony_ci - jpg hardware compression support (fi-4530C) 130141cc406Sopenharmony_ci v17 2004-03-04, OS 131141cc406Sopenharmony_ci - enabled option dropoutcolor for the fi-4530C, and fi-4x20C 132141cc406Sopenharmony_ci v18 2004-06-02, OS 133141cc406Sopenharmony_ci - bugfix: can read duplex color now 134141cc406Sopenharmony_ci v19 2004-06-28, MAN 135141cc406Sopenharmony_ci - 4220 use model code not strcmp (stan a t saticed.me.uk) 136141cc406Sopenharmony_ci v20 2004-08-24, OS 137141cc406Sopenharmony_ci - bugfix: 3091 did not work since 15.12.2003 138141cc406Sopenharmony_ci - M4099 supported (bw only) 139141cc406Sopenharmony_ci v21 2006-05-01, MAN 140141cc406Sopenharmony_ci - Complete rewrite, half code size 141141cc406Sopenharmony_ci - better (read: correct) usb command support 142141cc406Sopenharmony_ci - basic support for most fi-series 143141cc406Sopenharmony_ci - most scanner capabilities read from VPD 144141cc406Sopenharmony_ci - reduced model-specific code 145141cc406Sopenharmony_ci - improved scanner detection/initialization 146141cc406Sopenharmony_ci - improved SANE_Option handling 147141cc406Sopenharmony_ci - basic button support 148141cc406Sopenharmony_ci - all IPC and Imprinter options removed temporarily 149141cc406Sopenharmony_ci - duplex broken temporarily 150141cc406Sopenharmony_ci v22 2006-05-04, MAN 151141cc406Sopenharmony_ci - do_scsi_cmd gets basic looping capability 152141cc406Sopenharmony_ci - reverse now divided by mode 153141cc406Sopenharmony_ci - re-write sane_fix/unfix value handling 154141cc406Sopenharmony_ci - fix several bugs in options code 155141cc406Sopenharmony_ci - some options' ranges modified by other options vals 156141cc406Sopenharmony_ci - added advanced read-only options for all 157141cc406Sopenharmony_ci known hardware sensors and buttons 158141cc406Sopenharmony_ci - rewrote hw status function 159141cc406Sopenharmony_ci - initial testing with M3091dc- color mode broken 160141cc406Sopenharmony_ci v23 2006-05-14, MAN 161141cc406Sopenharmony_ci - initial attempt to recover duplex mode 162141cc406Sopenharmony_ci - fix bad usb prodID when config file missing 163141cc406Sopenharmony_ci v24 2006-05-17, MAN 164141cc406Sopenharmony_ci - sane_read must set len=0 when return != good 165141cc406Sopenharmony_ci - simplify do_cmd() calls by removing timeouts 166141cc406Sopenharmony_ci - lengthen most timeouts, shorten those for wait_scanner() 167141cc406Sopenharmony_ci v25 2006-05-19, MAN 168141cc406Sopenharmony_ci - rename scsi-buffer-size to buffer-size, usb uses it too 169141cc406Sopenharmony_ci - default buffer-size increased to 64k 170141cc406Sopenharmony_ci - use sanei_scsi_open_extended() to set buffer size 171141cc406Sopenharmony_ci - fix some compiler warns: 32&64 bit gcc 172141cc406Sopenharmony_ci v26 2006-05-23, MAN 173141cc406Sopenharmony_ci - don't send scanner control (F1) if unsupported 174141cc406Sopenharmony_ci v27 2006-05-30, MAN 175141cc406Sopenharmony_ci - speed up hexdump (adeuring A T gmx D O T net) 176141cc406Sopenharmony_ci - duplex request same size block from both sides 177141cc406Sopenharmony_ci - don't #include or call sanei_thread 178141cc406Sopenharmony_ci - split usb/scsi command DBG into 25 and 30 179141cc406Sopenharmony_ci v28 2006-06-01, MAN 180141cc406Sopenharmony_ci - sane_read() usleep if scanner is busy 181141cc406Sopenharmony_ci - do_*_cmd() no looping (only one caller used it), 182141cc406Sopenharmony_ci remove unneeded casts, cleanup/add error messages 183141cc406Sopenharmony_ci - scanner_control() look at correct has_cmd_* var, 184141cc406Sopenharmony_ci handles own looping on busy 185141cc406Sopenharmony_ci v29 2006-06-04, MAN 186141cc406Sopenharmony_ci - M3091/2 Color mode support (duplex still broken) 187141cc406Sopenharmony_ci - all sensors option names start with 'button-' 188141cc406Sopenharmony_ci - rewrite sane_read and helpers to use buffers, 189141cc406Sopenharmony_ci currently an extreme waste of ram, but should 190141cc406Sopenharmony_ci work with saned and scanimage -T 191141cc406Sopenharmony_ci - merge color conversion funcs into read_from_buf() 192141cc406Sopenharmony_ci - compare bytes tx v/s rx instead of storing EOFs 193141cc406Sopenharmony_ci - remove scanner cmd buf, use buf per func instead 194141cc406Sopenharmony_ci - print color and duplex raster offsets (inquiry) 195141cc406Sopenharmony_ci - print EOM, ILI, and info bytes (request sense) 196141cc406Sopenharmony_ci v30 2006-06-06, MAN 197141cc406Sopenharmony_ci - M3091/2 duplex support, color/gray/ht/lineart ok 198141cc406Sopenharmony_ci - sane_read helpers share code, report more errors 199141cc406Sopenharmony_ci - add error msg if VPD missing or non-extended 200141cc406Sopenharmony_ci - remove references to color_lineart and ht units 201141cc406Sopenharmony_ci - rework init_model to support more known models 202141cc406Sopenharmony_ci - don't send paper size data if using flatbed 203141cc406Sopenharmony_ci v31 2006-06-13, MAN 204141cc406Sopenharmony_ci - add 5220C usb id 205141cc406Sopenharmony_ci - don't show ink level buttons if no imprinter 206141cc406Sopenharmony_ci - run ghs/rs every second instead of every other 207141cc406Sopenharmony_ci v32 2006-06-14, MAN 208141cc406Sopenharmony_ci - add 4220C2 usb id 209141cc406Sopenharmony_ci v33 2006-06-14, MAN (SANE v1.0.18) 210141cc406Sopenharmony_ci - add Fi-5900 usb id and init_model section 211141cc406Sopenharmony_ci v34 2006-07-04, MAN 212141cc406Sopenharmony_ci - add S500 usb id 213141cc406Sopenharmony_ci - gather more data from inq and vpd 214141cc406Sopenharmony_ci - allow background color setting 215141cc406Sopenharmony_ci v35 2006-07-05, MAN 216141cc406Sopenharmony_ci - allow double feed sensor settings 217141cc406Sopenharmony_ci - more consistent naming of global strings 218141cc406Sopenharmony_ci v36 2006-07-06, MAN 219141cc406Sopenharmony_ci - deal with fi-5900 even bytes problem 220141cc406Sopenharmony_ci - less verbose calculateDerivedValues() 221141cc406Sopenharmony_ci v37 2006-07-14, MAN 222141cc406Sopenharmony_ci - mode sense command support 223141cc406Sopenharmony_ci - detect mode page codes instead of hardcoding 224141cc406Sopenharmony_ci - send command support 225141cc406Sopenharmony_ci - brightness/contrast support via LUT 226141cc406Sopenharmony_ci - merge global mode page buffers 227141cc406Sopenharmony_ci v38 2006-07-15, MAN 228141cc406Sopenharmony_ci - add 'useless noise' debug level (35) 229141cc406Sopenharmony_ci - move mode sense probe errors to DBG 35 230141cc406Sopenharmony_ci v39 2006-07-17, MAN 231141cc406Sopenharmony_ci - rewrite contrast slope math for readability 232141cc406Sopenharmony_ci v40 2006-08-26, MAN 233141cc406Sopenharmony_ci - rewrite brightness/contrast more like xsane 234141cc406Sopenharmony_ci - initial gamma support 235141cc406Sopenharmony_ci - add fi-5530 usb id 236141cc406Sopenharmony_ci - rewrite do_*_cmd functions to handle short reads 237141cc406Sopenharmony_ci and to use ptr to return read in length 238141cc406Sopenharmony_ci - new init_user function split from init_model 239141cc406Sopenharmony_ci - init_vpd allows short vpd block for older models 240141cc406Sopenharmony_ci - support MS buffer (s.scipioni AT harvardgroup DOT it) 241141cc406Sopenharmony_ci - support MS prepick 242141cc406Sopenharmony_ci - read only 1 byte of mode sense output 243141cc406Sopenharmony_ci v41 2006-08-28, MAN 244141cc406Sopenharmony_ci - do_usb_cmd() returns io error on cmd/out/status/rs EOF 245141cc406Sopenharmony_ci - fix bug in MS buffer/prepick scsi data block 246141cc406Sopenharmony_ci v42 2006-08-31, MAN 247141cc406Sopenharmony_ci - fix bug in get_hardware_status (#303798) 248141cc406Sopenharmony_ci v43 2006-09-19, MAN 249141cc406Sopenharmony_ci - add model-specific code to init_vpd for M3099 250141cc406Sopenharmony_ci v44 2007-01-26, MAN 251141cc406Sopenharmony_ci - set SANE_CAP_HARD_SELECT on all buttons/sensors 252141cc406Sopenharmony_ci - disable sending gamma LUT, seems wrong on some units? 253141cc406Sopenharmony_ci - support MS overscan 254141cc406Sopenharmony_ci - clamp the scan area to the pagesize on ADF 255141cc406Sopenharmony_ci v45 2007-01-28, MAN 256141cc406Sopenharmony_ci - update overscan code to extend max scan area 257141cc406Sopenharmony_ci v46 2007-03-08, MAN 258141cc406Sopenharmony_ci - tweak fi-4x20c2 and M3093 settings 259141cc406Sopenharmony_ci - add fi-5110EOXM usb id 260141cc406Sopenharmony_ci - add M3093 non-alternating duplex code 261141cc406Sopenharmony_ci v47 2007-04-13, MAN 262141cc406Sopenharmony_ci - change window_gamma determination 263141cc406Sopenharmony_ci - add fi-5650C usb id and color mode 264141cc406Sopenharmony_ci v48 2007-04-16, MAN 265141cc406Sopenharmony_ci - re-enable brightness/contrast for built-in models 266141cc406Sopenharmony_ci v49 2007-06-28, MAN 267141cc406Sopenharmony_ci - add fi-5750C usb id and color mode 268141cc406Sopenharmony_ci v50 2007-07-10, MAN 269141cc406Sopenharmony_ci - updated overscan and bgcolor option descriptions 270141cc406Sopenharmony_ci - added jpeg output support 271141cc406Sopenharmony_ci - restructured usb reading code to use RS len for short reads 272141cc406Sopenharmony_ci - combined calcDerivedValues with sane_get_params 273141cc406Sopenharmony_ci v51 2007-07-26, MAN 274141cc406Sopenharmony_ci - fix bug in jpeg output support 275141cc406Sopenharmony_ci v52 2007-07-27, MAN 276141cc406Sopenharmony_ci - remove unused jpeg function 277141cc406Sopenharmony_ci - reactivate look-up-table based brightness and contrast options 278141cc406Sopenharmony_ci - change range of hardware brightness/contrast to match LUT versions 279141cc406Sopenharmony_ci - call send_lut() from sane_control_option instead of sane_start 280141cc406Sopenharmony_ci v53 2007-11-18, MAN 281141cc406Sopenharmony_ci - add S510 usb id 282141cc406Sopenharmony_ci - OPT_NUM_OPTS type is SANE_TYPE_INT (jblache) 283141cc406Sopenharmony_ci v54 2007-12-29, MAN 284141cc406Sopenharmony_ci - disable SANE_FRAME_JPEG support until SANE 1.1.0 285141cc406Sopenharmony_ci v55 2007-12-29, MAN (SANE v1.0.19) 286141cc406Sopenharmony_ci - add S500M usb id 287141cc406Sopenharmony_ci v56 2008-02-14, MAN 288141cc406Sopenharmony_ci - sanei_config_read has already cleaned string (#310597) 289141cc406Sopenharmony_ci v57 2008-02-24, MAN 290141cc406Sopenharmony_ci - fi-5900 does not (initially) interlace colors 291141cc406Sopenharmony_ci - add mode sense for color interlacing? (page code 32) 292141cc406Sopenharmony_ci - more debug output in init_ms() 293141cc406Sopenharmony_ci v58 2008-04-19, MAN 294141cc406Sopenharmony_ci - page code 32 is not color interlacing, rename to 'unknown' 295141cc406Sopenharmony_ci - increase number of bytes in response buffer of init_ms() 296141cc406Sopenharmony_ci - protect debug modification code in init_ms() if NDEBUG is set 297141cc406Sopenharmony_ci - proper async sane_cancel support 298141cc406Sopenharmony_ci - re-enable JPEG support 299141cc406Sopenharmony_ci - replace s->img_count with s->side 300141cc406Sopenharmony_ci - sane_get_parameters(): don't round up larger than current paper size 301141cc406Sopenharmony_ci - sane_start() rewritten, shorter, more clear 302141cc406Sopenharmony_ci - return values are SANE_Status, not int 303141cc406Sopenharmony_ci - hide unused functions 304141cc406Sopenharmony_ci v59 2008-04-22, MAN 305141cc406Sopenharmony_ci - add fi-6140 usb ID, and fi-6x40 color mode 306141cc406Sopenharmony_ci v60 2008-04-27, MAN 307141cc406Sopenharmony_ci - move call to sanei_usb_init() from sane_init() to find_scanners 308141cc406Sopenharmony_ci - free sane_devArray before calloc'ing a new one 309141cc406Sopenharmony_ci v61 2008-05-11, MAN 310141cc406Sopenharmony_ci - minor cleanups to init_ms() 311141cc406Sopenharmony_ci - add fi-5530C2 usb id 312141cc406Sopenharmony_ci - merge find_scanners into sane_get_devices 313141cc406Sopenharmony_ci - inspect correct bool to enable prepick mode option 314141cc406Sopenharmony_ci v62 2008-05-20, MAN 315141cc406Sopenharmony_ci - check for all supported scsi commands 316141cc406Sopenharmony_ci - use well-known option group strings from saneopts.h 317141cc406Sopenharmony_ci - rename pagewidth to page-width, to meet sane 1.1.0, same for height 318141cc406Sopenharmony_ci - add unused get_window() 319141cc406Sopenharmony_ci v63 2008-05-21, MAN 320141cc406Sopenharmony_ci - use sane 1.1.0 well-known option names for some buttons 321141cc406Sopenharmony_ci - remove 'button-' from other buttons and sensors 322141cc406Sopenharmony_ci v64 2008-05-28, MAN 323141cc406Sopenharmony_ci - strcpy device_name[] instead of strdup/free *device_name 324141cc406Sopenharmony_ci - add send/read diag commands to get scanner serial number 325141cc406Sopenharmony_ci - use model and serial to build sane.name (idea from Ryan Duryea) 326141cc406Sopenharmony_ci - allow both serial_name and device_name to sane_open scanner 327141cc406Sopenharmony_ci - correct mode select/sense 6 vs 10 booleans 328141cc406Sopenharmony_ci - rename product_name to model_name 329141cc406Sopenharmony_ci - simulate missing VPD data for M3097G 330141cc406Sopenharmony_ci - hide get_window 331141cc406Sopenharmony_ci - improve handling of vendor unique section of set_window 332141cc406Sopenharmony_ci - add init_interlace to detect proper color mode without hardcoding 333141cc406Sopenharmony_ci - add ascii output to hexdump 334141cc406Sopenharmony_ci v65 2008-06-24, MAN 335141cc406Sopenharmony_ci - detect endorser type during init_inquiry() 336141cc406Sopenharmony_ci - add endorser options 337141cc406Sopenharmony_ci - add send_endorser() and call from sane_control_option() 338141cc406Sopenharmony_ci - add endorser() and call from sane_start() 339141cc406Sopenharmony_ci - convert set_window() to use local cmd and payload copies 340141cc406Sopenharmony_ci - remove get_window() 341141cc406Sopenharmony_ci - mode_select_buff() now clears the buffer, and called in sane_close() 342141cc406Sopenharmony_ci - fi-4990 quirks added, including modified even_scan_line code 343141cc406Sopenharmony_ci v66 2008-06-26, MAN 344141cc406Sopenharmony_ci - restructure double feed detection options for finer-grained control 345141cc406Sopenharmony_ci - add endorser side option 346141cc406Sopenharmony_ci - prevent init_interlace() from overriding init_model() 347141cc406Sopenharmony_ci - simplify sane_start() and fix interlaced duplex jpeg support 348141cc406Sopenharmony_ci - simplify sane_read() and add non-interlaced duplex jpeg support 349141cc406Sopenharmony_ci - removed unused code 350141cc406Sopenharmony_ci v67 2008-07-01, MAN 351141cc406Sopenharmony_ci - add IPC/DTC/SDTC options 352141cc406Sopenharmony_ci - call check_for_cancel() in sane_cancel, unless s->reader flag is set 353141cc406Sopenharmony_ci v68 2008-07-02, MAN 354141cc406Sopenharmony_ci - add halftone type and pattern options 355141cc406Sopenharmony_ci - support M3097G with IPC and CMP options via modified VPD response 356141cc406Sopenharmony_ci v69 2008-07-03, MAN 357141cc406Sopenharmony_ci - support hot-unplugging scanners 358141cc406Sopenharmony_ci v70 2008-07-05, MAN 359141cc406Sopenharmony_ci - fix bug in sane_get_parameters (failed to copy values) 360141cc406Sopenharmony_ci - autodetect jpeg duplex interlacing mode by inspecting scan width 361141cc406Sopenharmony_ci v71 2008-07-13, MAN 362141cc406Sopenharmony_ci - disable overscan option if vpd does not tell overscan size 363141cc406Sopenharmony_ci - fi-5110EOX crops scan area based on absolute maximum, not paper 364141cc406Sopenharmony_ci - fi-5530C/2 and fi-5650C can't handle 10 bit LUT via USB 365141cc406Sopenharmony_ci - fi-5900 has background color, though it reports otherwise 366141cc406Sopenharmony_ci v72 2008-07-13, MAN 367141cc406Sopenharmony_ci - use mode_sense to determine background color support 368141cc406Sopenharmony_ci - remove fi-5900 background color override 369141cc406Sopenharmony_ci v73 2008-07-14, MAN 370141cc406Sopenharmony_ci - correct overscan dimension calculation 371141cc406Sopenharmony_ci - provide correct overscan size overrides for fi-5110C and fi-4x20C2 372141cc406Sopenharmony_ci - add fi-6130 usb ID 373141cc406Sopenharmony_ci - fi-5750C can't handle 10 bit LUT via USB 374141cc406Sopenharmony_ci v74 2008-08-02, MAN 375141cc406Sopenharmony_ci - replace global scsi blocks with local ones in each function 376141cc406Sopenharmony_ci v75 2008-08-07, ReneR 377141cc406Sopenharmony_ci - added fi-6230 usb ID 378141cc406Sopenharmony_ci v76 2008-08-13, MAN 379141cc406Sopenharmony_ci - add independent maximum area values for flatbed 380141cc406Sopenharmony_ci - override said values for fi-4220C, fi-4220C2 and fi-5220C 381141cc406Sopenharmony_ci v77 2008-08-26, MAN 382141cc406Sopenharmony_ci - override flatbed maximum area for fi-6230C and fi-6240C 383141cc406Sopenharmony_ci - set PF bit in all mode_select(6) CDB's 384141cc406Sopenharmony_ci - set SANE_CAP_INACTIVE on all disabled options 385141cc406Sopenharmony_ci - fix bug in mode_select page for sleep timer 386141cc406Sopenharmony_ci v78 2008-08-26, MAN 387141cc406Sopenharmony_ci - recent model names (fi-6xxx) don't end in 'C' 388141cc406Sopenharmony_ci - simplify flatbed area overrides 389141cc406Sopenharmony_ci - call scanner_control to change source during sane_start 390141cc406Sopenharmony_ci v79 2008-10-01, MAN 391141cc406Sopenharmony_ci - add usb ids for several models 392141cc406Sopenharmony_ci - print additional hardware capability bits 393141cc406Sopenharmony_ci - detect front-side endorser 394141cc406Sopenharmony_ci - disable endorser-side controls if only one side installed 395141cc406Sopenharmony_ci - add quirks for fi-6x70 396141cc406Sopenharmony_ci v80 2008-10-08, MAN 397141cc406Sopenharmony_ci - front-side endorser uses data ID 0x80 398141cc406Sopenharmony_ci v81 2008-10-20, MAN 399141cc406Sopenharmony_ci - increase USB timeouts 400141cc406Sopenharmony_ci - enable get_pixelsize() to update scan params after set_window() 401141cc406Sopenharmony_ci - remove even_scan_line hack 402141cc406Sopenharmony_ci v82 2008-10-31, MAN 403141cc406Sopenharmony_ci - improved front-side endorser vpd detection 404141cc406Sopenharmony_ci - send scanner_control_ric during sane_read of each side 405141cc406Sopenharmony_ci - add fi-6770A and fi-6670A USB ID's 406141cc406Sopenharmony_ci v83 2008-11-06, MAN 407141cc406Sopenharmony_ci - round binary bpl and Bpl up to byte boundary 408141cc406Sopenharmony_ci - use s->params instead of user data in set_window() 409141cc406Sopenharmony_ci - read_from_scanner() only grabs an even number of lines 410141cc406Sopenharmony_ci v84 2008-11-07, MAN 411141cc406Sopenharmony_ci - round lines down to even number to get even # of total bytes 412141cc406Sopenharmony_ci - round binary bpl and Bpl down to byte boundary 413141cc406Sopenharmony_ci v85 2008-12-10, MAN 414141cc406Sopenharmony_ci - round pixels_per_line down to arbitrary limits for fi-4990 & fi-4860 415141cc406Sopenharmony_ci - fi-4860 returns random garbage to serial number queries 416141cc406Sopenharmony_ci - initialize *info to 0 in sane_control_option() 417141cc406Sopenharmony_ci v86 2008-12-18, MAN 418141cc406Sopenharmony_ci - get_pixelsize() sets back window ID for back side scans 419141cc406Sopenharmony_ci v87 2008-12-21, MAN 420141cc406Sopenharmony_ci - accept null pointer as empty device name 421141cc406Sopenharmony_ci - track frontend reading sensor/button values to reload 422141cc406Sopenharmony_ci - deactivate double feed options if df-action == default 423141cc406Sopenharmony_ci v88 2009-01-21, MAN 424141cc406Sopenharmony_ci - don't export private symbols 425141cc406Sopenharmony_ci v89 2009-02-20, MAN 426141cc406Sopenharmony_ci - fi-4750 returns random garbage to serial number queries 427141cc406Sopenharmony_ci v90 2009-02-23, MAN 428141cc406Sopenharmony_ci - added ScanSnap S510M usb ids 429141cc406Sopenharmony_ci v91 2009-03-20, MAN 430141cc406Sopenharmony_ci - remove unused temp file code 431141cc406Sopenharmony_ci v92 2009-04-12, MAN 432141cc406Sopenharmony_ci - disable SANE_FRAME_JPEG support (again) 433141cc406Sopenharmony_ci v93 2009-04-14, MAN (SANE 1.0.20) 434141cc406Sopenharmony_ci - return cmd status for reads on sensors 435141cc406Sopenharmony_ci - ignore errors in scanner_control(), 436141cc406Sopenharmony_ci M3091 has not worked since sane 1.0.19, due to this. 437141cc406Sopenharmony_ci - copy_buffer needs to count lines, or M309[12] cannot duplex 438141cc406Sopenharmony_ci v94 2009-05-22, MAN 439141cc406Sopenharmony_ci - add side option to show which duplex image is being transferred 440141cc406Sopenharmony_ci - convert front and simplex buffers to use much less ram 441141cc406Sopenharmony_ci - add lowmemory option which makes duplex back buffer small too 442141cc406Sopenharmony_ci - refactor image handling code to track eof's instead of lengths 443141cc406Sopenharmony_ci - do color deinterlacing after reading from scanner, before buffering 444141cc406Sopenharmony_ci v95 2009-06-02, MAN 445141cc406Sopenharmony_ci - scanner_control_ric should return a subset of the possible errors 446141cc406Sopenharmony_ci v96 2009-08-07, MAN 447141cc406Sopenharmony_ci - split sane_get_parameters into two functions 448141cc406Sopenharmony_ci - remove unused code from get_pixelsize 449141cc406Sopenharmony_ci - support hardware based auto length detection 450141cc406Sopenharmony_ci v97 2009-09-14, MAN 451141cc406Sopenharmony_ci - use sanei_magic to provide software deskew, autocrop and despeckle 452141cc406Sopenharmony_ci v98 2010-02-09, MAN (SANE 1.0.21) 453141cc406Sopenharmony_ci - clean up #include lines and copyright 454141cc406Sopenharmony_ci - add SANE_I18N to static strings 455141cc406Sopenharmony_ci - don't fail if scsi buffer is too small 456141cc406Sopenharmony_ci - disable bg_color for S1500 457141cc406Sopenharmony_ci - enable flatbed for M3092 458141cc406Sopenharmony_ci v99 2010-05-14, MAN 459141cc406Sopenharmony_ci - sense_handler(): collect rs_info for any ILI, not just EOM 460141cc406Sopenharmony_ci - do_usb_cmd(): use rs_info whenever set, not just EOF 461141cc406Sopenharmony_ci - read_from_*(): better handling of EOF from lower level functions 462141cc406Sopenharmony_ci - sane_read(): improve duplexing logic 463141cc406Sopenharmony_ci v100 2010-06-01, MAN 464141cc406Sopenharmony_ci - store more Request Sense data in scanner struct 465141cc406Sopenharmony_ci - clear Request Sense data at start of every do_cmd() call 466141cc406Sopenharmony_ci - track per-side ILI and global EOM flags 467141cc406Sopenharmony_ci - set per-side EOF flag if ILI and EOM are set 468141cc406Sopenharmony_ci v101 2010-06-23, MAN 469141cc406Sopenharmony_ci - fix compilation bug when jpeg is enabled 470141cc406Sopenharmony_ci v102 2010-09-22, MAN 471141cc406Sopenharmony_ci - fix infinite loop when scan is an odd number of lines 472141cc406Sopenharmony_ci v103 2010-11-23, MAN 473141cc406Sopenharmony_ci - remove compiled-in default config file 474141cc406Sopenharmony_ci - initial support for new fi-6xxx machines 475141cc406Sopenharmony_ci v104 2010-11-24, MAN 476141cc406Sopenharmony_ci - never request more than s->buffer_size from scanner 477141cc406Sopenharmony_ci - silence noisy set_window() calls from init_interlace() 478141cc406Sopenharmony_ci v105 2010-12-02, MAN 479141cc406Sopenharmony_ci - backup and restore image params around image processing code 480141cc406Sopenharmony_ci - cache software crop/deskew parameters for use on backside of duplex 481141cc406Sopenharmony_ci - fi-6110 does not support bgcolor or prepick 482141cc406Sopenharmony_ci v106 2011-01-30, MAN (SANE 1.0.22) 483141cc406Sopenharmony_ci - don't call mode_select with a page code the scanner does not support 484141cc406Sopenharmony_ci v107 2011-11-03, MAN 485141cc406Sopenharmony_ci - M3091 does not support scanner_control(adf) 486141cc406Sopenharmony_ci - Correct buffer overflow in read_from_3091duplex() 487141cc406Sopenharmony_ci - sane_read() now always calls read_from_*() 488141cc406Sopenharmony_ci - read_from_*() are callable when there is no data, and read to eof 489141cc406Sopenharmony_ci - sane_read() will keep alternate duplex reads to similar length 490141cc406Sopenharmony_ci - Added debugging statements 491141cc406Sopenharmony_ci - Corrected comments 492141cc406Sopenharmony_ci - Updated Copyright 493141cc406Sopenharmony_ci v108 2011-11-21, MAN 494141cc406Sopenharmony_ci - merged x/y resolution options 495141cc406Sopenharmony_ci - moved page width/height to start of geometry group 496141cc406Sopenharmony_ci - use mode to pick resolution list v/s range 497141cc406Sopenharmony_ci - improved M3091 resolution choices 498141cc406Sopenharmony_ci v109 2011-12-20, MAN 499141cc406Sopenharmony_ci - added some MS and INQ information 500141cc406Sopenharmony_ci - increased default buffer size for later machines in config file 501141cc406Sopenharmony_ci - renamed new fi-6xx0Z models 502141cc406Sopenharmony_ci v110 2012-05-09, MAN 503141cc406Sopenharmony_ci - correct max_y_fb for fi-62x0 series 504141cc406Sopenharmony_ci - add must_fully_buffer helper routine 505141cc406Sopenharmony_ci - add hwdeskewcrop option, with fallback to software versions 506141cc406Sopenharmony_ci - add 'actual' param to get_pixelsize for post-scan 507141cc406Sopenharmony_ci - add recent model VPD params 508141cc406Sopenharmony_ci - only set params->lines = -1 when using ald without buffering 509141cc406Sopenharmony_ci - fix bugs in background color when using software deskew 510141cc406Sopenharmony_ci v111 2012-05-10, MAN (SANE 1.0.23) 511141cc406Sopenharmony_ci - call send_* and mode_select_* from sane_start 512141cc406Sopenharmony_ci - split read payloads into new debug level 513141cc406Sopenharmony_ci - add paper-protect, staple-detect and df-recovery options 514141cc406Sopenharmony_ci v112 2013-02-22, MAN 515141cc406Sopenharmony_ci - some scanners (fi-6x70 and later) don't enable IPC by default 516141cc406Sopenharmony_ci v113 2013-02-24, MAN 517141cc406Sopenharmony_ci - support for ScanSnap iX500 518141cc406Sopenharmony_ci - fix bug with jpeg de-interlacing code 519141cc406Sopenharmony_ci - allow has_MS_* and has_pixelsize to be set in init_model 520141cc406Sopenharmony_ci - fix use of uninitialized buffer in send_lut 521141cc406Sopenharmony_ci - add send_q_table() 522141cc406Sopenharmony_ci - allow wait_scanner() to be bypassed in object_position 523141cc406Sopenharmony_ci - moved send_lut() to after set_window 524141cc406Sopenharmony_ci v114 2013-03-01, MAN 525141cc406Sopenharmony_ci - support resolutions > 300 for iX500 using diag_preread() 526141cc406Sopenharmony_ci - remove most communication with scanner during sane_control_option() 527141cc406Sopenharmony_ci v115 2013-03-09, MAN 528141cc406Sopenharmony_ci - separate s->mode into s_mode and u_mode 529141cc406Sopenharmony_ci - separate s->params into s_params and u_params 530141cc406Sopenharmony_ci - generate grayscale and binary in software if required (iX500) 531141cc406Sopenharmony_ci v116 2013-03-23, MAN 532141cc406Sopenharmony_ci - call set_mode() in init_interlace 533141cc406Sopenharmony_ci - add swskip option 534141cc406Sopenharmony_ci v117 2013-06-11, MAN (SANE 1.0.24) 535141cc406Sopenharmony_ci - default buffer-mode to off 536141cc406Sopenharmony_ci - improved error handling in sane_start 537141cc406Sopenharmony_ci - image width must be multiple of 8 when swcrop is used before binarization (iX500) 538141cc406Sopenharmony_ci - check hopper sensor before calling object_position(load) on iX500 539141cc406Sopenharmony_ci v118 2013-12-09, MAN 540141cc406Sopenharmony_ci - support fi-7160, fi-7260, fi-7180 and fi-7280 541141cc406Sopenharmony_ci - remove unused var from do_scsi_cmd() 542141cc406Sopenharmony_ci - added more request_sense options 543141cc406Sopenharmony_ci - add adv_paper_protect option 544141cc406Sopenharmony_ci - enable paper protection by default 545141cc406Sopenharmony_ci - increase max_x_fb for fi-6240 and fi-6230 546141cc406Sopenharmony_ci v119 2013-12-18, MAN 547141cc406Sopenharmony_ci - call get_pixelsize after start_scan, not before 548141cc406Sopenharmony_ci - extend get_pixelsize to request backside data 549141cc406Sopenharmony_ci - stop using backup/restore_params 550141cc406Sopenharmony_ci - don't use extended get_pixelsize on M3091 or M3092 551141cc406Sopenharmony_ci - call software crop code on backside images too 552141cc406Sopenharmony_ci v120 2014-01-29, MAN 553141cc406Sopenharmony_ci - only call hopper_before_op code at batch start 554141cc406Sopenharmony_ci - remove unused backup/restore_params 555141cc406Sopenharmony_ci v121 2014-04-07, MAN 556141cc406Sopenharmony_ci - add JFIF APP0 marker with resolution to jpeg images 557141cc406Sopenharmony_ci - improve jpeg duplex parsing code 558141cc406Sopenharmony_ci - simplify jpeg ifdefs 559141cc406Sopenharmony_ci - add offtimer option for more recent scanners 560141cc406Sopenharmony_ci - don't print 0 length line in hexdump 561141cc406Sopenharmony_ci v122 2014-10-28, MAN 562141cc406Sopenharmony_ci - add support for object_position halt 563141cc406Sopenharmony_ci - call object_position halt in check_for_cancel when requested 564141cc406Sopenharmony_ci v123 2014-11-06, MAN 565141cc406Sopenharmony_ci - workaround Linux USB3 bugs by adding command counting code and 566141cc406Sopenharmony_ci sending an even number of reads and writes during disconnect_fd 567141cc406Sopenharmony_ci v124 2014-12-09, MAN 568141cc406Sopenharmony_ci - support resolution controlled max page-height (fi-6/7xxx scanners) 569141cc406Sopenharmony_ci - reorder scanner sections in init_model chronologically 570141cc406Sopenharmony_ci v125 2014-12-16, MAN 571141cc406Sopenharmony_ci - remove USB packet counting code from v123, fix sanei_usb instead 572141cc406Sopenharmony_ci v126 2015-08-23, MAN 573141cc406Sopenharmony_ci - initial support for iX100 574141cc406Sopenharmony_ci - add late_lut support for iX500/iX100 575141cc406Sopenharmony_ci v127 2015-08-25, MAN (SANE 1.0.25) 576141cc406Sopenharmony_ci - separate iX100 from iX500 settings 577141cc406Sopenharmony_ci - iX100 has gray and lineart 578141cc406Sopenharmony_ci v128 2015-11-08, MAN 579141cc406Sopenharmony_ci - do not ask fi-4340 for serial number 580141cc406Sopenharmony_ci v129 2015-11-21, MAN 581141cc406Sopenharmony_ci - br_x and br_y locked to page_width/height until changed 582141cc406Sopenharmony_ci v130 2016-02-23, MAN 583141cc406Sopenharmony_ci - run init_model before init_ms so some scanners can override 584141cc406Sopenharmony_ci - set all M309x and M409x scanners s->broken_diag_serial = 1 585141cc406Sopenharmony_ci v131 2016-06-06, MAN 586141cc406Sopenharmony_ci - hide compression-arg option when jpeg disabled 587141cc406Sopenharmony_ci - add Send/SC/GHS macros for recent scanners 588141cc406Sopenharmony_ci - add initial support for fi-74x0 589141cc406Sopenharmony_ci - add initial support for fi-7030 590141cc406Sopenharmony_ci - set has_MS_lamp=0 for fi-71x0 591141cc406Sopenharmony_ci - add I18N macros to all option titles and descriptions 592141cc406Sopenharmony_ci v132 2016-10-07, MAN 593141cc406Sopenharmony_ci - remove ipc_mode option and variables 594141cc406Sopenharmony_ci - set ipc mode based on other options 595141cc406Sopenharmony_ci - cleanup inverted logic DTC options 596141cc406Sopenharmony_ci - fixes threshold option reported in #315069 597141cc406Sopenharmony_ci v133 2017-04-08, MAN 598141cc406Sopenharmony_ci - initial support for fi-7600/7700 599141cc406Sopenharmony_ci - autodetect various double feed capabilities using VPD 600141cc406Sopenharmony_ci - call send_lut if we are using a downloaded gamma table 601141cc406Sopenharmony_ci v134 2019-02-23, MAN 602141cc406Sopenharmony_ci - rewrite init_vpd for scanners which fail to report 603141cc406Sopenharmony_ci overscan correctly 604141cc406Sopenharmony_ci v135 2019-11-10, MAN (SANE 1.0.29) 605141cc406Sopenharmony_ci - set has_MS_lamp=0 for fi-72x0, bug #134 606141cc406Sopenharmony_ci v136 2020-02-07, MAN 607141cc406Sopenharmony_ci - add support for fi-800R 608141cc406Sopenharmony_ci - add support for card scanning slot (Return Path) 609141cc406Sopenharmony_ci - fix bug with reading hardware sensors on first invocation 610141cc406Sopenharmony_ci v137 2020-09-23, MAN 611141cc406Sopenharmony_ci - fix JPEG duplex memory corruption 612141cc406Sopenharmony_ci - change window_gamma init (fixes bright/contrast for iX1500) 613141cc406Sopenharmony_ci - only call send_lut after set_window (remove late_lut) 614141cc406Sopenharmony_ci v138 2022-06-01, MAN 615141cc406Sopenharmony_ci - minor updates to company name (FCPA -> PFU) 616141cc406Sopenharmony_ci v139 2022-11-15, MAN 617141cc406Sopenharmony_ci - move updated window_gamma logic to set_window 618141cc406Sopenharmony_ci - use internal gamma table if possible (fixes #618) 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci SANE FLOW DIAGRAM 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_ci - sane_init() : initialize backend 623141cc406Sopenharmony_ci . - sane_get_devices() : query list of scanner devices 624141cc406Sopenharmony_ci . - sane_open() : open a particular scanner device 625141cc406Sopenharmony_ci . . - sane_set_io_mode : set blocking mode 626141cc406Sopenharmony_ci . . - sane_get_select_fd : get scanner fd 627141cc406Sopenharmony_ci . . 628141cc406Sopenharmony_ci . . - sane_get_option_descriptor() : get option information 629141cc406Sopenharmony_ci . . - sane_control_option() : change option values 630141cc406Sopenharmony_ci . . - sane_get_parameters() : returns estimated scan parameters 631141cc406Sopenharmony_ci . . - (repeat previous 3 functions) 632141cc406Sopenharmony_ci . . 633141cc406Sopenharmony_ci . . - sane_start() : start image acquisition 634141cc406Sopenharmony_ci . . - sane_get_parameters() : returns actual scan parameters 635141cc406Sopenharmony_ci . . - sane_read() : read image data (from pipe) 636141cc406Sopenharmony_ci . . (sane_read called multiple times; after sane_read returns EOF, 637141cc406Sopenharmony_ci . . loop may continue with sane_start which may return a 2nd page 638141cc406Sopenharmony_ci . . when doing duplex scans, or load the next page from the ADF) 639141cc406Sopenharmony_ci . . 640141cc406Sopenharmony_ci . . - sane_cancel() : cancel operation 641141cc406Sopenharmony_ci . - sane_close() : close opened scanner device 642141cc406Sopenharmony_ci - sane_exit() : terminate use of backend 643141cc406Sopenharmony_ci 644141cc406Sopenharmony_ci*/ 645141cc406Sopenharmony_ci 646141cc406Sopenharmony_ci/* 647141cc406Sopenharmony_ci * @@ Section 1 - Boilerplate 648141cc406Sopenharmony_ci */ 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_ci#include "../include/sane/config.h" 651141cc406Sopenharmony_ci 652141cc406Sopenharmony_ci#include <string.h> /*memcpy...*/ 653141cc406Sopenharmony_ci#include <ctype.h> /*isspace*/ 654141cc406Sopenharmony_ci#include <math.h> /*tan*/ 655141cc406Sopenharmony_ci#include <unistd.h> /*usleep*/ 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 658141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 659141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 660141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 661141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 662141cc406Sopenharmony_ci#include "../include/sane/sanei_magic.h" 663141cc406Sopenharmony_ci 664141cc406Sopenharmony_ci#include "fujitsu-scsi.h" 665141cc406Sopenharmony_ci#include "fujitsu.h" 666141cc406Sopenharmony_ci 667141cc406Sopenharmony_ci#define DEBUG 1 668141cc406Sopenharmony_ci#define BUILD 139 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ci/* values for SANE_DEBUG_FUJITSU env var: 671141cc406Sopenharmony_ci - errors 5 672141cc406Sopenharmony_ci - function trace 10 673141cc406Sopenharmony_ci - function detail 15 674141cc406Sopenharmony_ci - get/setopt cmds 20 675141cc406Sopenharmony_ci - scsi/usb trace 25 676141cc406Sopenharmony_ci - scsi/usb writes 30 677141cc406Sopenharmony_ci - scsi/usb reads 31 678141cc406Sopenharmony_ci - useless noise 35 679141cc406Sopenharmony_ci*/ 680141cc406Sopenharmony_ci 681141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 682141cc406Sopenharmony_ci/* if JPEG support is not enabled in sane.h, we setup our own defines */ 683141cc406Sopenharmony_ci#ifndef SANE_FRAME_JPEG 684141cc406Sopenharmony_ci#define SANE_FRAME_JPEG 0x0B 685141cc406Sopenharmony_ci#define SANE_JPEG_DISABLED 1 686141cc406Sopenharmony_ci#endif 687141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 688141cc406Sopenharmony_ci#define STRING_FLATBED SANE_I18N("Flatbed") 689141cc406Sopenharmony_ci#define STRING_ADFFRONT SANE_I18N("ADF Front") 690141cc406Sopenharmony_ci#define STRING_ADFBACK SANE_I18N("ADF Back") 691141cc406Sopenharmony_ci#define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") 692141cc406Sopenharmony_ci#define STRING_CARDFRONT SANE_I18N("Card Front") 693141cc406Sopenharmony_ci#define STRING_CARDBACK SANE_I18N("Card Back") 694141cc406Sopenharmony_ci#define STRING_CARDDUPLEX SANE_I18N("Card Duplex") 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci#define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART 697141cc406Sopenharmony_ci#define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE 698141cc406Sopenharmony_ci#define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY 699141cc406Sopenharmony_ci#define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci#define STRING_DEFAULT SANE_I18N("Default") 702141cc406Sopenharmony_ci#define STRING_ON SANE_I18N("On") 703141cc406Sopenharmony_ci#define STRING_OFF SANE_I18N("Off") 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci#define STRING_DTC SANE_I18N("DTC") 706141cc406Sopenharmony_ci#define STRING_SDTC SANE_I18N("SDTC") 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci#define STRING_DITHER SANE_I18N("Dither") 709141cc406Sopenharmony_ci#define STRING_DIFFUSION SANE_I18N("Diffusion") 710141cc406Sopenharmony_ci 711141cc406Sopenharmony_ci#define STRING_RED SANE_I18N("Red") 712141cc406Sopenharmony_ci#define STRING_GREEN SANE_I18N("Green") 713141cc406Sopenharmony_ci#define STRING_BLUE SANE_I18N("Blue") 714141cc406Sopenharmony_ci#define STRING_WHITE SANE_I18N("White") 715141cc406Sopenharmony_ci#define STRING_BLACK SANE_I18N("Black") 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci#define STRING_NONE SANE_I18N("None") 718141cc406Sopenharmony_ci#define STRING_JPEG SANE_I18N("JPEG") 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci#define STRING_CONTINUE SANE_I18N("Continue") 721141cc406Sopenharmony_ci#define STRING_STOP SANE_I18N("Stop") 722141cc406Sopenharmony_ci 723141cc406Sopenharmony_ci#define STRING_10MM SANE_I18N("10mm") 724141cc406Sopenharmony_ci#define STRING_15MM SANE_I18N("15mm") 725141cc406Sopenharmony_ci#define STRING_20MM SANE_I18N("20mm") 726141cc406Sopenharmony_ci 727141cc406Sopenharmony_ci#define STRING_HORIZONTAL SANE_I18N("Horizontal") 728141cc406Sopenharmony_ci#define STRING_HORIZONTALBOLD SANE_I18N("Horizontal bold") 729141cc406Sopenharmony_ci#define STRING_HORIZONTALNARROW SANE_I18N("Horizontal narrow") 730141cc406Sopenharmony_ci#define STRING_VERTICAL SANE_I18N("Vertical") 731141cc406Sopenharmony_ci#define STRING_VERTICALBOLD SANE_I18N("Vertical bold") 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci#define STRING_TOPTOBOTTOM SANE_I18N("Top to bottom") 734141cc406Sopenharmony_ci#define STRING_BOTTOMTOTOP SANE_I18N("Bottom to top") 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci#define STRING_FRONT SANE_I18N("Front") 737141cc406Sopenharmony_ci#define STRING_BACK SANE_I18N("Back") 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci#define max(a,b) (((a)>(b))?(a):(b)) 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci/* Also set via config file. */ 742141cc406Sopenharmony_cistatic int global_buffer_size = 64 * 1024; 743141cc406Sopenharmony_ci 744141cc406Sopenharmony_ci/* 745141cc406Sopenharmony_ci * used by attach* and sane_get_devices 746141cc406Sopenharmony_ci * a ptr to a null term array of ptrs to SANE_Device structs 747141cc406Sopenharmony_ci * a ptr to a single-linked list of fujitsu structs 748141cc406Sopenharmony_ci */ 749141cc406Sopenharmony_cistatic const SANE_Device **sane_devArray = NULL; 750141cc406Sopenharmony_cistatic struct fujitsu *fujitsu_devList = NULL; 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci/* 753141cc406Sopenharmony_ci * @@ Section 2 - SANE & scanner init code 754141cc406Sopenharmony_ci */ 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_ci/* 757141cc406Sopenharmony_ci * Called by SANE initially. 758141cc406Sopenharmony_ci * 759141cc406Sopenharmony_ci * From the SANE spec: 760141cc406Sopenharmony_ci * This function must be called before any other SANE function can be 761141cc406Sopenharmony_ci * called. The behavior of a SANE backend is undefined if this 762141cc406Sopenharmony_ci * function is not called first. The version code of the backend is 763141cc406Sopenharmony_ci * returned in the value pointed to by version_code. If that pointer 764141cc406Sopenharmony_ci * is NULL, no version code is returned. Argument authorize is either 765141cc406Sopenharmony_ci * a pointer to a function that is invoked when the backend requires 766141cc406Sopenharmony_ci * authentication for a specific resource or NULL if the frontend does 767141cc406Sopenharmony_ci * not support authentication. 768141cc406Sopenharmony_ci */ 769141cc406Sopenharmony_ciSANE_Status 770141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 771141cc406Sopenharmony_ci{ 772141cc406Sopenharmony_ci (void) authorize; /* get rid of compiler warning */ 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci DBG_INIT (); 775141cc406Sopenharmony_ci DBG (10, "sane_init: start\n"); 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci if (version_code) 778141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ci DBG (5, "sane_init: fujitsu backend %d.%d.%d, from %s\n", 781141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); 782141cc406Sopenharmony_ci 783141cc406Sopenharmony_ci sanei_magic_init(); 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci DBG (10, "sane_init: finish\n"); 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 788141cc406Sopenharmony_ci} 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci/* 791141cc406Sopenharmony_ci * Called by SANE to find out about supported devices. 792141cc406Sopenharmony_ci * 793141cc406Sopenharmony_ci * From the SANE spec: 794141cc406Sopenharmony_ci * This function can be used to query the list of devices that are 795141cc406Sopenharmony_ci * available. If the function executes successfully, it stores a 796141cc406Sopenharmony_ci * pointer to a NULL terminated array of pointers to SANE_Device 797141cc406Sopenharmony_ci * structures in *device_list. The returned list is guaranteed to 798141cc406Sopenharmony_ci * remain unchanged and valid until (a) another call to this function 799141cc406Sopenharmony_ci * is performed or (b) a call to sane_exit() is performed. This 800141cc406Sopenharmony_ci * function can be called repeatedly to detect when new devices become 801141cc406Sopenharmony_ci * available. If argument local_only is true, only local devices are 802141cc406Sopenharmony_ci * returned (devices directly attached to the machine that SANE is 803141cc406Sopenharmony_ci * running on). If it is false, the device list includes all remote 804141cc406Sopenharmony_ci * devices that are accessible to the SANE library. 805141cc406Sopenharmony_ci * 806141cc406Sopenharmony_ci * SANE does not require that this function is called before a 807141cc406Sopenharmony_ci * sane_open() call is performed. A device name may be specified 808141cc406Sopenharmony_ci * explicitly by a user which would make it unnecessary and 809141cc406Sopenharmony_ci * undesirable to call this function first. 810141cc406Sopenharmony_ci */ 811141cc406Sopenharmony_ci/* 812141cc406Sopenharmony_ci * Read the config file, find scanners with help from sanei_* 813141cc406Sopenharmony_ci * and store in global device structs 814141cc406Sopenharmony_ci */ 815141cc406Sopenharmony_ciSANE_Status 816141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 817141cc406Sopenharmony_ci{ 818141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 819141cc406Sopenharmony_ci struct fujitsu * s; 820141cc406Sopenharmony_ci struct fujitsu * prev = NULL; 821141cc406Sopenharmony_ci char line[PATH_MAX]; 822141cc406Sopenharmony_ci const char *lp; 823141cc406Sopenharmony_ci FILE *fp; 824141cc406Sopenharmony_ci int num_devices=0; 825141cc406Sopenharmony_ci int i=0; 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci (void) local_only; /* get rid of compiler warning */ 828141cc406Sopenharmony_ci 829141cc406Sopenharmony_ci DBG (10, "sane_get_devices: start\n"); 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci /* mark all existing scanners as missing, attach_one will remove mark */ 832141cc406Sopenharmony_ci for (s = fujitsu_devList; s; s = s->next) { 833141cc406Sopenharmony_ci s->missing = 1; 834141cc406Sopenharmony_ci } 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci sanei_usb_init(); 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci /* set this to 64K before reading the file */ 839141cc406Sopenharmony_ci global_buffer_size = 64 * 1024; 840141cc406Sopenharmony_ci 841141cc406Sopenharmony_ci fp = sanei_config_open (FUJITSU_CONFIG_FILE); 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci if (fp) { 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci DBG (15, "sane_get_devices: reading config file %s\n", 846141cc406Sopenharmony_ci FUJITSU_CONFIG_FILE); 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci while (sanei_config_read (line, PATH_MAX, fp)) { 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci lp = line; 851141cc406Sopenharmony_ci 852141cc406Sopenharmony_ci /* ignore comments */ 853141cc406Sopenharmony_ci if (*lp == '#') 854141cc406Sopenharmony_ci continue; 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_ci /* skip empty lines */ 857141cc406Sopenharmony_ci if (*lp == 0) 858141cc406Sopenharmony_ci continue; 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci if ((strncmp ("option", lp, 6) == 0) && isspace (lp[6])) { 861141cc406Sopenharmony_ci 862141cc406Sopenharmony_ci lp += 6; 863141cc406Sopenharmony_ci lp = sanei_config_skip_whitespace (lp); 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci /* we allow setting buffersize too big */ 866141cc406Sopenharmony_ci if ((strncmp (lp, "buffer-size", 11) == 0) && isspace (lp[11])) { 867141cc406Sopenharmony_ci 868141cc406Sopenharmony_ci int buf; 869141cc406Sopenharmony_ci lp += 11; 870141cc406Sopenharmony_ci lp = sanei_config_skip_whitespace (lp); 871141cc406Sopenharmony_ci buf = atoi (lp); 872141cc406Sopenharmony_ci 873141cc406Sopenharmony_ci if (buf < 4096) { 874141cc406Sopenharmony_ci DBG (5, "sane_get_devices: config option \"buffer-size\" (%d) is < 4096, ignoring!\n", buf); 875141cc406Sopenharmony_ci continue; 876141cc406Sopenharmony_ci } 877141cc406Sopenharmony_ci 878141cc406Sopenharmony_ci if (buf > 64*1024) { 879141cc406Sopenharmony_ci DBG (5, "sane_get_devices: config option \"buffer-size\" (%d) is > %d, warning!\n", buf, 64*1024); 880141cc406Sopenharmony_ci } 881141cc406Sopenharmony_ci 882141cc406Sopenharmony_ci DBG (15, "sane_get_devices: setting \"buffer-size\" to %d\n", buf); 883141cc406Sopenharmony_ci global_buffer_size = buf; 884141cc406Sopenharmony_ci } 885141cc406Sopenharmony_ci else { 886141cc406Sopenharmony_ci DBG (5, "sane_get_devices: config option \"%s\" unrecognized - ignored.\n", lp); 887141cc406Sopenharmony_ci } 888141cc406Sopenharmony_ci } 889141cc406Sopenharmony_ci else if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) { 890141cc406Sopenharmony_ci DBG (15, "sane_get_devices: looking for '%s'\n", lp); 891141cc406Sopenharmony_ci sanei_usb_attach_matching_devices(lp, attach_one_usb); 892141cc406Sopenharmony_ci } 893141cc406Sopenharmony_ci else if ((strncmp ("scsi", lp, 4) == 0) && isspace (lp[4])) { 894141cc406Sopenharmony_ci DBG (15, "sane_get_devices: looking for '%s'\n", lp); 895141cc406Sopenharmony_ci sanei_config_attach_matching_devices (lp, attach_one_scsi); 896141cc406Sopenharmony_ci } 897141cc406Sopenharmony_ci else{ 898141cc406Sopenharmony_ci DBG (5, "sane_get_devices: config line \"%s\" unrecognized - ignored.\n", lp); 899141cc406Sopenharmony_ci } 900141cc406Sopenharmony_ci } 901141cc406Sopenharmony_ci fclose (fp); 902141cc406Sopenharmony_ci } 903141cc406Sopenharmony_ci 904141cc406Sopenharmony_ci else { 905141cc406Sopenharmony_ci DBG (5, "sane_get_devices: missing required config file '%s'!\n", 906141cc406Sopenharmony_ci FUJITSU_CONFIG_FILE); 907141cc406Sopenharmony_ci } 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci /*delete missing scanners from list*/ 910141cc406Sopenharmony_ci for (s = fujitsu_devList; s;) { 911141cc406Sopenharmony_ci if(s->missing){ 912141cc406Sopenharmony_ci DBG (5, "sane_get_devices: missing scanner %s\n",s->device_name); 913141cc406Sopenharmony_ci 914141cc406Sopenharmony_ci /*splice s out of list by changing pointer in prev to next*/ 915141cc406Sopenharmony_ci if(prev){ 916141cc406Sopenharmony_ci prev->next = s->next; 917141cc406Sopenharmony_ci free(s); 918141cc406Sopenharmony_ci s=prev->next; 919141cc406Sopenharmony_ci } 920141cc406Sopenharmony_ci /*remove s from head of list, using prev to cache it*/ 921141cc406Sopenharmony_ci else{ 922141cc406Sopenharmony_ci prev = s; 923141cc406Sopenharmony_ci s = s->next; 924141cc406Sopenharmony_ci free(prev); 925141cc406Sopenharmony_ci prev=NULL; 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci /*reset head to next s*/ 928141cc406Sopenharmony_ci fujitsu_devList = s; 929141cc406Sopenharmony_ci } 930141cc406Sopenharmony_ci } 931141cc406Sopenharmony_ci else{ 932141cc406Sopenharmony_ci prev = s; 933141cc406Sopenharmony_ci s=prev->next; 934141cc406Sopenharmony_ci } 935141cc406Sopenharmony_ci } 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci for (s = fujitsu_devList; s; s=s->next) { 938141cc406Sopenharmony_ci DBG (15, "sane_get_devices: found scanner %s\n",s->device_name); 939141cc406Sopenharmony_ci num_devices++; 940141cc406Sopenharmony_ci } 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_ci DBG (15, "sane_get_devices: found %d scanner(s)\n",num_devices); 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci if (sane_devArray) 945141cc406Sopenharmony_ci free (sane_devArray); 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci sane_devArray = calloc (num_devices + 1, sizeof (SANE_Device*)); 948141cc406Sopenharmony_ci if (!sane_devArray) 949141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 950141cc406Sopenharmony_ci 951141cc406Sopenharmony_ci for (s = fujitsu_devList; s; s=s->next) { 952141cc406Sopenharmony_ci sane_devArray[i++] = (SANE_Device *)&s->sane; 953141cc406Sopenharmony_ci } 954141cc406Sopenharmony_ci sane_devArray[i] = 0; 955141cc406Sopenharmony_ci 956141cc406Sopenharmony_ci if(device_list){ 957141cc406Sopenharmony_ci *device_list = sane_devArray; 958141cc406Sopenharmony_ci } 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci DBG (10, "sane_get_devices: finish\n"); 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci return ret; 963141cc406Sopenharmony_ci} 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci/* callbacks used by sane_get_devices */ 966141cc406Sopenharmony_cistatic SANE_Status 967141cc406Sopenharmony_ciattach_one_scsi (const char *device_name) 968141cc406Sopenharmony_ci{ 969141cc406Sopenharmony_ci return attach_one(device_name,CONNECTION_SCSI); 970141cc406Sopenharmony_ci} 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_cistatic SANE_Status 973141cc406Sopenharmony_ciattach_one_usb (const char *device_name) 974141cc406Sopenharmony_ci{ 975141cc406Sopenharmony_ci return attach_one(device_name,CONNECTION_USB); 976141cc406Sopenharmony_ci} 977141cc406Sopenharmony_ci 978141cc406Sopenharmony_ci/* build the scanner struct and link to global list 979141cc406Sopenharmony_ci * unless struct is already loaded, then pretend 980141cc406Sopenharmony_ci */ 981141cc406Sopenharmony_cistatic SANE_Status 982141cc406Sopenharmony_ciattach_one (const char *device_name, int connType) 983141cc406Sopenharmony_ci{ 984141cc406Sopenharmony_ci struct fujitsu *s; 985141cc406Sopenharmony_ci int ret; 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci DBG (10, "attach_one: start\n"); 988141cc406Sopenharmony_ci DBG (15, "attach_one: looking for '%s'\n", device_name); 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci for (s = fujitsu_devList; s; s = s->next) { 991141cc406Sopenharmony_ci if (strcmp (s->device_name, device_name) == 0){ 992141cc406Sopenharmony_ci DBG (10, "attach_one: already attached!\n"); 993141cc406Sopenharmony_ci s->missing = 0; 994141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 995141cc406Sopenharmony_ci } 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci 998141cc406Sopenharmony_ci /* build a fujitsu struct to hold it */ 999141cc406Sopenharmony_ci if ((s = calloc (sizeof (*s), 1)) == NULL) 1000141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1001141cc406Sopenharmony_ci 1002141cc406Sopenharmony_ci /* scsi command/data buffer */ 1003141cc406Sopenharmony_ci s->buffer_size = global_buffer_size; 1004141cc406Sopenharmony_ci 1005141cc406Sopenharmony_ci /* copy the device name */ 1006141cc406Sopenharmony_ci strcpy (s->device_name, device_name); 1007141cc406Sopenharmony_ci 1008141cc406Sopenharmony_ci /* connect the fd */ 1009141cc406Sopenharmony_ci s->connection = connType; 1010141cc406Sopenharmony_ci s->fd = -1; 1011141cc406Sopenharmony_ci ret = connect_fd(s); 1012141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1013141cc406Sopenharmony_ci free (s); 1014141cc406Sopenharmony_ci return ret; 1015141cc406Sopenharmony_ci } 1016141cc406Sopenharmony_ci 1017141cc406Sopenharmony_ci /* Now query the device to load its vendor/model/version */ 1018141cc406Sopenharmony_ci ret = init_inquire (s); 1019141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1020141cc406Sopenharmony_ci disconnect_fd(s); 1021141cc406Sopenharmony_ci free (s); 1022141cc406Sopenharmony_ci DBG (5, "attach_one: inquiry failed\n"); 1023141cc406Sopenharmony_ci return ret; 1024141cc406Sopenharmony_ci } 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci /* load detailed specs/capabilities from the device */ 1027141cc406Sopenharmony_ci ret = init_vpd (s); 1028141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1029141cc406Sopenharmony_ci disconnect_fd(s); 1030141cc406Sopenharmony_ci free (s); 1031141cc406Sopenharmony_ci DBG (5, "attach_one: vpd failed\n"); 1032141cc406Sopenharmony_ci return ret; 1033141cc406Sopenharmony_ci } 1034141cc406Sopenharmony_ci 1035141cc406Sopenharmony_ci /* clean up the scanner struct based on model */ 1036141cc406Sopenharmony_ci /* this is the only piece of model specific code */ 1037141cc406Sopenharmony_ci ret = init_model (s); 1038141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1039141cc406Sopenharmony_ci disconnect_fd(s); 1040141cc406Sopenharmony_ci free (s); 1041141cc406Sopenharmony_ci DBG (5, "attach_one: model failed\n"); 1042141cc406Sopenharmony_ci return ret; 1043141cc406Sopenharmony_ci } 1044141cc406Sopenharmony_ci 1045141cc406Sopenharmony_ci /* see what mode pages device supports */ 1046141cc406Sopenharmony_ci ret = init_ms (s); 1047141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1048141cc406Sopenharmony_ci disconnect_fd(s); 1049141cc406Sopenharmony_ci free (s); 1050141cc406Sopenharmony_ci DBG (5, "attach_one: ms failed\n"); 1051141cc406Sopenharmony_ci return ret; 1052141cc406Sopenharmony_ci } 1053141cc406Sopenharmony_ci 1054141cc406Sopenharmony_ci /* sets SANE option 'values' to good defaults */ 1055141cc406Sopenharmony_ci ret = init_user (s); 1056141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1057141cc406Sopenharmony_ci disconnect_fd(s); 1058141cc406Sopenharmony_ci free (s); 1059141cc406Sopenharmony_ci DBG (5, "attach_one: user failed\n"); 1060141cc406Sopenharmony_ci return ret; 1061141cc406Sopenharmony_ci } 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_ci ret = init_options (s); 1064141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1065141cc406Sopenharmony_ci disconnect_fd(s); 1066141cc406Sopenharmony_ci free (s); 1067141cc406Sopenharmony_ci DBG (5, "attach_one: options failed\n"); 1068141cc406Sopenharmony_ci return ret; 1069141cc406Sopenharmony_ci } 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci ret = init_interlace (s); 1072141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1073141cc406Sopenharmony_ci disconnect_fd(s); 1074141cc406Sopenharmony_ci free (s); 1075141cc406Sopenharmony_ci DBG (5, "attach_one: interlace failed\n"); 1076141cc406Sopenharmony_ci return ret; 1077141cc406Sopenharmony_ci } 1078141cc406Sopenharmony_ci 1079141cc406Sopenharmony_ci /* load strings into sane_device struct */ 1080141cc406Sopenharmony_ci s->sane.name = s->device_name; 1081141cc406Sopenharmony_ci s->sane.vendor = s->vendor_name; 1082141cc406Sopenharmony_ci s->sane.model = s->model_name; 1083141cc406Sopenharmony_ci s->sane.type = "scanner"; 1084141cc406Sopenharmony_ci 1085141cc406Sopenharmony_ci /* change name in sane_device struct if scanner has serial number */ 1086141cc406Sopenharmony_ci ret = init_serial (s); 1087141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD) { 1088141cc406Sopenharmony_ci s->sane.name = s->serial_name; 1089141cc406Sopenharmony_ci } 1090141cc406Sopenharmony_ci else{ 1091141cc406Sopenharmony_ci DBG (5, "attach_one: serial number unsupported?\n"); 1092141cc406Sopenharmony_ci } 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci /* we close the connection, so that another backend can talk to scanner */ 1095141cc406Sopenharmony_ci disconnect_fd(s); 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci /* store this scanner in global vars */ 1098141cc406Sopenharmony_ci s->next = fujitsu_devList; 1099141cc406Sopenharmony_ci fujitsu_devList = s; 1100141cc406Sopenharmony_ci 1101141cc406Sopenharmony_ci DBG (10, "attach_one: finish\n"); 1102141cc406Sopenharmony_ci 1103141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1104141cc406Sopenharmony_ci} 1105141cc406Sopenharmony_ci 1106141cc406Sopenharmony_ci/* 1107141cc406Sopenharmony_ci * connect the fd in the scanner struct 1108141cc406Sopenharmony_ci */ 1109141cc406Sopenharmony_cistatic SANE_Status 1110141cc406Sopenharmony_ciconnect_fd (struct fujitsu *s) 1111141cc406Sopenharmony_ci{ 1112141cc406Sopenharmony_ci SANE_Status ret; 1113141cc406Sopenharmony_ci int buffer_size = s->buffer_size; 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci DBG (10, "connect_fd: start\n"); 1116141cc406Sopenharmony_ci 1117141cc406Sopenharmony_ci if(s->fd > -1){ 1118141cc406Sopenharmony_ci DBG (5, "connect_fd: already open\n"); 1119141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 1120141cc406Sopenharmony_ci } 1121141cc406Sopenharmony_ci else if (s->connection == CONNECTION_USB) { 1122141cc406Sopenharmony_ci DBG (15, "connect_fd: opening USB device\n"); 1123141cc406Sopenharmony_ci ret = sanei_usb_open (s->device_name, &(s->fd)); 1124141cc406Sopenharmony_ci } 1125141cc406Sopenharmony_ci else { 1126141cc406Sopenharmony_ci DBG (15, "connect_fd: opening SCSI device\n"); 1127141cc406Sopenharmony_ci ret = sanei_scsi_open_extended (s->device_name, &(s->fd), sense_handler, s, 1128141cc406Sopenharmony_ci &s->buffer_size); 1129141cc406Sopenharmony_ci if(!ret && buffer_size != s->buffer_size){ 1130141cc406Sopenharmony_ci DBG (5, "connect_fd: cannot get requested buffer size (%d/%d)\n", 1131141cc406Sopenharmony_ci buffer_size, s->buffer_size); 1132141cc406Sopenharmony_ci } 1133141cc406Sopenharmony_ci } 1134141cc406Sopenharmony_ci 1135141cc406Sopenharmony_ci if(ret == SANE_STATUS_GOOD){ 1136141cc406Sopenharmony_ci 1137141cc406Sopenharmony_ci /* first generation usb scanners can get flaky if not closed 1138141cc406Sopenharmony_ci * properly after last use. very first commands sent to device 1139141cc406Sopenharmony_ci * must be prepared to correct this- see wait_scanner() */ 1140141cc406Sopenharmony_ci ret = wait_scanner(s); 1141141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 1142141cc406Sopenharmony_ci DBG (5, "connect_fd: could not wait_scanner\n"); 1143141cc406Sopenharmony_ci disconnect_fd(s); 1144141cc406Sopenharmony_ci } 1145141cc406Sopenharmony_ci 1146141cc406Sopenharmony_ci } 1147141cc406Sopenharmony_ci else{ 1148141cc406Sopenharmony_ci DBG (5, "connect_fd: could not open device: %d\n", ret); 1149141cc406Sopenharmony_ci } 1150141cc406Sopenharmony_ci 1151141cc406Sopenharmony_ci DBG (10, "connect_fd: finish\n"); 1152141cc406Sopenharmony_ci 1153141cc406Sopenharmony_ci return ret; 1154141cc406Sopenharmony_ci} 1155141cc406Sopenharmony_ci 1156141cc406Sopenharmony_ci/* 1157141cc406Sopenharmony_ci * This routine will check if a certain device is a Fujitsu scanner 1158141cc406Sopenharmony_ci * It also copies interesting data from INQUIRY into the handle structure 1159141cc406Sopenharmony_ci */ 1160141cc406Sopenharmony_cistatic SANE_Status 1161141cc406Sopenharmony_ciinit_inquire (struct fujitsu *s) 1162141cc406Sopenharmony_ci{ 1163141cc406Sopenharmony_ci int i; 1164141cc406Sopenharmony_ci SANE_Status ret; 1165141cc406Sopenharmony_ci 1166141cc406Sopenharmony_ci unsigned char cmd[INQUIRY_len]; 1167141cc406Sopenharmony_ci size_t cmdLen = INQUIRY_len; 1168141cc406Sopenharmony_ci 1169141cc406Sopenharmony_ci unsigned char in[INQUIRY_std_len]; 1170141cc406Sopenharmony_ci size_t inLen = INQUIRY_std_len; 1171141cc406Sopenharmony_ci 1172141cc406Sopenharmony_ci DBG (10, "init_inquire: start\n"); 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 1175141cc406Sopenharmony_ci set_SCSI_opcode(cmd, INQUIRY_code); 1176141cc406Sopenharmony_ci set_IN_return_size (cmd, inLen); 1177141cc406Sopenharmony_ci set_IN_evpd (cmd, 0); 1178141cc406Sopenharmony_ci set_IN_page_code (cmd, 0); 1179141cc406Sopenharmony_ci 1180141cc406Sopenharmony_ci ret = do_cmd ( 1181141cc406Sopenharmony_ci s, 1, 0, 1182141cc406Sopenharmony_ci cmd, cmdLen, 1183141cc406Sopenharmony_ci NULL, 0, 1184141cc406Sopenharmony_ci in, &inLen 1185141cc406Sopenharmony_ci ); 1186141cc406Sopenharmony_ci 1187141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD){ 1188141cc406Sopenharmony_ci return ret; 1189141cc406Sopenharmony_ci } 1190141cc406Sopenharmony_ci 1191141cc406Sopenharmony_ci if (get_IN_periph_devtype (in) != IN_periph_devtype_scanner){ 1192141cc406Sopenharmony_ci DBG (5, "The device at '%s' is not a scanner.\n", s->device_name); 1193141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1194141cc406Sopenharmony_ci } 1195141cc406Sopenharmony_ci 1196141cc406Sopenharmony_ci get_IN_vendor (in, s->vendor_name); 1197141cc406Sopenharmony_ci get_IN_product (in, s->model_name); 1198141cc406Sopenharmony_ci get_IN_version (in, s->version_name); 1199141cc406Sopenharmony_ci 1200141cc406Sopenharmony_ci s->vendor_name[8] = 0; 1201141cc406Sopenharmony_ci s->model_name[16] = 0; 1202141cc406Sopenharmony_ci s->version_name[4] = 0; 1203141cc406Sopenharmony_ci 1204141cc406Sopenharmony_ci /* gobble trailing spaces */ 1205141cc406Sopenharmony_ci for (i = 7; s->vendor_name[i] == ' ' && i >= 0; i--) 1206141cc406Sopenharmony_ci s->vendor_name[i] = 0; 1207141cc406Sopenharmony_ci for (i = 15; s->model_name[i] == ' ' && i >= 0; i--) 1208141cc406Sopenharmony_ci s->model_name[i] = 0; 1209141cc406Sopenharmony_ci for (i = 3; s->version_name[i] == ' ' && i >= 0; i--) 1210141cc406Sopenharmony_ci s->version_name[i] = 0; 1211141cc406Sopenharmony_ci 1212141cc406Sopenharmony_ci if (strcmp ("FUJITSU", s->vendor_name)) { 1213141cc406Sopenharmony_ci DBG (5, "The device at '%s' is reported to be made by '%s'\n", s->device_name, s->vendor_name); 1214141cc406Sopenharmony_ci DBG (5, "This backend only supports Fujitsu products.\n"); 1215141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1216141cc406Sopenharmony_ci } 1217141cc406Sopenharmony_ci 1218141cc406Sopenharmony_ci DBG (15, "init_inquire: Found %s scanner %s version %s at %s\n", 1219141cc406Sopenharmony_ci s->vendor_name, s->model_name, s->version_name, s->device_name); 1220141cc406Sopenharmony_ci 1221141cc406Sopenharmony_ci /*some scanners list random data here*/ 1222141cc406Sopenharmony_ci DBG (15, "inquiry options\n"); 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci s->color_raster_offset = get_IN_color_offset(in); 1225141cc406Sopenharmony_ci DBG (15, " color offset: %d lines\n",s->color_raster_offset); 1226141cc406Sopenharmony_ci 1227141cc406Sopenharmony_ci /* FIXME: we don't store all of these? */ 1228141cc406Sopenharmony_ci DBG (15, " long gray scan: %d\n",get_IN_long_gray(in)); 1229141cc406Sopenharmony_ci DBG (15, " long color scan: %d\n",get_IN_long_color(in)); 1230141cc406Sopenharmony_ci 1231141cc406Sopenharmony_ci DBG (15, " emulation mode: %d\n",get_IN_emulation(in)); 1232141cc406Sopenharmony_ci DBG (15, " CMP/CGA: %d\n",get_IN_cmp_cga(in)); 1233141cc406Sopenharmony_ci DBG (15, " background back: %d\n",get_IN_bg_back(in)); 1234141cc406Sopenharmony_ci DBG (15, " background front: %d\n",get_IN_bg_front(in)); 1235141cc406Sopenharmony_ci DBG (15, " background fb: %d\n",get_IN_bg_fb(in)); 1236141cc406Sopenharmony_ci DBG (15, " back only scan: %d\n",get_IN_has_back(in)); 1237141cc406Sopenharmony_ci 1238141cc406Sopenharmony_ci s->duplex_raster_offset = get_IN_duplex_offset(in); 1239141cc406Sopenharmony_ci DBG (15, " duplex offset: %d lines\n",s->duplex_raster_offset); 1240141cc406Sopenharmony_ci 1241141cc406Sopenharmony_ci DBG (10, "init_inquire: finish\n"); 1242141cc406Sopenharmony_ci 1243141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1244141cc406Sopenharmony_ci} 1245141cc406Sopenharmony_ci 1246141cc406Sopenharmony_ci/* 1247141cc406Sopenharmony_ci * Use INQUIRY VPD to setup more detail about the scanner 1248141cc406Sopenharmony_ci */ 1249141cc406Sopenharmony_cistatic SANE_Status 1250141cc406Sopenharmony_ciinit_vpd (struct fujitsu *s) 1251141cc406Sopenharmony_ci{ 1252141cc406Sopenharmony_ci SANE_Status ret; 1253141cc406Sopenharmony_ci 1254141cc406Sopenharmony_ci unsigned char cmd[INQUIRY_len]; 1255141cc406Sopenharmony_ci size_t cmdLen = INQUIRY_len; 1256141cc406Sopenharmony_ci 1257141cc406Sopenharmony_ci unsigned char in[INQUIRY_vpd_len]; 1258141cc406Sopenharmony_ci size_t inLen = INQUIRY_vpd_len; 1259141cc406Sopenharmony_ci 1260141cc406Sopenharmony_ci int payload_len, payload_off; 1261141cc406Sopenharmony_ci 1262141cc406Sopenharmony_ci DBG (10, "init_vpd: start\n"); 1263141cc406Sopenharmony_ci 1264141cc406Sopenharmony_ci /* get EVPD */ 1265141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 1266141cc406Sopenharmony_ci set_SCSI_opcode(cmd, INQUIRY_code); 1267141cc406Sopenharmony_ci set_IN_return_size (cmd, inLen); 1268141cc406Sopenharmony_ci set_IN_evpd (cmd, 1); 1269141cc406Sopenharmony_ci set_IN_page_code (cmd, 0xf0); 1270141cc406Sopenharmony_ci 1271141cc406Sopenharmony_ci ret = do_cmd ( 1272141cc406Sopenharmony_ci s, 1, 0, 1273141cc406Sopenharmony_ci cmd, cmdLen, 1274141cc406Sopenharmony_ci NULL, 0, 1275141cc406Sopenharmony_ci in, &inLen 1276141cc406Sopenharmony_ci ); 1277141cc406Sopenharmony_ci 1278141cc406Sopenharmony_ci /*FIXME no vpd, set some defaults? */ 1279141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD && ret != SANE_STATUS_EOF) { 1280141cc406Sopenharmony_ci DBG (5, "init_vpd: Your scanner does not support VPD?\n"); 1281141cc406Sopenharmony_ci DBG (5, "init_vpd: Please contact kitno455 at gmail dot com\n"); 1282141cc406Sopenharmony_ci DBG (5, "init_vpd: with details of your scanner model.\n"); 1283141cc406Sopenharmony_ci return ret; 1284141cc406Sopenharmony_ci } 1285141cc406Sopenharmony_ci 1286141cc406Sopenharmony_ci /* In byte 4, the scanner sends the length of the remainder of 1287141cc406Sopenharmony_ci * the payload. But, this value is often bogus. */ 1288141cc406Sopenharmony_ci payload_len = get_IN_page_length(in); 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci DBG (15, "init_vpd: length=%0x\n", payload_len); 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci /* M3099 gives all data, but wrong length */ 1293141cc406Sopenharmony_ci if (strstr (s->model_name, "M3099") && payload_len == 0x19){ 1294141cc406Sopenharmony_ci DBG (5, "init_vpd: M3099 repair\n"); 1295141cc406Sopenharmony_ci payload_len = 0x5f; 1296141cc406Sopenharmony_ci } 1297141cc406Sopenharmony_ci 1298141cc406Sopenharmony_ci /* M3097G has short vpd, fill in missing part */ 1299141cc406Sopenharmony_ci else if (strstr (s->model_name, "M3097G") && payload_len == 0x19){ 1300141cc406Sopenharmony_ci unsigned char vpd3097g[] = { 1301141cc406Sopenharmony_ci0, 0, 1302141cc406Sopenharmony_ci0xc2, 0x08, 0, 0, 0, 0, 0, 0, 0xed, 0xbf, 0, 0, 0, 0, 0, 0, 1303141cc406Sopenharmony_ci0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1304141cc406Sopenharmony_ci0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1305141cc406Sopenharmony_ci0, 0, 0xff, 0xff, 0xff, 0, 0x45, 0x35, 0, 0xe0, 0, 0, 0, 0, 0, 0, 1306141cc406Sopenharmony_ci0, 0, 0, 0 1307141cc406Sopenharmony_ci }; 1308141cc406Sopenharmony_ci 1309141cc406Sopenharmony_ci DBG (5, "init_vpd: M3097G repair\n"); 1310141cc406Sopenharmony_ci payload_len = 0x5f; 1311141cc406Sopenharmony_ci memcpy(in+0x1e,vpd3097g,sizeof(vpd3097g)); 1312141cc406Sopenharmony_ci 1313141cc406Sopenharmony_ci /*IPC*/ 1314141cc406Sopenharmony_ci if(strstr (s->model_name, "i")){ 1315141cc406Sopenharmony_ci DBG (5, "init_vpd: M3097G IPC repair\n"); 1316141cc406Sopenharmony_ci 1317141cc406Sopenharmony_ci /*subwin cmd*/ 1318141cc406Sopenharmony_ci in[0x2b] = 1; 1319141cc406Sopenharmony_ci 1320141cc406Sopenharmony_ci /*rif/dtc/sdtc/outline/emph/sep/mirr/wlf*/ 1321141cc406Sopenharmony_ci in[0x58] = 0xff; 1322141cc406Sopenharmony_ci 1323141cc406Sopenharmony_ci /*subwin/diffusion*/ 1324141cc406Sopenharmony_ci in[0x59] = 0xc0; 1325141cc406Sopenharmony_ci } 1326141cc406Sopenharmony_ci 1327141cc406Sopenharmony_ci /*CMP*/ 1328141cc406Sopenharmony_ci if(strstr (s->model_name, "m")){ 1329141cc406Sopenharmony_ci DBG (5, "init_vpd: M3097G CMP repair\n"); 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci /*4megs*/ 1332141cc406Sopenharmony_ci in[0x23] = 0x40; 1333141cc406Sopenharmony_ci 1334141cc406Sopenharmony_ci /*mh/mr/mmr*/ 1335141cc406Sopenharmony_ci in[0x5a] = 0xe0; 1336141cc406Sopenharmony_ci } 1337141cc406Sopenharmony_ci } 1338141cc406Sopenharmony_ci 1339141cc406Sopenharmony_ci /* all other known scanners have at least 0x5f, 1340141cc406Sopenharmony_ci * less would require software changes like above */ 1341141cc406Sopenharmony_ci else if (payload_len < 0x5f) { 1342141cc406Sopenharmony_ci DBG (5, "init_vpd: Your scanner supports only partial VPD?\n"); 1343141cc406Sopenharmony_ci DBG (5, "init_vpd: Please contact kitno455 at gmail dot com\n"); 1344141cc406Sopenharmony_ci DBG (5, "init_vpd: with details of your scanner model.\n"); 1345141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1346141cc406Sopenharmony_ci } 1347141cc406Sopenharmony_ci 1348141cc406Sopenharmony_ci /* Special case- some scanners will under-report the amount of 1349141cc406Sopenharmony_ci * valid vpd that they send, and return the default length. 1350141cc406Sopenharmony_ci * Adding 4 more bytes allows us to include the overscan info. 1351141cc406Sopenharmony_ci * Scanners that don't support overscan seem to have all zeros 1352141cc406Sopenharmony_ci * in these bytes, so no harm is done. 1353141cc406Sopenharmony_ci * This may be an 'off-by-four' error in the firmware. */ 1354141cc406Sopenharmony_ci else if (payload_len == 0x5f){ 1355141cc406Sopenharmony_ci payload_len += 4; 1356141cc406Sopenharmony_ci } 1357141cc406Sopenharmony_ci 1358141cc406Sopenharmony_ci /* Having an offset from the beginning of the payload 1359141cc406Sopenharmony_ci * is more useful than from byte 4, as that matches the 1360141cc406Sopenharmony_ci * documentation more closely. */ 1361141cc406Sopenharmony_ci payload_off = payload_len + 4; 1362141cc406Sopenharmony_ci 1363141cc406Sopenharmony_ci /* everything that appears in bytes 0 to 0x1d */ 1364141cc406Sopenharmony_ci DBG (15, "standard options\n"); 1365141cc406Sopenharmony_ci 1366141cc406Sopenharmony_ci s->basic_x_res = get_IN_basic_x_res (in); 1367141cc406Sopenharmony_ci DBG (15, " basic x res: %d dpi\n",s->basic_x_res); 1368141cc406Sopenharmony_ci 1369141cc406Sopenharmony_ci s->basic_y_res = get_IN_basic_y_res (in); 1370141cc406Sopenharmony_ci DBG (15, " basic y res: %d dpi\n",s->basic_y_res); 1371141cc406Sopenharmony_ci 1372141cc406Sopenharmony_ci s->step_x_res[MODE_LINEART] = get_IN_step_x_res (in); 1373141cc406Sopenharmony_ci DBG (15, " step x res: %d dpi\n", s->step_x_res[MODE_LINEART]); 1374141cc406Sopenharmony_ci 1375141cc406Sopenharmony_ci s->step_y_res[MODE_LINEART] = get_IN_step_y_res (in); 1376141cc406Sopenharmony_ci DBG (15, " step y res: %d dpi\n", s->step_y_res[MODE_LINEART]); 1377141cc406Sopenharmony_ci 1378141cc406Sopenharmony_ci s->max_x_res = get_IN_max_x_res (in); 1379141cc406Sopenharmony_ci DBG (15, " max x res: %d dpi\n", s->max_x_res); 1380141cc406Sopenharmony_ci 1381141cc406Sopenharmony_ci s->max_y_res = get_IN_max_y_res (in); 1382141cc406Sopenharmony_ci DBG (15, " max y res: %d dpi\n", s->max_y_res); 1383141cc406Sopenharmony_ci 1384141cc406Sopenharmony_ci s->min_x_res = get_IN_min_x_res (in); 1385141cc406Sopenharmony_ci DBG (15, " min x res: %d dpi\n", s->min_x_res); 1386141cc406Sopenharmony_ci 1387141cc406Sopenharmony_ci s->min_y_res = get_IN_min_y_res (in); 1388141cc406Sopenharmony_ci DBG (15, " min y res: %d dpi\n", s->min_y_res); 1389141cc406Sopenharmony_ci 1390141cc406Sopenharmony_ci /* some scanners list B&W resolutions. */ 1391141cc406Sopenharmony_ci s->std_res[0] = get_IN_std_res_60 (in); 1392141cc406Sopenharmony_ci DBG (15, " 60 dpi: %d\n", s->std_res[0]); 1393141cc406Sopenharmony_ci 1394141cc406Sopenharmony_ci s->std_res[1] = get_IN_std_res_75 (in); 1395141cc406Sopenharmony_ci DBG (15, " 75 dpi: %d\n", s->std_res[1]); 1396141cc406Sopenharmony_ci 1397141cc406Sopenharmony_ci s->std_res[2] = get_IN_std_res_100 (in); 1398141cc406Sopenharmony_ci DBG (15, " 100 dpi: %d\n", s->std_res[2]); 1399141cc406Sopenharmony_ci 1400141cc406Sopenharmony_ci s->std_res[3] = get_IN_std_res_120 (in); 1401141cc406Sopenharmony_ci DBG (15, " 120 dpi: %d\n", s->std_res[3]); 1402141cc406Sopenharmony_ci 1403141cc406Sopenharmony_ci s->std_res[4] = get_IN_std_res_150 (in); 1404141cc406Sopenharmony_ci DBG (15, " 150 dpi: %d\n", s->std_res[4]); 1405141cc406Sopenharmony_ci 1406141cc406Sopenharmony_ci s->std_res[5] = get_IN_std_res_160 (in); 1407141cc406Sopenharmony_ci DBG (15, " 160 dpi: %d\n", s->std_res[5]); 1408141cc406Sopenharmony_ci 1409141cc406Sopenharmony_ci s->std_res[6] = get_IN_std_res_180 (in); 1410141cc406Sopenharmony_ci DBG (15, " 180 dpi: %d\n", s->std_res[6]); 1411141cc406Sopenharmony_ci 1412141cc406Sopenharmony_ci s->std_res[7] = get_IN_std_res_200 (in); 1413141cc406Sopenharmony_ci DBG (15, " 200 dpi: %d\n", s->std_res[7]); 1414141cc406Sopenharmony_ci 1415141cc406Sopenharmony_ci s->std_res[8] = get_IN_std_res_240 (in); 1416141cc406Sopenharmony_ci DBG (15, " 240 dpi: %d\n", s->std_res[8]); 1417141cc406Sopenharmony_ci 1418141cc406Sopenharmony_ci s->std_res[9] = get_IN_std_res_300 (in); 1419141cc406Sopenharmony_ci DBG (15, " 300 dpi: %d\n", s->std_res[9]); 1420141cc406Sopenharmony_ci 1421141cc406Sopenharmony_ci s->std_res[10] = get_IN_std_res_320 (in); 1422141cc406Sopenharmony_ci DBG (15, " 320 dpi: %d\n", s->std_res[10]); 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_ci s->std_res[11] = get_IN_std_res_400 (in); 1425141cc406Sopenharmony_ci DBG (15, " 400 dpi: %d\n", s->std_res[11]); 1426141cc406Sopenharmony_ci 1427141cc406Sopenharmony_ci s->std_res[12] = get_IN_std_res_480 (in); 1428141cc406Sopenharmony_ci DBG (15, " 480 dpi: %d\n", s->std_res[12]); 1429141cc406Sopenharmony_ci 1430141cc406Sopenharmony_ci s->std_res[13] = get_IN_std_res_600 (in); 1431141cc406Sopenharmony_ci DBG (15, " 600 dpi: %d\n", s->std_res[13]); 1432141cc406Sopenharmony_ci 1433141cc406Sopenharmony_ci s->std_res[14] = get_IN_std_res_800 (in); 1434141cc406Sopenharmony_ci DBG (15, " 800 dpi: %d\n", s->std_res[14]); 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci s->std_res[15] = get_IN_std_res_1200 (in); 1437141cc406Sopenharmony_ci DBG (15, " 1200 dpi: %d\n", s->std_res[15]); 1438141cc406Sopenharmony_ci 1439141cc406Sopenharmony_ci /* maximum window width and length are reported in basic units.*/ 1440141cc406Sopenharmony_ci s->max_x_basic = get_IN_window_width(in); 1441141cc406Sopenharmony_ci DBG(15, " max width: %2.2f inches\n",(float)s->max_x_basic/s->basic_x_res); 1442141cc406Sopenharmony_ci 1443141cc406Sopenharmony_ci s->max_y_basic = get_IN_window_length(in); 1444141cc406Sopenharmony_ci DBG(15, " max length: %2.2f inches\n",(float)s->max_y_basic/s->basic_y_res); 1445141cc406Sopenharmony_ci 1446141cc406Sopenharmony_ci /* known modes */ 1447141cc406Sopenharmony_ci s->can_overflow = get_IN_overflow(in); 1448141cc406Sopenharmony_ci DBG (15, " overflow: %d\n", s->can_overflow); 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_ci s->can_mode[MODE_LINEART] = get_IN_monochrome (in); 1451141cc406Sopenharmony_ci DBG (15, " monochrome: %d\n", s->can_mode[MODE_LINEART]); 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci s->can_mode[MODE_HALFTONE] = get_IN_half_tone (in); 1454141cc406Sopenharmony_ci DBG (15, " halftone: %d\n", s->can_mode[MODE_HALFTONE]); 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ci s->can_mode[MODE_GRAYSCALE] = get_IN_multilevel (in); 1457141cc406Sopenharmony_ci DBG (15, " grayscale: %d\n", s->can_mode[MODE_GRAYSCALE]); 1458141cc406Sopenharmony_ci 1459141cc406Sopenharmony_ci DBG (15, " color_monochrome: %d\n", get_IN_monochrome_rgb(in)); 1460141cc406Sopenharmony_ci DBG (15, " color_halftone: %d\n", get_IN_half_tone_rgb(in)); 1461141cc406Sopenharmony_ci 1462141cc406Sopenharmony_ci s->can_mode[MODE_COLOR] = get_IN_multilevel_rgb (in); 1463141cc406Sopenharmony_ci DBG (15, " color_grayscale: %d\n", s->can_mode[MODE_COLOR]); 1464141cc406Sopenharmony_ci 1465141cc406Sopenharmony_ci /* now we look at vendor specific data in bytes 0x1e onward */ 1466141cc406Sopenharmony_ci DBG (15, "vendor options\n"); 1467141cc406Sopenharmony_ci 1468141cc406Sopenharmony_ci s->has_adf = get_IN_adf(in); 1469141cc406Sopenharmony_ci DBG (15, " adf: %d\n", s->has_adf); 1470141cc406Sopenharmony_ci 1471141cc406Sopenharmony_ci s->has_flatbed = get_IN_flatbed(in); 1472141cc406Sopenharmony_ci DBG (15, " flatbed: %d\n", s->has_flatbed); 1473141cc406Sopenharmony_ci 1474141cc406Sopenharmony_ci s->has_transparency = get_IN_transparency(in); 1475141cc406Sopenharmony_ci DBG (15, " transparency: %d\n", s->has_transparency); 1476141cc406Sopenharmony_ci 1477141cc406Sopenharmony_ci s->has_duplex = get_IN_duplex(in); 1478141cc406Sopenharmony_ci s->has_back = s->has_duplex; 1479141cc406Sopenharmony_ci DBG (15, " duplex: %d\n", s->has_duplex); 1480141cc406Sopenharmony_ci 1481141cc406Sopenharmony_ci s->has_endorser_b = get_IN_endorser_b(in); 1482141cc406Sopenharmony_ci DBG (15, " back endorser: %d\n", s->has_endorser_b); 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci s->has_barcode = get_IN_barcode(in); 1485141cc406Sopenharmony_ci DBG (15, " barcode: %d\n", s->has_barcode); 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci s->has_operator_panel = get_IN_operator_panel(in); 1488141cc406Sopenharmony_ci DBG (15, " operator panel: %d\n", s->has_operator_panel); 1489141cc406Sopenharmony_ci 1490141cc406Sopenharmony_ci s->has_endorser_f = get_IN_endorser_f(in); 1491141cc406Sopenharmony_ci DBG (15, " front endorser: %d\n", s->has_endorser_f); 1492141cc406Sopenharmony_ci 1493141cc406Sopenharmony_ci DBG (15, " multi-purpose stacker: %d\n", get_IN_mp_stacker(in)); 1494141cc406Sopenharmony_ci 1495141cc406Sopenharmony_ci DBG (15, " prepick: %d\n", get_IN_prepick(in)); 1496141cc406Sopenharmony_ci DBG (15, " mf detect: %d\n", get_IN_mf_detect(in)); 1497141cc406Sopenharmony_ci 1498141cc406Sopenharmony_ci s->has_paper_protect = get_IN_paperprot(in); 1499141cc406Sopenharmony_ci DBG (15, " paper protection: %d\n", s->has_paper_protect); 1500141cc406Sopenharmony_ci 1501141cc406Sopenharmony_ci s->adbits = get_IN_adbits(in); 1502141cc406Sopenharmony_ci DBG (15, " A/D bits: %d\n",s->adbits); 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci s->buffer_bytes = get_IN_buffer_bytes(in); 1505141cc406Sopenharmony_ci DBG (15, " buffer bytes: %d\n",s->buffer_bytes); 1506141cc406Sopenharmony_ci 1507141cc406Sopenharmony_ci DBG (15, "Standard commands\n"); 1508141cc406Sopenharmony_ci 1509141cc406Sopenharmony_ci /* std scsi command support byte 26*/ 1510141cc406Sopenharmony_ci s->has_cmd_msen10 = get_IN_has_cmd_msen10(in); 1511141cc406Sopenharmony_ci DBG (15, " mode_sense_10 cmd: %d\n", s->has_cmd_msen10); 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_ci s->has_cmd_msel10 = get_IN_has_cmd_msel10(in); 1514141cc406Sopenharmony_ci DBG (15, " mode_select_10 cmd: %d\n", s->has_cmd_msel10); 1515141cc406Sopenharmony_ci 1516141cc406Sopenharmony_ci /* std scsi command support byte 27*/ 1517141cc406Sopenharmony_ci s->has_cmd_lsen = get_IN_has_cmd_lsen(in); 1518141cc406Sopenharmony_ci DBG (15, " log_sense cmd: %d\n", s->has_cmd_lsen); 1519141cc406Sopenharmony_ci 1520141cc406Sopenharmony_ci s->has_cmd_lsel = get_IN_has_cmd_lsel(in); 1521141cc406Sopenharmony_ci DBG (15, " log_select cmd: %d\n", s->has_cmd_lsel); 1522141cc406Sopenharmony_ci 1523141cc406Sopenharmony_ci s->has_cmd_change = get_IN_has_cmd_change(in); 1524141cc406Sopenharmony_ci DBG (15, " change cmd: %d\n", s->has_cmd_change); 1525141cc406Sopenharmony_ci 1526141cc406Sopenharmony_ci s->has_cmd_rbuff = get_IN_has_cmd_rbuff(in); 1527141cc406Sopenharmony_ci DBG (15, " read_buffer cmd: %d\n", s->has_cmd_rbuff); 1528141cc406Sopenharmony_ci 1529141cc406Sopenharmony_ci s->has_cmd_wbuff = get_IN_has_cmd_wbuff(in); 1530141cc406Sopenharmony_ci DBG (15, " write_buffer cmd: %d\n", s->has_cmd_wbuff); 1531141cc406Sopenharmony_ci 1532141cc406Sopenharmony_ci s->has_cmd_cav = get_IN_has_cmd_cav(in); 1533141cc406Sopenharmony_ci DBG (15, " copy_and_verify cmd: %d\n", s->has_cmd_cav); 1534141cc406Sopenharmony_ci 1535141cc406Sopenharmony_ci s->has_cmd_comp = get_IN_has_cmd_comp(in); 1536141cc406Sopenharmony_ci DBG (15, " compare cmd: %d\n", s->has_cmd_comp); 1537141cc406Sopenharmony_ci 1538141cc406Sopenharmony_ci s->has_cmd_gdbs = get_IN_has_cmd_gdbs(in); 1539141cc406Sopenharmony_ci DBG (15, " get_d_b_status cmd: %d\n", s->has_cmd_gdbs); 1540141cc406Sopenharmony_ci 1541141cc406Sopenharmony_ci /* std scsi command support byte 28*/ 1542141cc406Sopenharmony_ci s->has_cmd_op = get_IN_has_cmd_op(in); 1543141cc406Sopenharmony_ci DBG (15, " object_pos cmd: %d\n", s->has_cmd_op); 1544141cc406Sopenharmony_ci 1545141cc406Sopenharmony_ci s->has_cmd_send = get_IN_has_cmd_send(in); 1546141cc406Sopenharmony_ci DBG (15, " send cmd: %d\n", s->has_cmd_send); 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci s->has_cmd_read = get_IN_has_cmd_read(in); 1549141cc406Sopenharmony_ci DBG (15, " read cmd: %d\n", s->has_cmd_read); 1550141cc406Sopenharmony_ci 1551141cc406Sopenharmony_ci s->has_cmd_gwin = get_IN_has_cmd_gwin(in); 1552141cc406Sopenharmony_ci DBG (15, " get_window cmd: %d\n", s->has_cmd_gwin); 1553141cc406Sopenharmony_ci 1554141cc406Sopenharmony_ci s->has_cmd_swin = get_IN_has_cmd_swin(in); 1555141cc406Sopenharmony_ci DBG (15, " set_window cmd: %d\n", s->has_cmd_swin); 1556141cc406Sopenharmony_ci 1557141cc406Sopenharmony_ci s->has_cmd_sdiag = get_IN_has_cmd_sdiag(in); 1558141cc406Sopenharmony_ci DBG (15, " send_diag cmd: %d\n", s->has_cmd_sdiag); 1559141cc406Sopenharmony_ci 1560141cc406Sopenharmony_ci s->has_cmd_rdiag = get_IN_has_cmd_rdiag(in); 1561141cc406Sopenharmony_ci DBG (15, " read_diag cmd: %d\n", s->has_cmd_rdiag); 1562141cc406Sopenharmony_ci 1563141cc406Sopenharmony_ci s->has_cmd_scan = get_IN_has_cmd_scan(in); 1564141cc406Sopenharmony_ci DBG (15, " scan cmd: %d\n", s->has_cmd_scan); 1565141cc406Sopenharmony_ci 1566141cc406Sopenharmony_ci /* std scsi command support byte 29*/ 1567141cc406Sopenharmony_ci s->has_cmd_msen6 = get_IN_has_cmd_msen6(in); 1568141cc406Sopenharmony_ci DBG (15, " mode_sense_6 cmd: %d\n", s->has_cmd_msen6); 1569141cc406Sopenharmony_ci 1570141cc406Sopenharmony_ci s->has_cmd_copy = get_IN_has_cmd_copy(in); 1571141cc406Sopenharmony_ci DBG (15, " copy cmd: %d\n", s->has_cmd_copy); 1572141cc406Sopenharmony_ci 1573141cc406Sopenharmony_ci s->has_cmd_rel = get_IN_has_cmd_rel(in); 1574141cc406Sopenharmony_ci DBG (15, " release cmd: %d\n", s->has_cmd_rel); 1575141cc406Sopenharmony_ci 1576141cc406Sopenharmony_ci s->has_cmd_runit = get_IN_has_cmd_runit(in); 1577141cc406Sopenharmony_ci DBG (15, " reserve_unit cmd: %d\n", s->has_cmd_runit); 1578141cc406Sopenharmony_ci 1579141cc406Sopenharmony_ci s->has_cmd_msel6 = get_IN_has_cmd_msel6(in); 1580141cc406Sopenharmony_ci DBG (15, " mode_select_6 cmd: %d\n", s->has_cmd_msel6); 1581141cc406Sopenharmony_ci 1582141cc406Sopenharmony_ci s->has_cmd_inq = get_IN_has_cmd_inq(in); 1583141cc406Sopenharmony_ci DBG (15, " inquiry cmd: %d\n", s->has_cmd_inq); 1584141cc406Sopenharmony_ci 1585141cc406Sopenharmony_ci s->has_cmd_rs = get_IN_has_cmd_rs(in); 1586141cc406Sopenharmony_ci DBG (15, " request_sense cmd: %d\n", s->has_cmd_rs); 1587141cc406Sopenharmony_ci 1588141cc406Sopenharmony_ci s->has_cmd_tur = get_IN_has_cmd_tur(in); 1589141cc406Sopenharmony_ci DBG (15, " test_unit_ready cmd: %d\n", s->has_cmd_tur); 1590141cc406Sopenharmony_ci 1591141cc406Sopenharmony_ci /* vendor added scsi command support */ 1592141cc406Sopenharmony_ci /* FIXME: there are more of these... */ 1593141cc406Sopenharmony_ci DBG (15, "Vendor commands\n"); 1594141cc406Sopenharmony_ci 1595141cc406Sopenharmony_ci s->has_cmd_subwindow = get_IN_has_cmd_subwindow(in); 1596141cc406Sopenharmony_ci DBG (15, " subwindow cmd: %d\n", s->has_cmd_subwindow); 1597141cc406Sopenharmony_ci 1598141cc406Sopenharmony_ci s->has_cmd_endorser = get_IN_has_cmd_endorser(in); 1599141cc406Sopenharmony_ci DBG (15, " endorser cmd: %d\n", s->has_cmd_endorser); 1600141cc406Sopenharmony_ci 1601141cc406Sopenharmony_ci s->has_cmd_hw_status = get_IN_has_cmd_hw_status (in); 1602141cc406Sopenharmony_ci DBG (15, " hardware status cmd: %d\n", s->has_cmd_hw_status); 1603141cc406Sopenharmony_ci 1604141cc406Sopenharmony_ci s->has_cmd_hw_status_2 = get_IN_has_cmd_hw_status_2 (in); 1605141cc406Sopenharmony_ci DBG (15, " hardware status 2 cmd: %d\n", s->has_cmd_hw_status_2); 1606141cc406Sopenharmony_ci 1607141cc406Sopenharmony_ci s->has_cmd_hw_status_3 = get_IN_has_cmd_hw_status_3 (in); 1608141cc406Sopenharmony_ci DBG (15, " hardware status 3 cmd: %d\n", s->has_cmd_hw_status_3); 1609141cc406Sopenharmony_ci 1610141cc406Sopenharmony_ci s->has_cmd_scanner_ctl = get_IN_has_cmd_scanner_ctl(in); 1611141cc406Sopenharmony_ci DBG (15, " scanner control cmd: %d\n", s->has_cmd_scanner_ctl); 1612141cc406Sopenharmony_ci 1613141cc406Sopenharmony_ci s->has_cmd_device_restart = get_IN_has_cmd_device_restart(in); 1614141cc406Sopenharmony_ci DBG (15, " device restart cmd: %d\n", s->has_cmd_device_restart); 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci /* get threshold, brightness and contrast ranges. */ 1617141cc406Sopenharmony_ci s->brightness_steps = get_IN_brightness_steps(in); 1618141cc406Sopenharmony_ci DBG (15, " brightness steps: %d\n", s->brightness_steps); 1619141cc406Sopenharmony_ci 1620141cc406Sopenharmony_ci s->threshold_steps = get_IN_threshold_steps(in); 1621141cc406Sopenharmony_ci DBG (15, " threshold steps: %d\n", s->threshold_steps); 1622141cc406Sopenharmony_ci 1623141cc406Sopenharmony_ci s->contrast_steps = get_IN_contrast_steps(in); 1624141cc406Sopenharmony_ci DBG (15, " contrast steps: %d\n", s->contrast_steps); 1625141cc406Sopenharmony_ci 1626141cc406Sopenharmony_ci /* dither/gamma patterns */ 1627141cc406Sopenharmony_ci s->num_internal_gamma = get_IN_num_gamma_internal (in); 1628141cc406Sopenharmony_ci DBG (15, " built in gamma patterns: %d\n", s->num_internal_gamma); 1629141cc406Sopenharmony_ci 1630141cc406Sopenharmony_ci s->num_download_gamma = get_IN_num_gamma_download (in); 1631141cc406Sopenharmony_ci DBG (15, " download gamma patterns: %d\n", s->num_download_gamma); 1632141cc406Sopenharmony_ci 1633141cc406Sopenharmony_ci s->num_internal_dither = get_IN_num_dither_internal (in); 1634141cc406Sopenharmony_ci DBG (15, " built in dither patterns: %d\n", s->num_internal_dither); 1635141cc406Sopenharmony_ci 1636141cc406Sopenharmony_ci s->num_download_dither = get_IN_num_dither_download (in); 1637141cc406Sopenharmony_ci DBG (15, " download dither patterns: %d\n", s->num_download_dither); 1638141cc406Sopenharmony_ci 1639141cc406Sopenharmony_ci /* ipc functions */ 1640141cc406Sopenharmony_ci s->has_rif = get_IN_ipc_bw_rif (in); 1641141cc406Sopenharmony_ci DBG (15, " RIF: %d\n", s->has_rif); 1642141cc406Sopenharmony_ci 1643141cc406Sopenharmony_ci s->has_dtc = get_IN_ipc_dtc(in); 1644141cc406Sopenharmony_ci DBG (15, " DTC (AutoI): %d\n", s->has_dtc); 1645141cc406Sopenharmony_ci 1646141cc406Sopenharmony_ci s->has_sdtc = get_IN_ipc_sdtc(in); 1647141cc406Sopenharmony_ci DBG (15, " SDTC (AutoII): %d\n", s->has_sdtc); 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci s->has_outline = get_IN_ipc_outline_extraction (in); 1650141cc406Sopenharmony_ci DBG (15, " outline extraction: %d\n", s->has_outline); 1651141cc406Sopenharmony_ci 1652141cc406Sopenharmony_ci s->has_emphasis = get_IN_ipc_image_emphasis (in); 1653141cc406Sopenharmony_ci DBG (15, " image emphasis: %d\n", s->has_emphasis); 1654141cc406Sopenharmony_ci 1655141cc406Sopenharmony_ci s->has_autosep = get_IN_ipc_auto_separation (in); 1656141cc406Sopenharmony_ci DBG (15, " automatic separation: %d\n", s->has_autosep); 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci s->has_mirroring = get_IN_ipc_mirroring (in); 1659141cc406Sopenharmony_ci DBG (15, " mirror image: %d\n", s->has_mirroring); 1660141cc406Sopenharmony_ci 1661141cc406Sopenharmony_ci s->has_wl_follow = get_IN_ipc_wl_follow (in); 1662141cc406Sopenharmony_ci DBG (15, " white level follower: %d\n", s->has_wl_follow); 1663141cc406Sopenharmony_ci 1664141cc406Sopenharmony_ci /* byte 58 */ 1665141cc406Sopenharmony_ci s->has_subwindow = get_IN_ipc_subwindow (in); 1666141cc406Sopenharmony_ci DBG (15, " subwindow: %d\n", s->has_subwindow); 1667141cc406Sopenharmony_ci 1668141cc406Sopenharmony_ci s->has_diffusion = get_IN_ipc_diffusion (in); 1669141cc406Sopenharmony_ci DBG (15, " diffusion: %d\n", s->has_diffusion); 1670141cc406Sopenharmony_ci 1671141cc406Sopenharmony_ci s->has_ipc3 = get_IN_ipc_ipc3 (in); 1672141cc406Sopenharmony_ci DBG (15, " ipc3: %d\n", s->has_ipc3); 1673141cc406Sopenharmony_ci 1674141cc406Sopenharmony_ci s->has_rotation = get_IN_ipc_rotation (in); 1675141cc406Sopenharmony_ci DBG (15, " rotation: %d\n", s->has_rotation); 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci s->has_hybrid_crop_deskew = get_IN_ipc_hybrid_crop_deskew(in); 1678141cc406Sopenharmony_ci DBG (15, " hybrid crop deskew: %d\n", s->has_hybrid_crop_deskew); 1679141cc406Sopenharmony_ci 1680141cc406Sopenharmony_ci /* this one is weird, overrides the payload length from scanner */ 1681141cc406Sopenharmony_ci DBG (15, " vpd extends to byte 6f: %d\n", get_IN_vpd_thru_byte_6f(in)); 1682141cc406Sopenharmony_ci if(get_IN_vpd_thru_byte_6f(in) && payload_off < 0x6f){ 1683141cc406Sopenharmony_ci payload_off = 0x6f; 1684141cc406Sopenharmony_ci } 1685141cc406Sopenharmony_ci 1686141cc406Sopenharmony_ci /* compression modes */ 1687141cc406Sopenharmony_ci s->has_comp_MH = get_IN_compression_MH (in); 1688141cc406Sopenharmony_ci DBG (15, " compression MH: %d\n", s->has_comp_MH); 1689141cc406Sopenharmony_ci 1690141cc406Sopenharmony_ci s->has_comp_MR = get_IN_compression_MR (in); 1691141cc406Sopenharmony_ci DBG (15, " compression MR: %d\n", s->has_comp_MR); 1692141cc406Sopenharmony_ci 1693141cc406Sopenharmony_ci s->has_comp_MMR = get_IN_compression_MMR (in); 1694141cc406Sopenharmony_ci DBG (15, " compression MMR: %d\n", s->has_comp_MMR); 1695141cc406Sopenharmony_ci 1696141cc406Sopenharmony_ci s->has_comp_JBIG = get_IN_compression_JBIG (in); 1697141cc406Sopenharmony_ci DBG (15, " compression JBIG: %d\n", s->has_comp_JBIG); 1698141cc406Sopenharmony_ci 1699141cc406Sopenharmony_ci s->has_comp_JPG1 = get_IN_compression_JPG_BASE (in); 1700141cc406Sopenharmony_ci DBG (15, " compression JPG1: %d\n", s->has_comp_JPG1); 1701141cc406Sopenharmony_ci#ifdef SANE_JPEG_DISABLED 1702141cc406Sopenharmony_ci DBG (15, " (Disabled)\n"); 1703141cc406Sopenharmony_ci#endif 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci s->has_comp_JPG2 = get_IN_compression_JPG_EXT (in); 1706141cc406Sopenharmony_ci DBG (15, " compression JPG2: %d\n", s->has_comp_JPG2); 1707141cc406Sopenharmony_ci 1708141cc406Sopenharmony_ci s->has_comp_JPG3 = get_IN_compression_JPG_INDEP (in); 1709141cc406Sopenharmony_ci DBG (15, " compression JPG3: %d\n", s->has_comp_JPG3); 1710141cc406Sopenharmony_ci 1711141cc406Sopenharmony_ci /* FIXME: we don't store these? */ 1712141cc406Sopenharmony_ci DBG (15, " back endorser mech: %d\n", get_IN_endorser_b_mech(in)); 1713141cc406Sopenharmony_ci DBG (15, " back endorser stamp: %d\n", get_IN_endorser_b_stamp(in)); 1714141cc406Sopenharmony_ci DBG (15, " back endorser elec: %d\n", get_IN_endorser_b_elec(in)); 1715141cc406Sopenharmony_ci DBG (15, " endorser max id: %d\n", get_IN_endorser_max_id(in)); 1716141cc406Sopenharmony_ci 1717141cc406Sopenharmony_ci DBG (15, " front endorser mech: %d\n", get_IN_endorser_f_mech(in)); 1718141cc406Sopenharmony_ci DBG (15, " front endorser stamp: %d\n", get_IN_endorser_f_stamp(in)); 1719141cc406Sopenharmony_ci DBG (15, " front endorser elec: %d\n", get_IN_endorser_f_elec(in)); 1720141cc406Sopenharmony_ci 1721141cc406Sopenharmony_ci s->endorser_type_b = get_IN_endorser_b_type(in); 1722141cc406Sopenharmony_ci DBG (15, " back endorser type: %d\n", s->endorser_type_b); 1723141cc406Sopenharmony_ci 1724141cc406Sopenharmony_ci s->endorser_type_f = get_IN_endorser_f_type(in); 1725141cc406Sopenharmony_ci DBG (15, " back endorser type: %d\n", s->endorser_type_f); 1726141cc406Sopenharmony_ci 1727141cc406Sopenharmony_ci DBG (15, " connection type: %d\n", get_IN_connection(in)); 1728141cc406Sopenharmony_ci 1729141cc406Sopenharmony_ci DBG (15, " endorser ext: %d\n", get_IN_endorser_type_ext(in)); 1730141cc406Sopenharmony_ci DBG (15, " endorser pr_b: %d\n", get_IN_endorser_pre_back(in)); 1731141cc406Sopenharmony_ci DBG (15, " endorser pr_f: %d\n", get_IN_endorser_pre_front(in)); 1732141cc406Sopenharmony_ci DBG (15, " endorser po_b: %d\n", get_IN_endorser_post_back(in)); 1733141cc406Sopenharmony_ci DBG (15, " endorser po_f: %d\n", get_IN_endorser_post_front(in)); 1734141cc406Sopenharmony_ci 1735141cc406Sopenharmony_ci s->os_x_basic = get_IN_x_overscan_size(in); 1736141cc406Sopenharmony_ci DBG (15, " horizontal overscan: %d\n", s->os_x_basic); 1737141cc406Sopenharmony_ci 1738141cc406Sopenharmony_ci s->os_y_basic = get_IN_y_overscan_size(in); 1739141cc406Sopenharmony_ci DBG (15, " vertical overscan: %d\n", s->os_y_basic); 1740141cc406Sopenharmony_ci 1741141cc406Sopenharmony_ci /* not all scanners go this far */ 1742141cc406Sopenharmony_ci if (payload_off >= 0x68) { 1743141cc406Sopenharmony_ci DBG (15, " default bg adf b: %d\n", get_IN_default_bg_adf_b(in)); 1744141cc406Sopenharmony_ci DBG (15, " default bg adf f: %d\n", get_IN_default_bg_adf_f(in)); 1745141cc406Sopenharmony_ci DBG (15, " default bg fb: %d\n", get_IN_default_bg_fb(in)); 1746141cc406Sopenharmony_ci } 1747141cc406Sopenharmony_ci 1748141cc406Sopenharmony_ci if (payload_off >= 0x69) { 1749141cc406Sopenharmony_ci DBG (15, " auto color: %d\n", get_IN_auto_color(in)); 1750141cc406Sopenharmony_ci DBG (15, " blank skip: %d\n", get_IN_blank_skip(in)); 1751141cc406Sopenharmony_ci DBG (15, " multi image: %d\n", get_IN_multi_image(in)); 1752141cc406Sopenharmony_ci DBG (15, " f b type indep: %d\n", get_IN_f_b_type_indep(in)); 1753141cc406Sopenharmony_ci DBG (15, " f b res indep: %d\n", get_IN_f_b_res_indep(in)); 1754141cc406Sopenharmony_ci } 1755141cc406Sopenharmony_ci 1756141cc406Sopenharmony_ci if (payload_off >= 0x6a) { 1757141cc406Sopenharmony_ci DBG (15, " dropout spec: %d\n", get_IN_dropout_spec(in)); 1758141cc406Sopenharmony_ci DBG (15, " dropout non: %d\n", get_IN_dropout_non(in)); 1759141cc406Sopenharmony_ci DBG (15, " dropout white: %d\n", get_IN_dropout_white(in)); 1760141cc406Sopenharmony_ci } 1761141cc406Sopenharmony_ci 1762141cc406Sopenharmony_ci if (payload_off >= 0x6d) { 1763141cc406Sopenharmony_ci DBG (15, " skew check: %d\n", get_IN_skew_check(in)); 1764141cc406Sopenharmony_ci DBG (15, " new feed roller: %d\n", get_IN_new_fd_roll(in)); 1765141cc406Sopenharmony_ci s->has_adv_paper_prot = get_IN_paper_prot_2(in); 1766141cc406Sopenharmony_ci DBG (15, " paper protection: %d\n", s->has_adv_paper_prot); 1767141cc406Sopenharmony_ci } 1768141cc406Sopenharmony_ci 1769141cc406Sopenharmony_ci /* this one is weird, overrides the payload length from scanner, 1770141cc406Sopenharmony_ci * but the enlarged area is just null bytes, so we ignore this */ 1771141cc406Sopenharmony_ci if (payload_off >= 0x6f) { 1772141cc406Sopenharmony_ci DBG (15, " extra evpd length: %d\n", get_IN_evpd_len(in)); 1773141cc406Sopenharmony_ci } 1774141cc406Sopenharmony_ci 1775141cc406Sopenharmony_ci if (payload_off >= 0x70) { 1776141cc406Sopenharmony_ci DBG (15, " paper count: %d\n", get_IN_paper_count(in)); 1777141cc406Sopenharmony_ci DBG (15, " paper number: %d\n", get_IN_paper_number(in)); 1778141cc406Sopenharmony_ci DBG (15, " ext send to: %d\n", get_IN_ext_send_to(in)); 1779141cc406Sopenharmony_ci 1780141cc406Sopenharmony_ci s->has_staple_detect = get_IN_staple_det(in); 1781141cc406Sopenharmony_ci DBG (15, " staple det: %d\n", s->has_staple_detect); 1782141cc406Sopenharmony_ci 1783141cc406Sopenharmony_ci DBG (15, " pause host: %d\n", get_IN_pause_host(in)); 1784141cc406Sopenharmony_ci DBG (15, " pause panel: %d\n", get_IN_pause_panel(in)); 1785141cc406Sopenharmony_ci DBG (15, " pause conf: %d\n", get_IN_pause_conf(in)); 1786141cc406Sopenharmony_ci DBG (15, " hq print: %d\n", get_IN_hq_print(in)); 1787141cc406Sopenharmony_ci } 1788141cc406Sopenharmony_ci 1789141cc406Sopenharmony_ci if (payload_off >= 0x71) { 1790141cc406Sopenharmony_ci DBG (15, " ext GHS len: %d\n", get_IN_ext_GHS_len(in)); 1791141cc406Sopenharmony_ci } 1792141cc406Sopenharmony_ci 1793141cc406Sopenharmony_ci if (payload_off >= 0x72) { 1794141cc406Sopenharmony_ci DBG (15, " smbc func: %d\n", get_IN_smbc_func(in)); 1795141cc406Sopenharmony_ci DBG (15, " imprint chk b: %d\n", get_IN_imprint_chk_b(in)); 1796141cc406Sopenharmony_ci DBG (15, " imprint chk f: %d\n", get_IN_imprint_chk_f(in)); 1797141cc406Sopenharmony_ci DBG (15, " force w bg: %d\n", get_IN_force_w_bg(in)); 1798141cc406Sopenharmony_ci 1799141cc406Sopenharmony_ci s->has_df_recovery = get_IN_mf_recover_lvl(in); 1800141cc406Sopenharmony_ci DBG (15, " mf recover lvl: %d\n", s->has_df_recovery); 1801141cc406Sopenharmony_ci } 1802141cc406Sopenharmony_ci 1803141cc406Sopenharmony_ci if (payload_off >= 0x73) { 1804141cc406Sopenharmony_ci DBG (15, " first read time: %d\n", get_IN_first_read_time(in)); 1805141cc406Sopenharmony_ci DBG (15, " div scanning: %d\n", get_IN_div_scanning(in)); 1806141cc406Sopenharmony_ci DBG (15, " start job: %d\n", get_IN_start_job(in)); 1807141cc406Sopenharmony_ci DBG (15, " lifetime log: %d\n", get_IN_lifetime_log(in)); 1808141cc406Sopenharmony_ci DBG (15, " imff save rest: %d\n", get_IN_imff_save_rest(in)); 1809141cc406Sopenharmony_ci DBG (15, " wide scsi type: %d\n", get_IN_wide_scsi_type(in)); 1810141cc406Sopenharmony_ci } 1811141cc406Sopenharmony_ci 1812141cc406Sopenharmony_ci if (payload_off >= 0x74) { 1813141cc406Sopenharmony_ci DBG (15, " lut hybrid crop: %d\n", get_IN_lut_hybrid_crop(in)); 1814141cc406Sopenharmony_ci DBG (15, " over under amt: %d\n", get_IN_over_under_amt(in)); 1815141cc406Sopenharmony_ci DBG (15, " rgb lut: %d\n", get_IN_rgb_lut(in)); 1816141cc406Sopenharmony_ci DBG (15, " num lut dl: %d\n", get_IN_num_lut_dl(in)); 1817141cc406Sopenharmony_ci } 1818141cc406Sopenharmony_ci 1819141cc406Sopenharmony_ci /* Various items below are poorly documented or missing */ 1820141cc406Sopenharmony_ci 1821141cc406Sopenharmony_ci if (payload_off >= 0x76) { 1822141cc406Sopenharmony_ci s->has_off_mode = get_IN_erp_lot6_supp(in); 1823141cc406Sopenharmony_ci DBG (15, " ErP Lot6 (power off timer): %d\n", s->has_off_mode); 1824141cc406Sopenharmony_ci DBG (15, " sync next feed: %d\n", get_IN_sync_next_feed(in)); 1825141cc406Sopenharmony_ci } 1826141cc406Sopenharmony_ci 1827141cc406Sopenharmony_ci if (payload_off >= 0x79) { 1828141cc406Sopenharmony_ci DBG (15, " battery: %d\n", get_IN_battery(in)); 1829141cc406Sopenharmony_ci DBG (15, " battery save: %d\n", get_IN_battery_save(in)); 1830141cc406Sopenharmony_ci DBG (15, " object position reverse: %d\n", get_IN_op_reverse(in)); 1831141cc406Sopenharmony_ci } 1832141cc406Sopenharmony_ci 1833141cc406Sopenharmony_ci if (payload_off >= 0x7a) { 1834141cc406Sopenharmony_ci s->has_op_halt = get_IN_op_halt(in); 1835141cc406Sopenharmony_ci DBG (15, " object position halt: %d\n", s->has_op_halt); 1836141cc406Sopenharmony_ci } 1837141cc406Sopenharmony_ci 1838141cc406Sopenharmony_ci if (payload_off >= 0x7c) { 1839141cc406Sopenharmony_ci s->has_return_path = get_IN_return_path(in); 1840141cc406Sopenharmony_ci DBG (15, " return path (card) scanning: %d\n", s->has_return_path); 1841141cc406Sopenharmony_ci DBG (15, " energy star 3: %d\n", get_IN_energy_star3(in)); 1842141cc406Sopenharmony_ci } 1843141cc406Sopenharmony_ci 1844141cc406Sopenharmony_ci DBG (10, "init_vpd: finish\n"); 1845141cc406Sopenharmony_ci 1846141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1847141cc406Sopenharmony_ci} 1848141cc406Sopenharmony_ci 1849141cc406Sopenharmony_cistatic SANE_Status 1850141cc406Sopenharmony_ciinit_ms(struct fujitsu *s) 1851141cc406Sopenharmony_ci{ 1852141cc406Sopenharmony_ci int ret; 1853141cc406Sopenharmony_ci int oldDbg=0; 1854141cc406Sopenharmony_ci 1855141cc406Sopenharmony_ci unsigned char cmd[MODE_SENSE_len]; 1856141cc406Sopenharmony_ci size_t cmdLen = MODE_SENSE_len; 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci unsigned char in[MODE_SENSE_data_len]; 1859141cc406Sopenharmony_ci size_t inLen = MODE_SENSE_data_len; 1860141cc406Sopenharmony_ci 1861141cc406Sopenharmony_ci DBG (10, "init_ms: start\n"); 1862141cc406Sopenharmony_ci 1863141cc406Sopenharmony_ci if(!s->has_cmd_msen6){ 1864141cc406Sopenharmony_ci DBG (10, "init_ms: unsupported\n"); 1865141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1866141cc406Sopenharmony_ci } 1867141cc406Sopenharmony_ci 1868141cc406Sopenharmony_ci /* some of the following probes will produce errors */ 1869141cc406Sopenharmony_ci /* so we reduce the dbg level to reduce the noise */ 1870141cc406Sopenharmony_ci /* however, if user builds with NDEBUG, we can't do that */ 1871141cc406Sopenharmony_ci /* so we protect the code with the following macro */ 1872141cc406Sopenharmony_ci IF_DBG( oldDbg=DBG_LEVEL; ) 1873141cc406Sopenharmony_ci IF_DBG( if(DBG_LEVEL < 35){ DBG_LEVEL = 0; } ) 1874141cc406Sopenharmony_ci 1875141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 1876141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SENSE_code); 1877141cc406Sopenharmony_ci set_MSEN_xfer_length (cmd, inLen); 1878141cc406Sopenharmony_ci 1879141cc406Sopenharmony_ci if(s->has_MS_autocolor){ 1880141cc406Sopenharmony_ci DBG (35, "init_ms: autocolor\n"); 1881141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_autocolor); 1882141cc406Sopenharmony_ci ret = do_cmd ( 1883141cc406Sopenharmony_ci s, 1, 0, 1884141cc406Sopenharmony_ci cmd, cmdLen, 1885141cc406Sopenharmony_ci NULL, 0, 1886141cc406Sopenharmony_ci in, &inLen 1887141cc406Sopenharmony_ci ); 1888141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1889141cc406Sopenharmony_ci s->has_MS_autocolor=0; 1890141cc406Sopenharmony_ci } 1891141cc406Sopenharmony_ci } 1892141cc406Sopenharmony_ci 1893141cc406Sopenharmony_ci if(s->has_MS_prepick){ 1894141cc406Sopenharmony_ci DBG (35, "init_ms: prepick\n"); 1895141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_prepick); 1896141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 1897141cc406Sopenharmony_ci ret = do_cmd ( 1898141cc406Sopenharmony_ci s, 1, 0, 1899141cc406Sopenharmony_ci cmd, cmdLen, 1900141cc406Sopenharmony_ci NULL, 0, 1901141cc406Sopenharmony_ci in, &inLen 1902141cc406Sopenharmony_ci ); 1903141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1904141cc406Sopenharmony_ci s->has_MS_prepick=0; 1905141cc406Sopenharmony_ci } 1906141cc406Sopenharmony_ci } 1907141cc406Sopenharmony_ci 1908141cc406Sopenharmony_ci if(s->has_MS_sleep){ 1909141cc406Sopenharmony_ci DBG (35, "init_ms: sleep\n"); 1910141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_sleep); 1911141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 1912141cc406Sopenharmony_ci ret = do_cmd ( 1913141cc406Sopenharmony_ci s, 1, 0, 1914141cc406Sopenharmony_ci cmd, cmdLen, 1915141cc406Sopenharmony_ci NULL, 0, 1916141cc406Sopenharmony_ci in, &inLen 1917141cc406Sopenharmony_ci ); 1918141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1919141cc406Sopenharmony_ci s->has_MS_sleep=0; 1920141cc406Sopenharmony_ci } 1921141cc406Sopenharmony_ci } 1922141cc406Sopenharmony_ci 1923141cc406Sopenharmony_ci if(s->has_MS_duplex){ 1924141cc406Sopenharmony_ci DBG (35, "init_ms: duplex\n"); 1925141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_duplex); 1926141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 1927141cc406Sopenharmony_ci ret = do_cmd ( 1928141cc406Sopenharmony_ci s, 1, 0, 1929141cc406Sopenharmony_ci cmd, cmdLen, 1930141cc406Sopenharmony_ci NULL, 0, 1931141cc406Sopenharmony_ci in, &inLen 1932141cc406Sopenharmony_ci ); 1933141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1934141cc406Sopenharmony_ci s->has_MS_duplex=0; 1935141cc406Sopenharmony_ci } 1936141cc406Sopenharmony_ci } 1937141cc406Sopenharmony_ci 1938141cc406Sopenharmony_ci if(s->has_MS_rand){ 1939141cc406Sopenharmony_ci DBG (35, "init_ms: rand\n"); 1940141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_rand); 1941141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 1942141cc406Sopenharmony_ci ret = do_cmd ( 1943141cc406Sopenharmony_ci s, 1, 0, 1944141cc406Sopenharmony_ci cmd, cmdLen, 1945141cc406Sopenharmony_ci NULL, 0, 1946141cc406Sopenharmony_ci in, &inLen 1947141cc406Sopenharmony_ci ); 1948141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1949141cc406Sopenharmony_ci s->has_MS_rand=0; 1950141cc406Sopenharmony_ci } 1951141cc406Sopenharmony_ci } 1952141cc406Sopenharmony_ci 1953141cc406Sopenharmony_ci if(s->has_MS_bg){ 1954141cc406Sopenharmony_ci DBG (35, "init_ms: bg\n"); 1955141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_bg); 1956141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 1957141cc406Sopenharmony_ci ret = do_cmd ( 1958141cc406Sopenharmony_ci s, 1, 0, 1959141cc406Sopenharmony_ci cmd, cmdLen, 1960141cc406Sopenharmony_ci NULL, 0, 1961141cc406Sopenharmony_ci in, &inLen 1962141cc406Sopenharmony_ci ); 1963141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1964141cc406Sopenharmony_ci s->has_MS_bg=0; 1965141cc406Sopenharmony_ci } 1966141cc406Sopenharmony_ci } 1967141cc406Sopenharmony_ci 1968141cc406Sopenharmony_ci if(s->has_MS_df){ 1969141cc406Sopenharmony_ci DBG (35, "init_ms: df\n"); 1970141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_df); 1971141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 1972141cc406Sopenharmony_ci ret = do_cmd ( 1973141cc406Sopenharmony_ci s, 1, 0, 1974141cc406Sopenharmony_ci cmd, cmdLen, 1975141cc406Sopenharmony_ci NULL, 0, 1976141cc406Sopenharmony_ci in, &inLen 1977141cc406Sopenharmony_ci ); 1978141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1979141cc406Sopenharmony_ci s->has_MS_df=0; 1980141cc406Sopenharmony_ci } 1981141cc406Sopenharmony_ci } 1982141cc406Sopenharmony_ci 1983141cc406Sopenharmony_ci if(s->has_MS_dropout){ 1984141cc406Sopenharmony_ci DBG (35, "init_ms: dropout\n"); 1985141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_dropout); 1986141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 1987141cc406Sopenharmony_ci ret = do_cmd ( 1988141cc406Sopenharmony_ci s, 1, 0, 1989141cc406Sopenharmony_ci cmd, cmdLen, 1990141cc406Sopenharmony_ci NULL, 0, 1991141cc406Sopenharmony_ci in, &inLen 1992141cc406Sopenharmony_ci ); 1993141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 1994141cc406Sopenharmony_ci s->has_MS_dropout=0; 1995141cc406Sopenharmony_ci } 1996141cc406Sopenharmony_ci } 1997141cc406Sopenharmony_ci 1998141cc406Sopenharmony_ci if(s->has_MS_buff){ 1999141cc406Sopenharmony_ci DBG (35, "init_ms: buffer\n"); 2000141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_buff); 2001141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 2002141cc406Sopenharmony_ci ret = do_cmd ( 2003141cc406Sopenharmony_ci s, 1, 0, 2004141cc406Sopenharmony_ci cmd, cmdLen, 2005141cc406Sopenharmony_ci NULL, 0, 2006141cc406Sopenharmony_ci in, &inLen 2007141cc406Sopenharmony_ci ); 2008141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 2009141cc406Sopenharmony_ci s->has_MS_buff=0; 2010141cc406Sopenharmony_ci } 2011141cc406Sopenharmony_ci } 2012141cc406Sopenharmony_ci 2013141cc406Sopenharmony_ci if(s->has_MS_auto){ 2014141cc406Sopenharmony_ci DBG (35, "init_ms: auto\n"); 2015141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_auto); 2016141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 2017141cc406Sopenharmony_ci ret = do_cmd ( 2018141cc406Sopenharmony_ci s, 1, 0, 2019141cc406Sopenharmony_ci cmd, cmdLen, 2020141cc406Sopenharmony_ci NULL, 0, 2021141cc406Sopenharmony_ci in, &inLen 2022141cc406Sopenharmony_ci ); 2023141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 2024141cc406Sopenharmony_ci s->has_MS_auto=0; 2025141cc406Sopenharmony_ci } 2026141cc406Sopenharmony_ci } 2027141cc406Sopenharmony_ci 2028141cc406Sopenharmony_ci if(s->has_MS_lamp){ 2029141cc406Sopenharmony_ci DBG (35, "init_ms: lamp\n"); 2030141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_lamp); 2031141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 2032141cc406Sopenharmony_ci ret = do_cmd ( 2033141cc406Sopenharmony_ci s, 1, 0, 2034141cc406Sopenharmony_ci cmd, cmdLen, 2035141cc406Sopenharmony_ci NULL, 0, 2036141cc406Sopenharmony_ci in, &inLen 2037141cc406Sopenharmony_ci ); 2038141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 2039141cc406Sopenharmony_ci s->has_MS_lamp=0; 2040141cc406Sopenharmony_ci } 2041141cc406Sopenharmony_ci } 2042141cc406Sopenharmony_ci 2043141cc406Sopenharmony_ci if(s->has_MS_jobsep){ 2044141cc406Sopenharmony_ci DBG (35, "init_ms: jobsep\n"); 2045141cc406Sopenharmony_ci set_MSEN_pc(cmd, MS_pc_jobsep); 2046141cc406Sopenharmony_ci inLen = MODE_SENSE_data_len; 2047141cc406Sopenharmony_ci ret = do_cmd ( 2048141cc406Sopenharmony_ci s, 1, 0, 2049141cc406Sopenharmony_ci cmd, cmdLen, 2050141cc406Sopenharmony_ci NULL, 0, 2051141cc406Sopenharmony_ci in, &inLen 2052141cc406Sopenharmony_ci ); 2053141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 2054141cc406Sopenharmony_ci s->has_MS_jobsep=0; 2055141cc406Sopenharmony_ci } 2056141cc406Sopenharmony_ci } 2057141cc406Sopenharmony_ci 2058141cc406Sopenharmony_ci IF_DBG (DBG_LEVEL = oldDbg;) 2059141cc406Sopenharmony_ci 2060141cc406Sopenharmony_ci DBG (15, " autocolor: %d\n", s->has_MS_autocolor); 2061141cc406Sopenharmony_ci DBG (15, " prepick: %d\n", s->has_MS_prepick); 2062141cc406Sopenharmony_ci DBG (15, " sleep: %d\n", s->has_MS_sleep); 2063141cc406Sopenharmony_ci DBG (15, " duplex: %d\n", s->has_MS_duplex); 2064141cc406Sopenharmony_ci DBG (15, " rand: %d\n", s->has_MS_rand); 2065141cc406Sopenharmony_ci DBG (15, " bg: %d\n", s->has_MS_bg); 2066141cc406Sopenharmony_ci DBG (15, " df: %d\n", s->has_MS_df); 2067141cc406Sopenharmony_ci DBG (15, " dropout: %d\n", s->has_MS_dropout); 2068141cc406Sopenharmony_ci DBG (15, " buff: %d\n", s->has_MS_buff); 2069141cc406Sopenharmony_ci DBG (15, " auto: %d\n", s->has_MS_auto); 2070141cc406Sopenharmony_ci DBG (15, " lamp: %d\n", s->has_MS_lamp); 2071141cc406Sopenharmony_ci DBG (15, " jobsep: %d\n", s->has_MS_jobsep); 2072141cc406Sopenharmony_ci 2073141cc406Sopenharmony_ci DBG (10, "init_ms: finish\n"); 2074141cc406Sopenharmony_ci 2075141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2076141cc406Sopenharmony_ci} 2077141cc406Sopenharmony_ci 2078141cc406Sopenharmony_ci/* 2079141cc406Sopenharmony_ci * get model specific info that is not in vpd, and correct 2080141cc406Sopenharmony_ci * errors in vpd data. struct is already initialized to 0. 2081141cc406Sopenharmony_ci */ 2082141cc406Sopenharmony_cistatic SANE_Status 2083141cc406Sopenharmony_ciinit_model (struct fujitsu *s) 2084141cc406Sopenharmony_ci{ 2085141cc406Sopenharmony_ci int i; 2086141cc406Sopenharmony_ci 2087141cc406Sopenharmony_ci DBG (10, "init_model: start\n"); 2088141cc406Sopenharmony_ci 2089141cc406Sopenharmony_ci /* for most scanners these are good defaults */ 2090141cc406Sopenharmony_ci if(s->can_mode[MODE_LINEART] 2091141cc406Sopenharmony_ci || s->can_mode[MODE_HALFTONE] 2092141cc406Sopenharmony_ci || s->can_mode[MODE_GRAYSCALE] 2093141cc406Sopenharmony_ci ){ 2094141cc406Sopenharmony_ci s->has_vuid_mono = 1; 2095141cc406Sopenharmony_ci } 2096141cc406Sopenharmony_ci if(s->can_mode[MODE_COLOR]){ 2097141cc406Sopenharmony_ci s->has_vuid_color = 1; 2098141cc406Sopenharmony_ci } 2099141cc406Sopenharmony_ci 2100141cc406Sopenharmony_ci for(i=MODE_HALFTONE;i<=MODE_COLOR;i++){ 2101141cc406Sopenharmony_ci s->step_x_res[i] = s->step_x_res[MODE_LINEART]; 2102141cc406Sopenharmony_ci s->step_y_res[i] = s->step_y_res[MODE_LINEART]; 2103141cc406Sopenharmony_ci } 2104141cc406Sopenharmony_ci 2105141cc406Sopenharmony_ci s->reverse_by_mode[MODE_LINEART] = 0; 2106141cc406Sopenharmony_ci s->reverse_by_mode[MODE_HALFTONE] = 0; 2107141cc406Sopenharmony_ci s->reverse_by_mode[MODE_GRAYSCALE] = 1; 2108141cc406Sopenharmony_ci s->reverse_by_mode[MODE_COLOR] = 1; 2109141cc406Sopenharmony_ci 2110141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_LINEART] = 8; 2111141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_HALFTONE] = 8; 2112141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_GRAYSCALE] = 1; 2113141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_COLOR] = 1; 2114141cc406Sopenharmony_ci 2115141cc406Sopenharmony_ci /* endorser type tells string length (among other things) */ 2116141cc406Sopenharmony_ci if(s->has_endorser_b){ 2117141cc406Sopenharmony_ci /*old-style is 40 bytes*/ 2118141cc406Sopenharmony_ci if(s->endorser_type_b == ET_OLD){ 2119141cc406Sopenharmony_ci s->endorser_string_len = 40; 2120141cc406Sopenharmony_ci } 2121141cc406Sopenharmony_ci /*short new style is 60 bytes*/ 2122141cc406Sopenharmony_ci else if(s->endorser_type_b == ET_30){ 2123141cc406Sopenharmony_ci s->endorser_string_len = 60; 2124141cc406Sopenharmony_ci } 2125141cc406Sopenharmony_ci /*long new style is 80 bytes*/ 2126141cc406Sopenharmony_ci else if(s->endorser_type_b == ET_40){ 2127141cc406Sopenharmony_ci s->endorser_string_len = 80; 2128141cc406Sopenharmony_ci } 2129141cc406Sopenharmony_ci } 2130141cc406Sopenharmony_ci else if(s->has_endorser_f){ 2131141cc406Sopenharmony_ci /*old-style is 40 bytes*/ 2132141cc406Sopenharmony_ci if(s->endorser_type_f == ET_OLD){ 2133141cc406Sopenharmony_ci s->endorser_string_len = 40; 2134141cc406Sopenharmony_ci } 2135141cc406Sopenharmony_ci /*short new style is 60 bytes*/ 2136141cc406Sopenharmony_ci else if(s->endorser_type_f == ET_30){ 2137141cc406Sopenharmony_ci s->endorser_string_len = 60; 2138141cc406Sopenharmony_ci } 2139141cc406Sopenharmony_ci /*long new style is 80 bytes*/ 2140141cc406Sopenharmony_ci else if(s->endorser_type_f == ET_40){ 2141141cc406Sopenharmony_ci s->endorser_string_len = 80; 2142141cc406Sopenharmony_ci } 2143141cc406Sopenharmony_ci } 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_ci /* convert to 1200dpi units */ 2146141cc406Sopenharmony_ci s->max_x = s->max_x_basic * 1200 / s->basic_x_res; 2147141cc406Sopenharmony_ci s->max_y = s->max_y_basic * 1200 / s->basic_y_res; 2148141cc406Sopenharmony_ci 2149141cc406Sopenharmony_ci /* setup the list with a single choice, in 1200dpi units, at max res */ 2150141cc406Sopenharmony_ci s->max_y_by_res[0].res = s->max_y_res; 2151141cc406Sopenharmony_ci s->max_y_by_res[0].len = s->max_y; 2152141cc406Sopenharmony_ci 2153141cc406Sopenharmony_ci /* assume these are same as adf, override below */ 2154141cc406Sopenharmony_ci s->max_x_fb = s->max_x; 2155141cc406Sopenharmony_ci s->max_y_fb = s->max_y; 2156141cc406Sopenharmony_ci 2157141cc406Sopenharmony_ci /* assume we can do these. we will disable 2158141cc406Sopenharmony_ci * them at runtime if they cannot */ 2159141cc406Sopenharmony_ci s->has_pixelsize = 1; 2160141cc406Sopenharmony_ci s->has_MS_autocolor = 1; 2161141cc406Sopenharmony_ci s->has_MS_prepick = 1; 2162141cc406Sopenharmony_ci s->has_MS_sleep = 1; 2163141cc406Sopenharmony_ci s->has_MS_duplex = 1; 2164141cc406Sopenharmony_ci s->has_MS_rand = 1; 2165141cc406Sopenharmony_ci s->has_MS_bg = 1; 2166141cc406Sopenharmony_ci s->has_MS_df = 1; 2167141cc406Sopenharmony_ci s->has_MS_dropout = 1; 2168141cc406Sopenharmony_ci s->has_MS_buff = 1; 2169141cc406Sopenharmony_ci s->has_MS_auto = 1; 2170141cc406Sopenharmony_ci s->has_MS_lamp = 1; 2171141cc406Sopenharmony_ci s->has_MS_jobsep = 1; 2172141cc406Sopenharmony_ci 2173141cc406Sopenharmony_ci /* these two scanners lie about their capabilities, 2174141cc406Sopenharmony_ci * and/or differ significantly from most other models */ 2175141cc406Sopenharmony_ci if (strstr (s->model_name, "M3091") 2176141cc406Sopenharmony_ci || strstr (s->model_name, "M3092")) { 2177141cc406Sopenharmony_ci 2178141cc406Sopenharmony_ci /* lies */ 2179141cc406Sopenharmony_ci s->has_rif = 1; 2180141cc406Sopenharmony_ci s->has_back = 0; 2181141cc406Sopenharmony_ci s->adbits = 8; 2182141cc406Sopenharmony_ci if (strstr (s->model_name, "M3092")) 2183141cc406Sopenharmony_ci s->has_flatbed = 1; 2184141cc406Sopenharmony_ci 2185141cc406Sopenharmony_ci /*actually does have res range in non-color modes */ 2186141cc406Sopenharmony_ci for(i=MODE_LINEART;i<MODE_COLOR;i++){ 2187141cc406Sopenharmony_ci s->step_x_res[i] = 1; 2188141cc406Sopenharmony_ci s->step_y_res[i] = 1; 2189141cc406Sopenharmony_ci } 2190141cc406Sopenharmony_ci 2191141cc406Sopenharmony_ci /*but the color mode y list is very limited, only 75, 150, 300 (and 600)*/ 2192141cc406Sopenharmony_ci for(i=0;i<16;i++){ 2193141cc406Sopenharmony_ci s->std_res[i] = 0; 2194141cc406Sopenharmony_ci } 2195141cc406Sopenharmony_ci s->std_res[1] = 1; 2196141cc406Sopenharmony_ci s->std_res[4] = 1; 2197141cc406Sopenharmony_ci s->std_res[9] = 1; 2198141cc406Sopenharmony_ci 2199141cc406Sopenharmony_ci /* weirdness */ 2200141cc406Sopenharmony_ci s->has_vuid_3091 = 1; 2201141cc406Sopenharmony_ci s->has_vuid_color = 0; 2202141cc406Sopenharmony_ci s->has_vuid_mono = 0; 2203141cc406Sopenharmony_ci s->has_short_pixelsize = 1; 2204141cc406Sopenharmony_ci 2205141cc406Sopenharmony_ci s->color_interlace = COLOR_INTERLACE_3091; 2206141cc406Sopenharmony_ci s->duplex_interlace = DUPLEX_INTERLACE_3091; 2207141cc406Sopenharmony_ci s->ghs_in_rs = 1; 2208141cc406Sopenharmony_ci 2209141cc406Sopenharmony_ci /* might be inaccurate */ 2210141cc406Sopenharmony_ci s->num_internal_gamma = 1; 2211141cc406Sopenharmony_ci s->num_download_gamma = 0; 2212141cc406Sopenharmony_ci 2213141cc406Sopenharmony_ci s->reverse_by_mode[MODE_LINEART] = 1; 2214141cc406Sopenharmony_ci s->reverse_by_mode[MODE_HALFTONE] = 1; 2215141cc406Sopenharmony_ci s->reverse_by_mode[MODE_GRAYSCALE] = 0; 2216141cc406Sopenharmony_ci s->reverse_by_mode[MODE_COLOR] = 0; 2217141cc406Sopenharmony_ci } 2218141cc406Sopenharmony_ci 2219141cc406Sopenharmony_ci else if (strstr (s->model_name, "M3093")){ 2220141cc406Sopenharmony_ci 2221141cc406Sopenharmony_ci /* lies */ 2222141cc406Sopenharmony_ci s->has_back = 0; 2223141cc406Sopenharmony_ci s->adbits = 8; 2224141cc406Sopenharmony_ci 2225141cc406Sopenharmony_ci /* weirdness */ 2226141cc406Sopenharmony_ci s->duplex_interlace = DUPLEX_INTERLACE_NONE; 2227141cc406Sopenharmony_ci } 2228141cc406Sopenharmony_ci 2229141cc406Sopenharmony_ci else if ( strstr (s->model_name, "M309") 2230141cc406Sopenharmony_ci || strstr (s->model_name, "M409")){ 2231141cc406Sopenharmony_ci 2232141cc406Sopenharmony_ci /* weirdness */ 2233141cc406Sopenharmony_ci s->broken_diag_serial = 1; 2234141cc406Sopenharmony_ci 2235141cc406Sopenharmony_ci /* lies */ 2236141cc406Sopenharmony_ci s->adbits = 8; 2237141cc406Sopenharmony_ci } 2238141cc406Sopenharmony_ci 2239141cc406Sopenharmony_ci else if (strstr (s->model_name, "fi-4120C2") 2240141cc406Sopenharmony_ci || strstr (s->model_name, "fi-4220C2") ) { 2241141cc406Sopenharmony_ci 2242141cc406Sopenharmony_ci /* missing from vpd */ 2243141cc406Sopenharmony_ci s->os_x_basic = 118; 2244141cc406Sopenharmony_ci s->os_y_basic = 118; 2245141cc406Sopenharmony_ci s->max_y_fb = 14032; 2246141cc406Sopenharmony_ci } 2247141cc406Sopenharmony_ci 2248141cc406Sopenharmony_ci else if (strstr (s->model_name, "fi-4220C")){ 2249141cc406Sopenharmony_ci 2250141cc406Sopenharmony_ci /* missing from vpd */ 2251141cc406Sopenharmony_ci s->max_y_fb = 14032; 2252141cc406Sopenharmony_ci } 2253141cc406Sopenharmony_ci 2254141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-4340") 2255141cc406Sopenharmony_ci || strstr (s->model_name, "fi-4750") ) { 2256141cc406Sopenharmony_ci /* weirdness */ 2257141cc406Sopenharmony_ci s->broken_diag_serial = 1; 2258141cc406Sopenharmony_ci } 2259141cc406Sopenharmony_ci 2260141cc406Sopenharmony_ci /* some firmware versions use capital f? */ 2261141cc406Sopenharmony_ci else if (strstr (s->model_name, "Fi-4860") 2262141cc406Sopenharmony_ci || strstr (s->model_name, "fi-4860") ) { 2263141cc406Sopenharmony_ci 2264141cc406Sopenharmony_ci /* weirdness */ 2265141cc406Sopenharmony_ci s->broken_diag_serial = 1; 2266141cc406Sopenharmony_ci 2267141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_LINEART] = 32; 2268141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_HALFTONE] = 32; 2269141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; 2270141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_COLOR] = 4; 2271141cc406Sopenharmony_ci } 2272141cc406Sopenharmony_ci 2273141cc406Sopenharmony_ci /* some firmware versions use capital f? */ 2274141cc406Sopenharmony_ci else if (strstr (s->model_name, "Fi-4990") 2275141cc406Sopenharmony_ci || strstr (s->model_name, "fi-4990") ) { 2276141cc406Sopenharmony_ci 2277141cc406Sopenharmony_ci /* weirdness */ 2278141cc406Sopenharmony_ci s->duplex_interlace = DUPLEX_INTERLACE_NONE; 2279141cc406Sopenharmony_ci s->color_interlace = COLOR_INTERLACE_RRGGBB; 2280141cc406Sopenharmony_ci 2281141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_LINEART] = 32; 2282141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_HALFTONE] = 32; 2283141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; 2284141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_COLOR] = 4; 2285141cc406Sopenharmony_ci } 2286141cc406Sopenharmony_ci 2287141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-5110C")){ 2288141cc406Sopenharmony_ci 2289141cc406Sopenharmony_ci /* missing from vpd */ 2290141cc406Sopenharmony_ci s->os_x_basic = 147; 2291141cc406Sopenharmony_ci s->os_y_basic = 147; 2292141cc406Sopenharmony_ci } 2293141cc406Sopenharmony_ci 2294141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-5110EOX")){ 2295141cc406Sopenharmony_ci 2296141cc406Sopenharmony_ci /* weirdness */ 2297141cc406Sopenharmony_ci s->cropping_mode = CROP_ABSOLUTE; 2298141cc406Sopenharmony_ci } 2299141cc406Sopenharmony_ci 2300141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-5220C")){ 2301141cc406Sopenharmony_ci 2302141cc406Sopenharmony_ci /* missing from vpd */ 2303141cc406Sopenharmony_ci s->max_x_fb = 10764; 2304141cc406Sopenharmony_ci s->max_y_fb = 14032; 2305141cc406Sopenharmony_ci } 2306141cc406Sopenharmony_ci 2307141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-5530") 2308141cc406Sopenharmony_ci || strstr (s->model_name,"fi-5650") 2309141cc406Sopenharmony_ci || strstr (s->model_name,"fi-5750")){ 2310141cc406Sopenharmony_ci 2311141cc406Sopenharmony_ci /* lies - usb only */ 2312141cc406Sopenharmony_ci if(s->connection == CONNECTION_USB) 2313141cc406Sopenharmony_ci s->adbits = 8; 2314141cc406Sopenharmony_ci } 2315141cc406Sopenharmony_ci 2316141cc406Sopenharmony_ci else if (strstr (s->model_name,"S1500")){ 2317141cc406Sopenharmony_ci 2318141cc406Sopenharmony_ci /*lies*/ 2319141cc406Sopenharmony_ci s->has_MS_bg=0; 2320141cc406Sopenharmony_ci s->has_MS_prepick=0; 2321141cc406Sopenharmony_ci } 2322141cc406Sopenharmony_ci 2323141cc406Sopenharmony_ci /* also includes the 'Z' models */ 2324141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-6130") 2325141cc406Sopenharmony_ci || strstr (s->model_name,"fi-6140")){ 2326141cc406Sopenharmony_ci 2327141cc406Sopenharmony_ci /* weirdness */ 2328141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2329141cc406Sopenharmony_ci s->max_y_by_res[1].res = 200; 2330141cc406Sopenharmony_ci s->max_y_by_res[1].len = 151512; 2331141cc406Sopenharmony_ci } 2332141cc406Sopenharmony_ci 2333141cc406Sopenharmony_ci /* also includes the 'Z' models */ 2334141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-6230") 2335141cc406Sopenharmony_ci || strstr (s->model_name,"fi-6240")){ 2336141cc406Sopenharmony_ci 2337141cc406Sopenharmony_ci /* weirdness */ 2338141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2339141cc406Sopenharmony_ci s->max_y_by_res[1].res = 200; 2340141cc406Sopenharmony_ci s->max_y_by_res[1].len = 151512; 2341141cc406Sopenharmony_ci 2342141cc406Sopenharmony_ci /* missing from vpd */ 2343141cc406Sopenharmony_ci s->max_x_fb = 10764; /* was previously 10488 */ 2344141cc406Sopenharmony_ci s->max_y_fb = 14032; /* some scanners can be slightly more? */ 2345141cc406Sopenharmony_ci } 2346141cc406Sopenharmony_ci 2347141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-6110")){ 2348141cc406Sopenharmony_ci 2349141cc406Sopenharmony_ci /* weirdness */ 2350141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2351141cc406Sopenharmony_ci s->max_y_by_res[1].res = 200; 2352141cc406Sopenharmony_ci s->max_y_by_res[1].len = 151512; 2353141cc406Sopenharmony_ci 2354141cc406Sopenharmony_ci /*lies*/ 2355141cc406Sopenharmony_ci s->has_MS_bg=0; 2356141cc406Sopenharmony_ci s->has_MS_prepick=0; 2357141cc406Sopenharmony_ci } 2358141cc406Sopenharmony_ci 2359141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-6800") 2360141cc406Sopenharmony_ci || strstr (s->model_name,"fi-5900")){ 2361141cc406Sopenharmony_ci /* do not need overrides */ 2362141cc406Sopenharmony_ci } 2363141cc406Sopenharmony_ci 2364141cc406Sopenharmony_ci else if (strstr (s->model_name,"iX500")){ 2365141cc406Sopenharmony_ci /* locks up scanner if we try to auto detect */ 2366141cc406Sopenharmony_ci s->has_MS_lamp = 0; 2367141cc406Sopenharmony_ci 2368141cc406Sopenharmony_ci /* weirdness */ 2369141cc406Sopenharmony_ci s->need_q_table = 1; 2370141cc406Sopenharmony_ci s->need_diag_preread = 1; 2371141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_COLOR] = 2; 2372141cc406Sopenharmony_ci s->hopper_before_op = 1; 2373141cc406Sopenharmony_ci s->no_wait_after_op = 1; 2374141cc406Sopenharmony_ci 2375141cc406Sopenharmony_ci /* lies */ 2376141cc406Sopenharmony_ci s->adbits = 8; 2377141cc406Sopenharmony_ci 2378141cc406Sopenharmony_ci /* we have to simulate these in software*/ 2379141cc406Sopenharmony_ci s->can_mode[MODE_LINEART] = 2; 2380141cc406Sopenharmony_ci s->can_mode[MODE_GRAYSCALE] = 2; 2381141cc406Sopenharmony_ci 2382141cc406Sopenharmony_ci /* don't bother with this one */ 2383141cc406Sopenharmony_ci s->can_mode[MODE_HALFTONE] = 0; 2384141cc406Sopenharmony_ci } 2385141cc406Sopenharmony_ci 2386141cc406Sopenharmony_ci /*mostly copied from iX500*/ 2387141cc406Sopenharmony_ci else if (strstr (s->model_name,"iX100")){ 2388141cc406Sopenharmony_ci /* locks up scanner if we try to auto detect */ 2389141cc406Sopenharmony_ci s->has_MS_lamp = 0; 2390141cc406Sopenharmony_ci 2391141cc406Sopenharmony_ci /* weirdness */ 2392141cc406Sopenharmony_ci s->need_q_table = 1; 2393141cc406Sopenharmony_ci s->need_diag_preread = 1; 2394141cc406Sopenharmony_ci s->ppl_mod_by_mode[MODE_COLOR] = 2; 2395141cc406Sopenharmony_ci s->hopper_before_op = 1; 2396141cc406Sopenharmony_ci s->no_wait_after_op = 1; 2397141cc406Sopenharmony_ci 2398141cc406Sopenharmony_ci /* lies */ 2399141cc406Sopenharmony_ci s->adbits = 8; 2400141cc406Sopenharmony_ci 2401141cc406Sopenharmony_ci /* don't bother with this one */ 2402141cc406Sopenharmony_ci s->can_mode[MODE_HALFTONE] = 0; 2403141cc406Sopenharmony_ci } 2404141cc406Sopenharmony_ci 2405141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-7180") 2406141cc406Sopenharmony_ci || strstr (s->model_name,"fi-7160")){ 2407141cc406Sopenharmony_ci /* locks up scanner if we try to auto detect */ 2408141cc406Sopenharmony_ci s->has_MS_lamp = 0; 2409141cc406Sopenharmony_ci 2410141cc406Sopenharmony_ci /* weirdness */ 2411141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2412141cc406Sopenharmony_ci s->max_y_by_res[1].res = 400; 2413141cc406Sopenharmony_ci s->max_y_by_res[1].len = 194268; 2414141cc406Sopenharmony_ci s->max_y_by_res[2].res = 300; 2415141cc406Sopenharmony_ci s->max_y_by_res[2].len = 260268; 2416141cc406Sopenharmony_ci s->max_y_by_res[3].res = 200; 2417141cc406Sopenharmony_ci s->max_y_by_res[3].len = 266268; 2418141cc406Sopenharmony_ci } 2419141cc406Sopenharmony_ci 2420141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-7280") 2421141cc406Sopenharmony_ci || strstr (s->model_name,"fi-7260")){ 2422141cc406Sopenharmony_ci /* locks up scanner if we try to auto detect */ 2423141cc406Sopenharmony_ci s->has_MS_lamp = 0; 2424141cc406Sopenharmony_ci 2425141cc406Sopenharmony_ci /* weirdness */ 2426141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2427141cc406Sopenharmony_ci s->max_y_by_res[1].res = 400; 2428141cc406Sopenharmony_ci s->max_y_by_res[1].len = 194268; 2429141cc406Sopenharmony_ci s->max_y_by_res[2].res = 300; 2430141cc406Sopenharmony_ci s->max_y_by_res[2].len = 260268; 2431141cc406Sopenharmony_ci s->max_y_by_res[3].res = 200; 2432141cc406Sopenharmony_ci s->max_y_by_res[3].len = 266268; 2433141cc406Sopenharmony_ci 2434141cc406Sopenharmony_ci /* missing from vpd */ 2435141cc406Sopenharmony_ci s->max_x_fb = 10764; 2436141cc406Sopenharmony_ci s->max_y_fb = 14032; /* some scanners can be slightly more? */ 2437141cc406Sopenharmony_ci } 2438141cc406Sopenharmony_ci 2439141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-7480") 2440141cc406Sopenharmony_ci || strstr (s->model_name,"fi-7460")){ 2441141cc406Sopenharmony_ci 2442141cc406Sopenharmony_ci /* weirdness */ 2443141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2444141cc406Sopenharmony_ci s->max_y_by_res[1].res = 400; 2445141cc406Sopenharmony_ci s->max_y_by_res[1].len = 194268; 2446141cc406Sopenharmony_ci s->max_y_by_res[2].res = 300; 2447141cc406Sopenharmony_ci s->max_y_by_res[2].len = 260268; 2448141cc406Sopenharmony_ci s->max_y_by_res[3].res = 200; 2449141cc406Sopenharmony_ci s->max_y_by_res[3].len = 266268; 2450141cc406Sopenharmony_ci } 2451141cc406Sopenharmony_ci 2452141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-7030")){ 2453141cc406Sopenharmony_ci 2454141cc406Sopenharmony_ci /* weirdness */ 2455141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2456141cc406Sopenharmony_ci s->max_y_by_res[1].res = 400; 2457141cc406Sopenharmony_ci s->max_y_by_res[1].len = 192000; 2458141cc406Sopenharmony_ci s->max_y_by_res[2].res = 300; 2459141cc406Sopenharmony_ci s->max_y_by_res[2].len = 258000; 2460141cc406Sopenharmony_ci s->max_y_by_res[3].res = 200; 2461141cc406Sopenharmony_ci s->max_y_by_res[3].len = 264000; 2462141cc406Sopenharmony_ci } 2463141cc406Sopenharmony_ci 2464141cc406Sopenharmony_ci else if (strstr (s->model_name,"fi-7700") 2465141cc406Sopenharmony_ci || strstr (s->model_name,"fi-7600")){ 2466141cc406Sopenharmony_ci 2467141cc406Sopenharmony_ci /* weirdness */ 2468141cc406Sopenharmony_ci /* these machines have longer max paper at lower res */ 2469141cc406Sopenharmony_ci s->max_y_by_res[1].res = 400; 2470141cc406Sopenharmony_ci s->max_y_by_res[1].len = 192000; 2471141cc406Sopenharmony_ci s->max_y_by_res[2].res = 300; 2472141cc406Sopenharmony_ci s->max_y_by_res[2].len = 258000; 2473141cc406Sopenharmony_ci s->max_y_by_res[3].res = 200; 2474141cc406Sopenharmony_ci s->max_y_by_res[3].len = 264000; 2475141cc406Sopenharmony_ci } 2476141cc406Sopenharmony_ci 2477141cc406Sopenharmony_ci DBG (10, "init_model: finish\n"); 2478141cc406Sopenharmony_ci 2479141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2480141cc406Sopenharmony_ci} 2481141cc406Sopenharmony_ci 2482141cc406Sopenharmony_cistatic SANE_Status 2483141cc406Sopenharmony_ciset_mode (struct fujitsu *s, int mode) 2484141cc406Sopenharmony_ci{ 2485141cc406Sopenharmony_ci int i; 2486141cc406Sopenharmony_ci /* give the user what they asked for */ 2487141cc406Sopenharmony_ci s->u_mode = mode; 2488141cc406Sopenharmony_ci 2489141cc406Sopenharmony_ci /* give the scanner the closest mode */ 2490141cc406Sopenharmony_ci for(i=MODE_COLOR;i>=mode;i--){ 2491141cc406Sopenharmony_ci if(s->can_mode[i] == 1){ 2492141cc406Sopenharmony_ci s->s_mode = i; 2493141cc406Sopenharmony_ci } 2494141cc406Sopenharmony_ci } 2495141cc406Sopenharmony_ci 2496141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2497141cc406Sopenharmony_ci} 2498141cc406Sopenharmony_ci 2499141cc406Sopenharmony_ci/* 2500141cc406Sopenharmony_ci * set good default user values. 2501141cc406Sopenharmony_ci * struct is already initialized to 0. 2502141cc406Sopenharmony_ci */ 2503141cc406Sopenharmony_cistatic SANE_Status 2504141cc406Sopenharmony_ciinit_user (struct fujitsu *s) 2505141cc406Sopenharmony_ci{ 2506141cc406Sopenharmony_ci 2507141cc406Sopenharmony_ci DBG (10, "init_user: start\n"); 2508141cc406Sopenharmony_ci 2509141cc406Sopenharmony_ci /* source */ 2510141cc406Sopenharmony_ci if(s->has_flatbed) 2511141cc406Sopenharmony_ci s->source = SOURCE_FLATBED; 2512141cc406Sopenharmony_ci else if(s->has_adf) 2513141cc406Sopenharmony_ci s->source = SOURCE_ADF_FRONT; 2514141cc406Sopenharmony_ci else if(s->has_return_path) 2515141cc406Sopenharmony_ci s->source = SOURCE_CARD_FRONT; 2516141cc406Sopenharmony_ci 2517141cc406Sopenharmony_ci /* scan mode */ 2518141cc406Sopenharmony_ci if(s->can_mode[MODE_LINEART]) 2519141cc406Sopenharmony_ci set_mode(s,MODE_LINEART); 2520141cc406Sopenharmony_ci else if(s->can_mode[MODE_HALFTONE]) 2521141cc406Sopenharmony_ci set_mode(s,MODE_HALFTONE); 2522141cc406Sopenharmony_ci else if(s->can_mode[MODE_GRAYSCALE]) 2523141cc406Sopenharmony_ci set_mode(s,MODE_GRAYSCALE); 2524141cc406Sopenharmony_ci else if(s->can_mode[MODE_COLOR]) 2525141cc406Sopenharmony_ci set_mode(s,MODE_COLOR); 2526141cc406Sopenharmony_ci 2527141cc406Sopenharmony_ci /*x res*/ 2528141cc406Sopenharmony_ci s->resolution_x = s->basic_x_res; 2529141cc406Sopenharmony_ci 2530141cc406Sopenharmony_ci /*y res*/ 2531141cc406Sopenharmony_ci s->resolution_y = s->basic_y_res; 2532141cc406Sopenharmony_ci if(s->resolution_y > s->resolution_x){ 2533141cc406Sopenharmony_ci s->resolution_y = s->resolution_x; 2534141cc406Sopenharmony_ci } 2535141cc406Sopenharmony_ci 2536141cc406Sopenharmony_ci /* page width US-Letter */ 2537141cc406Sopenharmony_ci s->page_width = 8.5 * 1200; 2538141cc406Sopenharmony_ci if(s->page_width > s->max_x){ 2539141cc406Sopenharmony_ci s->page_width = s->max_x; 2540141cc406Sopenharmony_ci } 2541141cc406Sopenharmony_ci 2542141cc406Sopenharmony_ci /* page height US-Letter */ 2543141cc406Sopenharmony_ci s->page_height = 11 * 1200; 2544141cc406Sopenharmony_ci set_max_y(s); 2545141cc406Sopenharmony_ci if(s->page_height > s->max_y){ 2546141cc406Sopenharmony_ci s->page_height = s->max_y; 2547141cc406Sopenharmony_ci } 2548141cc406Sopenharmony_ci 2549141cc406Sopenharmony_ci /* bottom-right x */ 2550141cc406Sopenharmony_ci s->br_x = s->page_width; 2551141cc406Sopenharmony_ci 2552141cc406Sopenharmony_ci /* bottom-right y */ 2553141cc406Sopenharmony_ci s->br_y = s->page_height; 2554141cc406Sopenharmony_ci 2555141cc406Sopenharmony_ci /* gamma ramp exponent */ 2556141cc406Sopenharmony_ci s->gamma = 1; 2557141cc406Sopenharmony_ci 2558141cc406Sopenharmony_ci /* safe endorser settings */ 2559141cc406Sopenharmony_ci s->u_endorser_bits=16; 2560141cc406Sopenharmony_ci s->u_endorser_step=1; 2561141cc406Sopenharmony_ci s->u_endorser_side=ED_back; 2562141cc406Sopenharmony_ci if(s->has_endorser_f){ 2563141cc406Sopenharmony_ci s->u_endorser_side=ED_front; 2564141cc406Sopenharmony_ci } 2565141cc406Sopenharmony_ci s->u_endorser_dir=DIR_TTB; 2566141cc406Sopenharmony_ci strcpy((char *)s->u_endorser_string,"%05ud"); 2567141cc406Sopenharmony_ci 2568141cc406Sopenharmony_ci /* more recent machines default to this being 'on', * 2569141cc406Sopenharmony_ci * which causes the scanner to ingest multiple pages * 2570141cc406Sopenharmony_ci * even when the user only wants one */ 2571141cc406Sopenharmony_ci s->buff_mode = MSEL_OFF; 2572141cc406Sopenharmony_ci 2573141cc406Sopenharmony_ci /* useful features of newer scanners which we turn on, 2574141cc406Sopenharmony_ci * even though the scanner defaults to off */ 2575141cc406Sopenharmony_ci if(s->has_paper_protect){ 2576141cc406Sopenharmony_ci s->paper_protect = MSEL_ON; 2577141cc406Sopenharmony_ci } 2578141cc406Sopenharmony_ci if(s->has_staple_detect){ 2579141cc406Sopenharmony_ci s->staple_detect = MSEL_ON; 2580141cc406Sopenharmony_ci } 2581141cc406Sopenharmony_ci if(s->has_df_recovery){ 2582141cc406Sopenharmony_ci s->df_recovery = MSEL_ON; 2583141cc406Sopenharmony_ci } 2584141cc406Sopenharmony_ci if(s->has_adv_paper_prot){ 2585141cc406Sopenharmony_ci s->adv_paper_prot = MSEL_ON; 2586141cc406Sopenharmony_ci } 2587141cc406Sopenharmony_ci 2588141cc406Sopenharmony_ci s->off_time = 240; 2589141cc406Sopenharmony_ci 2590141cc406Sopenharmony_ci DBG (10, "init_user: finish\n"); 2591141cc406Sopenharmony_ci 2592141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2593141cc406Sopenharmony_ci} 2594141cc406Sopenharmony_ci 2595141cc406Sopenharmony_ci/* 2596141cc406Sopenharmony_ci * This function presets the "option" array to blank 2597141cc406Sopenharmony_ci */ 2598141cc406Sopenharmony_cistatic SANE_Status 2599141cc406Sopenharmony_ciinit_options (struct fujitsu *s) 2600141cc406Sopenharmony_ci{ 2601141cc406Sopenharmony_ci int i; 2602141cc406Sopenharmony_ci 2603141cc406Sopenharmony_ci DBG (10, "init_options: start\n"); 2604141cc406Sopenharmony_ci 2605141cc406Sopenharmony_ci memset (s->opt, 0, sizeof (s->opt)); 2606141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) { 2607141cc406Sopenharmony_ci s->opt[i].name = "filler"; 2608141cc406Sopenharmony_ci s->opt[i].size = sizeof (SANE_Word); 2609141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_INACTIVE; 2610141cc406Sopenharmony_ci } 2611141cc406Sopenharmony_ci 2612141cc406Sopenharmony_ci /* go ahead and setup the first opt, because 2613141cc406Sopenharmony_ci * frontend may call control_option on it 2614141cc406Sopenharmony_ci * before calling get_option_descriptor 2615141cc406Sopenharmony_ci */ 2616141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 2617141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2618141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2619141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2620141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2621141cc406Sopenharmony_ci 2622141cc406Sopenharmony_ci DBG (10, "init_options: finish\n"); 2623141cc406Sopenharmony_ci 2624141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2625141cc406Sopenharmony_ci} 2626141cc406Sopenharmony_ci 2627141cc406Sopenharmony_ci/* 2628141cc406Sopenharmony_ci * send set window repeatedly to color scanners, 2629141cc406Sopenharmony_ci * searching for valid color interlacing mode 2630141cc406Sopenharmony_ci */ 2631141cc406Sopenharmony_cistatic SANE_Status 2632141cc406Sopenharmony_ciinit_interlace (struct fujitsu *s) 2633141cc406Sopenharmony_ci{ 2634141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 2635141cc406Sopenharmony_ci int curr_mode = s->u_mode; 2636141cc406Sopenharmony_ci int oldDbg=0; 2637141cc406Sopenharmony_ci 2638141cc406Sopenharmony_ci DBG (10, "init_interlace: start\n"); 2639141cc406Sopenharmony_ci 2640141cc406Sopenharmony_ci if(s->color_interlace != COLOR_INTERLACE_UNK){ 2641141cc406Sopenharmony_ci DBG (10, "init_interlace: already loaded\n"); 2642141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2643141cc406Sopenharmony_ci } 2644141cc406Sopenharmony_ci 2645141cc406Sopenharmony_ci if(!s->has_vuid_color){ 2646141cc406Sopenharmony_ci DBG (10, "init_interlace: color unsupported\n"); 2647141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2648141cc406Sopenharmony_ci } 2649141cc406Sopenharmony_ci 2650141cc406Sopenharmony_ci /* set to color mode first */ 2651141cc406Sopenharmony_ci set_mode(s,MODE_COLOR); 2652141cc406Sopenharmony_ci 2653141cc406Sopenharmony_ci /* load our own private copy of scan params */ 2654141cc406Sopenharmony_ci ret = update_params(s); 2655141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 2656141cc406Sopenharmony_ci DBG (5, "init_interlace: ERROR: cannot update params\n"); 2657141cc406Sopenharmony_ci return ret; 2658141cc406Sopenharmony_ci } 2659141cc406Sopenharmony_ci 2660141cc406Sopenharmony_ci /*loop thru all the formats we support*/ 2661141cc406Sopenharmony_ci for(s->color_interlace = COLOR_INTERLACE_RGB; 2662141cc406Sopenharmony_ci s->color_interlace <= COLOR_INTERLACE_RRGGBB; 2663141cc406Sopenharmony_ci s->color_interlace++){ 2664141cc406Sopenharmony_ci 2665141cc406Sopenharmony_ci /* some of the following probes will produce errors */ 2666141cc406Sopenharmony_ci /* so we reduce the dbg level to reduce the noise */ 2667141cc406Sopenharmony_ci /* however, if user builds with NDEBUG, we can't do that */ 2668141cc406Sopenharmony_ci /* so we protect the code with the following macro */ 2669141cc406Sopenharmony_ci IF_DBG( oldDbg=DBG_LEVEL; ) 2670141cc406Sopenharmony_ci IF_DBG( if(DBG_LEVEL < 35){ DBG_LEVEL = 0; } ) 2671141cc406Sopenharmony_ci 2672141cc406Sopenharmony_ci ret = set_window(s); 2673141cc406Sopenharmony_ci 2674141cc406Sopenharmony_ci IF_DBG (DBG_LEVEL = oldDbg;) 2675141cc406Sopenharmony_ci 2676141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD){ 2677141cc406Sopenharmony_ci break; 2678141cc406Sopenharmony_ci } 2679141cc406Sopenharmony_ci else{ 2680141cc406Sopenharmony_ci DBG (15, "init_interlace: not %d\n", s->color_interlace); 2681141cc406Sopenharmony_ci } 2682141cc406Sopenharmony_ci } 2683141cc406Sopenharmony_ci 2684141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD){ 2685141cc406Sopenharmony_ci DBG (5, "init_interlace: no valid interlacings\n"); 2686141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2687141cc406Sopenharmony_ci } 2688141cc406Sopenharmony_ci 2689141cc406Sopenharmony_ci DBG (15, "init_interlace: color_interlace: %d\n",s->color_interlace); 2690141cc406Sopenharmony_ci 2691141cc406Sopenharmony_ci /* restore mode */ 2692141cc406Sopenharmony_ci set_mode(s,curr_mode); 2693141cc406Sopenharmony_ci 2694141cc406Sopenharmony_ci DBG (10, "init_interlace: finish\n"); 2695141cc406Sopenharmony_ci 2696141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2697141cc406Sopenharmony_ci} 2698141cc406Sopenharmony_ci 2699141cc406Sopenharmony_ci/* 2700141cc406Sopenharmony_ci * send diag query for serial number, and read result back 2701141cc406Sopenharmony_ci * use it to build a unique name for scanner in s->serial_name 2702141cc406Sopenharmony_ci */ 2703141cc406Sopenharmony_cistatic SANE_Status 2704141cc406Sopenharmony_ciinit_serial (struct fujitsu *s) 2705141cc406Sopenharmony_ci{ 2706141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 2707141cc406Sopenharmony_ci unsigned int sn = 0; 2708141cc406Sopenharmony_ci 2709141cc406Sopenharmony_ci unsigned char cmd[SEND_DIAGNOSTIC_len]; /*also big enough for READ_DIAG*/ 2710141cc406Sopenharmony_ci size_t cmdLen = SEND_DIAGNOSTIC_len; 2711141cc406Sopenharmony_ci 2712141cc406Sopenharmony_ci unsigned char out[SD_gdi_len]; 2713141cc406Sopenharmony_ci size_t outLen = SD_gdi_len; 2714141cc406Sopenharmony_ci 2715141cc406Sopenharmony_ci unsigned char in[RD_gdi_len]; 2716141cc406Sopenharmony_ci size_t inLen = RD_gdi_len; 2717141cc406Sopenharmony_ci 2718141cc406Sopenharmony_ci DBG (10, "init_serial: start\n"); 2719141cc406Sopenharmony_ci 2720141cc406Sopenharmony_ci if (!s->has_cmd_sdiag || !s->has_cmd_rdiag || s->broken_diag_serial){ 2721141cc406Sopenharmony_ci DBG (5, "init_serial: send/read diag not supported, returning\n"); 2722141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2723141cc406Sopenharmony_ci } 2724141cc406Sopenharmony_ci 2725141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 2726141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SEND_DIAGNOSTIC_code); 2727141cc406Sopenharmony_ci set_SD_slftst(cmd, 0); 2728141cc406Sopenharmony_ci set_SD_xferlen(cmd, outLen); 2729141cc406Sopenharmony_ci 2730141cc406Sopenharmony_ci memcpy(out,SD_gdi_string,outLen); 2731141cc406Sopenharmony_ci 2732141cc406Sopenharmony_ci ret = do_cmd ( 2733141cc406Sopenharmony_ci s, 1, 0, 2734141cc406Sopenharmony_ci cmd, cmdLen, 2735141cc406Sopenharmony_ci out, outLen, 2736141cc406Sopenharmony_ci NULL, NULL 2737141cc406Sopenharmony_ci ); 2738141cc406Sopenharmony_ci 2739141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD){ 2740141cc406Sopenharmony_ci DBG (5, "init_serial: send diag error: %d\n", ret); 2741141cc406Sopenharmony_ci return ret; 2742141cc406Sopenharmony_ci } 2743141cc406Sopenharmony_ci 2744141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 2745141cc406Sopenharmony_ci set_SCSI_opcode(cmd, READ_DIAGNOSTIC_code); 2746141cc406Sopenharmony_ci set_RD_xferlen(cmd, inLen); 2747141cc406Sopenharmony_ci 2748141cc406Sopenharmony_ci ret = do_cmd ( 2749141cc406Sopenharmony_ci s, 1, 0, 2750141cc406Sopenharmony_ci cmd, cmdLen, 2751141cc406Sopenharmony_ci NULL, 0, 2752141cc406Sopenharmony_ci in, &inLen 2753141cc406Sopenharmony_ci ); 2754141cc406Sopenharmony_ci 2755141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD){ 2756141cc406Sopenharmony_ci DBG (5, "init_serial: read diag error: %d\n", ret); 2757141cc406Sopenharmony_ci return ret; 2758141cc406Sopenharmony_ci } 2759141cc406Sopenharmony_ci 2760141cc406Sopenharmony_ci sn = get_RD_id_serial(in); 2761141cc406Sopenharmony_ci 2762141cc406Sopenharmony_ci DBG (15, "init_serial: found sn %d\n",sn); 2763141cc406Sopenharmony_ci 2764141cc406Sopenharmony_ci sprintf(s->serial_name, "%s:%d", s->model_name, sn); 2765141cc406Sopenharmony_ci 2766141cc406Sopenharmony_ci DBG (15, "init_serial: serial_name: %s\n",s->serial_name); 2767141cc406Sopenharmony_ci 2768141cc406Sopenharmony_ci DBG (10, "init_serial: finish\n"); 2769141cc406Sopenharmony_ci 2770141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2771141cc406Sopenharmony_ci} 2772141cc406Sopenharmony_ci 2773141cc406Sopenharmony_ci/* 2774141cc406Sopenharmony_ci * From the SANE spec: 2775141cc406Sopenharmony_ci * This function is used to establish a connection to a particular 2776141cc406Sopenharmony_ci * device. The name of the device to be opened is passed in argument 2777141cc406Sopenharmony_ci * name. If the call completes successfully, a handle for the device 2778141cc406Sopenharmony_ci * is returned in *h. As a special case, specifying a zero-length 2779141cc406Sopenharmony_ci * string as the device requests opening the first available device 2780141cc406Sopenharmony_ci * (if there is such a device). 2781141cc406Sopenharmony_ci */ 2782141cc406Sopenharmony_ciSANE_Status 2783141cc406Sopenharmony_cisane_open (SANE_String_Const name, SANE_Handle * handle) 2784141cc406Sopenharmony_ci{ 2785141cc406Sopenharmony_ci struct fujitsu *dev = NULL; 2786141cc406Sopenharmony_ci struct fujitsu *s = NULL; 2787141cc406Sopenharmony_ci SANE_Status ret; 2788141cc406Sopenharmony_ci 2789141cc406Sopenharmony_ci DBG (10, "sane_open: start\n"); 2790141cc406Sopenharmony_ci 2791141cc406Sopenharmony_ci if(fujitsu_devList){ 2792141cc406Sopenharmony_ci DBG (15, "sane_open: searching currently attached scanners\n"); 2793141cc406Sopenharmony_ci } 2794141cc406Sopenharmony_ci else{ 2795141cc406Sopenharmony_ci DBG (15, "sane_open: no scanners currently attached, attaching\n"); 2796141cc406Sopenharmony_ci 2797141cc406Sopenharmony_ci ret = sane_get_devices(NULL,0); 2798141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 2799141cc406Sopenharmony_ci return ret; 2800141cc406Sopenharmony_ci } 2801141cc406Sopenharmony_ci } 2802141cc406Sopenharmony_ci 2803141cc406Sopenharmony_ci if(!name || !name[0]){ 2804141cc406Sopenharmony_ci DBG (15, "sane_open: no device requested, using default\n"); 2805141cc406Sopenharmony_ci s = fujitsu_devList; 2806141cc406Sopenharmony_ci } 2807141cc406Sopenharmony_ci else{ 2808141cc406Sopenharmony_ci DBG (15, "sane_open: device %s requested\n", name); 2809141cc406Sopenharmony_ci 2810141cc406Sopenharmony_ci for (dev = fujitsu_devList; dev; dev = dev->next) { 2811141cc406Sopenharmony_ci if (strcmp (dev->sane.name, name) == 0 2812141cc406Sopenharmony_ci || strcmp (dev->device_name, name) == 0) { /*always allow sanei devname*/ 2813141cc406Sopenharmony_ci s = dev; 2814141cc406Sopenharmony_ci break; 2815141cc406Sopenharmony_ci } 2816141cc406Sopenharmony_ci } 2817141cc406Sopenharmony_ci } 2818141cc406Sopenharmony_ci 2819141cc406Sopenharmony_ci if (!s) { 2820141cc406Sopenharmony_ci DBG (5, "sane_open: no device found\n"); 2821141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2822141cc406Sopenharmony_ci } 2823141cc406Sopenharmony_ci 2824141cc406Sopenharmony_ci DBG (15, "sane_open: device %s found\n", s->sane.name); 2825141cc406Sopenharmony_ci 2826141cc406Sopenharmony_ci *handle = s; 2827141cc406Sopenharmony_ci 2828141cc406Sopenharmony_ci /* connect the fd so we can talk to scanner */ 2829141cc406Sopenharmony_ci ret = connect_fd(s); 2830141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 2831141cc406Sopenharmony_ci return ret; 2832141cc406Sopenharmony_ci } 2833141cc406Sopenharmony_ci 2834141cc406Sopenharmony_ci DBG (10, "sane_open: finish\n"); 2835141cc406Sopenharmony_ci 2836141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2837141cc406Sopenharmony_ci} 2838141cc406Sopenharmony_ci 2839141cc406Sopenharmony_ci/* 2840141cc406Sopenharmony_ci * @@ Section 3 - SANE Options functions 2841141cc406Sopenharmony_ci */ 2842141cc406Sopenharmony_ci 2843141cc406Sopenharmony_ci/* 2844141cc406Sopenharmony_ci * Returns the options we know. 2845141cc406Sopenharmony_ci * 2846141cc406Sopenharmony_ci * From the SANE spec: 2847141cc406Sopenharmony_ci * This function is used to access option descriptors. The function 2848141cc406Sopenharmony_ci * returns the option descriptor for option number n of the device 2849141cc406Sopenharmony_ci * represented by handle h. Option number 0 is guaranteed to be a 2850141cc406Sopenharmony_ci * valid option. Its value is an integer that specifies the number of 2851141cc406Sopenharmony_ci * options that are available for device handle h (the count includes 2852141cc406Sopenharmony_ci * option 0). If n is not a valid option index, the function returns 2853141cc406Sopenharmony_ci * NULL. The returned option descriptor is guaranteed to remain valid 2854141cc406Sopenharmony_ci * (and at the returned address) until the device is closed. 2855141cc406Sopenharmony_ci */ 2856141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 2857141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 2858141cc406Sopenharmony_ci{ 2859141cc406Sopenharmony_ci struct fujitsu *s = handle; 2860141cc406Sopenharmony_ci int i,j; 2861141cc406Sopenharmony_ci SANE_Option_Descriptor *opt = &s->opt[option]; 2862141cc406Sopenharmony_ci 2863141cc406Sopenharmony_ci DBG (20, "sane_get_option_descriptor: %d\n", option); 2864141cc406Sopenharmony_ci 2865141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 2866141cc406Sopenharmony_ci return NULL; 2867141cc406Sopenharmony_ci 2868141cc406Sopenharmony_ci /* "Mode" group -------------------------------------------------------- */ 2869141cc406Sopenharmony_ci if(option==OPT_STANDARD_GROUP){ 2870141cc406Sopenharmony_ci opt->name = SANE_NAME_STANDARD; 2871141cc406Sopenharmony_ci opt->title = SANE_TITLE_STANDARD; 2872141cc406Sopenharmony_ci opt->desc = SANE_DESC_STANDARD; 2873141cc406Sopenharmony_ci opt->type = SANE_TYPE_GROUP; 2874141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 2875141cc406Sopenharmony_ci } 2876141cc406Sopenharmony_ci 2877141cc406Sopenharmony_ci /* source */ 2878141cc406Sopenharmony_ci if(option==OPT_SOURCE){ 2879141cc406Sopenharmony_ci i=0; 2880141cc406Sopenharmony_ci if(s->has_flatbed){ 2881141cc406Sopenharmony_ci s->source_list[i++]=STRING_FLATBED; 2882141cc406Sopenharmony_ci } 2883141cc406Sopenharmony_ci if(s->has_adf){ 2884141cc406Sopenharmony_ci s->source_list[i++]=STRING_ADFFRONT; 2885141cc406Sopenharmony_ci 2886141cc406Sopenharmony_ci if(s->has_back){ 2887141cc406Sopenharmony_ci s->source_list[i++]=STRING_ADFBACK; 2888141cc406Sopenharmony_ci } 2889141cc406Sopenharmony_ci if(s->has_duplex){ 2890141cc406Sopenharmony_ci s->source_list[i++]=STRING_ADFDUPLEX; 2891141cc406Sopenharmony_ci } 2892141cc406Sopenharmony_ci } 2893141cc406Sopenharmony_ci if(s->has_return_path){ 2894141cc406Sopenharmony_ci s->source_list[i++]=STRING_CARDFRONT; 2895141cc406Sopenharmony_ci 2896141cc406Sopenharmony_ci if(s->has_back){ 2897141cc406Sopenharmony_ci s->source_list[i++]=STRING_CARDBACK; 2898141cc406Sopenharmony_ci } 2899141cc406Sopenharmony_ci if(s->has_duplex){ 2900141cc406Sopenharmony_ci s->source_list[i++]=STRING_CARDDUPLEX; 2901141cc406Sopenharmony_ci } 2902141cc406Sopenharmony_ci } 2903141cc406Sopenharmony_ci s->source_list[i]=NULL; 2904141cc406Sopenharmony_ci 2905141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN_SOURCE; 2906141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN_SOURCE; 2907141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN_SOURCE; 2908141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 2909141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 2910141cc406Sopenharmony_ci opt->constraint.string_list = s->source_list; 2911141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 2912141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2913141cc406Sopenharmony_ci } 2914141cc406Sopenharmony_ci 2915141cc406Sopenharmony_ci /* scan mode */ 2916141cc406Sopenharmony_ci if(option==OPT_MODE){ 2917141cc406Sopenharmony_ci i=0; 2918141cc406Sopenharmony_ci if(s->can_mode[MODE_LINEART]){ 2919141cc406Sopenharmony_ci s->mode_list[i++]=STRING_LINEART; 2920141cc406Sopenharmony_ci } 2921141cc406Sopenharmony_ci if(s->can_mode[MODE_HALFTONE]){ 2922141cc406Sopenharmony_ci s->mode_list[i++]=STRING_HALFTONE; 2923141cc406Sopenharmony_ci } 2924141cc406Sopenharmony_ci if(s->can_mode[MODE_GRAYSCALE]){ 2925141cc406Sopenharmony_ci s->mode_list[i++]=STRING_GRAYSCALE; 2926141cc406Sopenharmony_ci } 2927141cc406Sopenharmony_ci if(s->can_mode[MODE_COLOR]){ 2928141cc406Sopenharmony_ci s->mode_list[i++]=STRING_COLOR; 2929141cc406Sopenharmony_ci } 2930141cc406Sopenharmony_ci s->mode_list[i]=NULL; 2931141cc406Sopenharmony_ci 2932141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN_MODE; 2933141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN_MODE; 2934141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN_MODE; 2935141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 2936141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 2937141cc406Sopenharmony_ci opt->constraint.string_list = s->mode_list; 2938141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 2939141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2940141cc406Sopenharmony_ci } 2941141cc406Sopenharmony_ci 2942141cc406Sopenharmony_ci /* resolution */ 2943141cc406Sopenharmony_ci /* some scanners only support fixed res 2944141cc406Sopenharmony_ci * build a list of possible choices */ 2945141cc406Sopenharmony_ci if(option==OPT_RES){ 2946141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN_RESOLUTION; 2947141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN_RESOLUTION; 2948141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN_RESOLUTION; 2949141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 2950141cc406Sopenharmony_ci opt->unit = SANE_UNIT_DPI; 2951141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2952141cc406Sopenharmony_ci 2953141cc406Sopenharmony_ci if(s->step_x_res[s->s_mode] && s->step_y_res[s->s_mode]){ 2954141cc406Sopenharmony_ci s->res_range.min = s->min_x_res; 2955141cc406Sopenharmony_ci s->res_range.max = s->max_x_res; 2956141cc406Sopenharmony_ci s->res_range.quant = s->step_x_res[s->s_mode]; 2957141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 2958141cc406Sopenharmony_ci opt->constraint.range = &s->res_range; 2959141cc406Sopenharmony_ci } 2960141cc406Sopenharmony_ci else{ 2961141cc406Sopenharmony_ci int reses[] 2962141cc406Sopenharmony_ci = {60,75,100,120,150,160,180,200,240,300,320,400,480,600,800,1200}; 2963141cc406Sopenharmony_ci 2964141cc406Sopenharmony_ci i=0; 2965141cc406Sopenharmony_ci for(j=0;j<16;j++){ 2966141cc406Sopenharmony_ci if(s->std_res[j] 2967141cc406Sopenharmony_ci && s->max_x_res >= reses[j] && s->min_x_res <= reses[j] 2968141cc406Sopenharmony_ci && s->max_y_res >= reses[j] && s->min_y_res <= reses[j] 2969141cc406Sopenharmony_ci ){ 2970141cc406Sopenharmony_ci s->res_list[++i] = reses[j]; 2971141cc406Sopenharmony_ci } 2972141cc406Sopenharmony_ci } 2973141cc406Sopenharmony_ci s->res_list[0] = i; 2974141cc406Sopenharmony_ci 2975141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_WORD_LIST; 2976141cc406Sopenharmony_ci opt->constraint.word_list = s->res_list; 2977141cc406Sopenharmony_ci } 2978141cc406Sopenharmony_ci } 2979141cc406Sopenharmony_ci 2980141cc406Sopenharmony_ci /* "Geometry" group ---------------------------------------------------- */ 2981141cc406Sopenharmony_ci if(option==OPT_GEOMETRY_GROUP){ 2982141cc406Sopenharmony_ci opt->name = SANE_NAME_GEOMETRY; 2983141cc406Sopenharmony_ci opt->title = SANE_TITLE_GEOMETRY; 2984141cc406Sopenharmony_ci opt->desc = SANE_DESC_GEOMETRY; 2985141cc406Sopenharmony_ci opt->type = SANE_TYPE_GROUP; 2986141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 2987141cc406Sopenharmony_ci } 2988141cc406Sopenharmony_ci 2989141cc406Sopenharmony_ci /* top-left x */ 2990141cc406Sopenharmony_ci if(option==OPT_TL_X){ 2991141cc406Sopenharmony_ci /* values stored in 1200 dpi units */ 2992141cc406Sopenharmony_ci /* must be converted to MM for sane */ 2993141cc406Sopenharmony_ci s->tl_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); 2994141cc406Sopenharmony_ci s->tl_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); 2995141cc406Sopenharmony_ci s->tl_x_range.quant = MM_PER_UNIT_FIX; 2996141cc406Sopenharmony_ci 2997141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN_TL_X; 2998141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN_TL_X; 2999141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN_TL_X; 3000141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 3001141cc406Sopenharmony_ci opt->unit = SANE_UNIT_MM; 3002141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3003141cc406Sopenharmony_ci opt->constraint.range = &(s->tl_x_range); 3004141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3005141cc406Sopenharmony_ci } 3006141cc406Sopenharmony_ci 3007141cc406Sopenharmony_ci /* top-left y */ 3008141cc406Sopenharmony_ci if(option==OPT_TL_Y){ 3009141cc406Sopenharmony_ci /* values stored in 1200 dpi units */ 3010141cc406Sopenharmony_ci /* must be converted to MM for sane */ 3011141cc406Sopenharmony_ci s->tl_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); 3012141cc406Sopenharmony_ci s->tl_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); 3013141cc406Sopenharmony_ci s->tl_y_range.quant = MM_PER_UNIT_FIX; 3014141cc406Sopenharmony_ci 3015141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN_TL_Y; 3016141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN_TL_Y; 3017141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN_TL_Y; 3018141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 3019141cc406Sopenharmony_ci opt->unit = SANE_UNIT_MM; 3020141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3021141cc406Sopenharmony_ci opt->constraint.range = &(s->tl_y_range); 3022141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3023141cc406Sopenharmony_ci } 3024141cc406Sopenharmony_ci 3025141cc406Sopenharmony_ci /* bottom-right x */ 3026141cc406Sopenharmony_ci if(option==OPT_BR_X){ 3027141cc406Sopenharmony_ci /* values stored in 1200 dpi units */ 3028141cc406Sopenharmony_ci /* must be converted to MM for sane */ 3029141cc406Sopenharmony_ci s->br_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); 3030141cc406Sopenharmony_ci s->br_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); 3031141cc406Sopenharmony_ci s->br_x_range.quant = MM_PER_UNIT_FIX; 3032141cc406Sopenharmony_ci 3033141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN_BR_X; 3034141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN_BR_X; 3035141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN_BR_X; 3036141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 3037141cc406Sopenharmony_ci opt->unit = SANE_UNIT_MM; 3038141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3039141cc406Sopenharmony_ci opt->constraint.range = &(s->br_x_range); 3040141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3041141cc406Sopenharmony_ci } 3042141cc406Sopenharmony_ci 3043141cc406Sopenharmony_ci /* bottom-right y */ 3044141cc406Sopenharmony_ci if(option==OPT_BR_Y){ 3045141cc406Sopenharmony_ci /* values stored in 1200 dpi units */ 3046141cc406Sopenharmony_ci /* must be converted to MM for sane */ 3047141cc406Sopenharmony_ci s->br_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); 3048141cc406Sopenharmony_ci s->br_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); 3049141cc406Sopenharmony_ci s->br_y_range.quant = MM_PER_UNIT_FIX; 3050141cc406Sopenharmony_ci 3051141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN_BR_Y; 3052141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN_BR_Y; 3053141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN_BR_Y; 3054141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 3055141cc406Sopenharmony_ci opt->unit = SANE_UNIT_MM; 3056141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3057141cc406Sopenharmony_ci opt->constraint.range = &(s->br_y_range); 3058141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3059141cc406Sopenharmony_ci } 3060141cc406Sopenharmony_ci 3061141cc406Sopenharmony_ci /* page width */ 3062141cc406Sopenharmony_ci if(option==OPT_PAGE_WIDTH){ 3063141cc406Sopenharmony_ci /* values stored in 1200 dpi units */ 3064141cc406Sopenharmony_ci /* must be converted to MM for sane */ 3065141cc406Sopenharmony_ci s->paper_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); 3066141cc406Sopenharmony_ci s->paper_x_range.max = SCANNER_UNIT_TO_FIXED_MM(s->max_x); 3067141cc406Sopenharmony_ci s->paper_x_range.quant = MM_PER_UNIT_FIX; 3068141cc406Sopenharmony_ci 3069141cc406Sopenharmony_ci opt->name = SANE_NAME_PAGE_WIDTH; 3070141cc406Sopenharmony_ci opt->title = SANE_TITLE_PAGE_WIDTH; 3071141cc406Sopenharmony_ci opt->desc = SANE_DESC_PAGE_WIDTH; 3072141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 3073141cc406Sopenharmony_ci opt->unit = SANE_UNIT_MM; 3074141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3075141cc406Sopenharmony_ci opt->constraint.range = &s->paper_x_range; 3076141cc406Sopenharmony_ci 3077141cc406Sopenharmony_ci if(s->has_adf || s->has_return_path){ 3078141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3079141cc406Sopenharmony_ci if(s->source == SOURCE_FLATBED){ 3080141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3081141cc406Sopenharmony_ci } 3082141cc406Sopenharmony_ci } 3083141cc406Sopenharmony_ci else{ 3084141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3085141cc406Sopenharmony_ci } 3086141cc406Sopenharmony_ci } 3087141cc406Sopenharmony_ci 3088141cc406Sopenharmony_ci /* page height */ 3089141cc406Sopenharmony_ci if(option==OPT_PAGE_HEIGHT){ 3090141cc406Sopenharmony_ci /* values stored in 1200 dpi units */ 3091141cc406Sopenharmony_ci /* must be converted to MM for sane */ 3092141cc406Sopenharmony_ci s->paper_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); 3093141cc406Sopenharmony_ci s->paper_y_range.max = SCANNER_UNIT_TO_FIXED_MM(s->max_y); 3094141cc406Sopenharmony_ci s->paper_y_range.quant = MM_PER_UNIT_FIX; 3095141cc406Sopenharmony_ci 3096141cc406Sopenharmony_ci opt->name = SANE_NAME_PAGE_HEIGHT; 3097141cc406Sopenharmony_ci opt->title = SANE_TITLE_PAGE_HEIGHT; 3098141cc406Sopenharmony_ci opt->desc = SANE_DESC_PAGE_HEIGHT; 3099141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 3100141cc406Sopenharmony_ci opt->unit = SANE_UNIT_MM; 3101141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3102141cc406Sopenharmony_ci opt->constraint.range = &s->paper_y_range; 3103141cc406Sopenharmony_ci 3104141cc406Sopenharmony_ci if(s->has_adf || s->has_return_path){ 3105141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3106141cc406Sopenharmony_ci if(s->source == SOURCE_FLATBED){ 3107141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3108141cc406Sopenharmony_ci } 3109141cc406Sopenharmony_ci } 3110141cc406Sopenharmony_ci else{ 3111141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3112141cc406Sopenharmony_ci } 3113141cc406Sopenharmony_ci } 3114141cc406Sopenharmony_ci 3115141cc406Sopenharmony_ci /* "Enhancement" group ------------------------------------------------- */ 3116141cc406Sopenharmony_ci if(option==OPT_ENHANCEMENT_GROUP){ 3117141cc406Sopenharmony_ci opt->name = SANE_NAME_ENHANCEMENT; 3118141cc406Sopenharmony_ci opt->title = SANE_TITLE_ENHANCEMENT; 3119141cc406Sopenharmony_ci opt->desc = SANE_DESC_ENHANCEMENT; 3120141cc406Sopenharmony_ci opt->type = SANE_TYPE_GROUP; 3121141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 3122141cc406Sopenharmony_ci } 3123141cc406Sopenharmony_ci 3124141cc406Sopenharmony_ci /* brightness */ 3125141cc406Sopenharmony_ci if(option==OPT_BRIGHTNESS){ 3126141cc406Sopenharmony_ci opt->name = SANE_NAME_BRIGHTNESS; 3127141cc406Sopenharmony_ci opt->title = SANE_TITLE_BRIGHTNESS; 3128141cc406Sopenharmony_ci opt->desc = SANE_DESC_BRIGHTNESS; 3129141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3130141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3131141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3132141cc406Sopenharmony_ci opt->constraint.range = &s->brightness_range; 3133141cc406Sopenharmony_ci s->brightness_range.quant=1; 3134141cc406Sopenharmony_ci 3135141cc406Sopenharmony_ci /* some have hardware brightness (always 0 to 255?) */ 3136141cc406Sopenharmony_ci /* some use LUT or GT (-127 to +127)*/ 3137141cc406Sopenharmony_ci if (s->brightness_steps || s->num_download_gamma){ 3138141cc406Sopenharmony_ci s->brightness_range.min=-127; 3139141cc406Sopenharmony_ci s->brightness_range.max=127; 3140141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3141141cc406Sopenharmony_ci } 3142141cc406Sopenharmony_ci else{ 3143141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3144141cc406Sopenharmony_ci } 3145141cc406Sopenharmony_ci } 3146141cc406Sopenharmony_ci 3147141cc406Sopenharmony_ci /* contrast */ 3148141cc406Sopenharmony_ci if(option==OPT_CONTRAST){ 3149141cc406Sopenharmony_ci opt->name = SANE_NAME_CONTRAST; 3150141cc406Sopenharmony_ci opt->title = SANE_TITLE_CONTRAST; 3151141cc406Sopenharmony_ci opt->desc = SANE_DESC_CONTRAST; 3152141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3153141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3154141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3155141cc406Sopenharmony_ci opt->constraint.range = &s->contrast_range; 3156141cc406Sopenharmony_ci s->contrast_range.quant=1; 3157141cc406Sopenharmony_ci 3158141cc406Sopenharmony_ci /* some have hardware contrast (always 0 to 255?) */ 3159141cc406Sopenharmony_ci /* some use LUT or GT (-127 to +127)*/ 3160141cc406Sopenharmony_ci if (s->contrast_steps || s->num_download_gamma){ 3161141cc406Sopenharmony_ci s->contrast_range.min=-127; 3162141cc406Sopenharmony_ci s->contrast_range.max=127; 3163141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3164141cc406Sopenharmony_ci } 3165141cc406Sopenharmony_ci else { 3166141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3167141cc406Sopenharmony_ci } 3168141cc406Sopenharmony_ci } 3169141cc406Sopenharmony_ci 3170141cc406Sopenharmony_ci /* gamma */ 3171141cc406Sopenharmony_ci if(option==OPT_GAMMA){ 3172141cc406Sopenharmony_ci opt->name = "gamma"; 3173141cc406Sopenharmony_ci opt->title = SANE_I18N ("Gamma function exponent"); 3174141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Changes intensity of midtones"); 3175141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 3176141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3177141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3178141cc406Sopenharmony_ci opt->constraint.range = &s->gamma_range; 3179141cc406Sopenharmony_ci 3180141cc406Sopenharmony_ci /* value ranges from .3 to 5, should be log scale? */ 3181141cc406Sopenharmony_ci s->gamma_range.quant=SANE_FIX(0.01); 3182141cc406Sopenharmony_ci s->gamma_range.min=SANE_FIX(0.3); 3183141cc406Sopenharmony_ci s->gamma_range.max=SANE_FIX(5); 3184141cc406Sopenharmony_ci 3185141cc406Sopenharmony_ci /* scanner has gamma via LUT or GT */ 3186141cc406Sopenharmony_ci /*if (s->num_download_gamma){ 3187141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3188141cc406Sopenharmony_ci } 3189141cc406Sopenharmony_ci else { 3190141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3191141cc406Sopenharmony_ci }*/ 3192141cc406Sopenharmony_ci 3193141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3194141cc406Sopenharmony_ci } 3195141cc406Sopenharmony_ci 3196141cc406Sopenharmony_ci /*threshold*/ 3197141cc406Sopenharmony_ci if(option==OPT_THRESHOLD){ 3198141cc406Sopenharmony_ci opt->name = SANE_NAME_THRESHOLD; 3199141cc406Sopenharmony_ci opt->title = SANE_TITLE_THRESHOLD; 3200141cc406Sopenharmony_ci opt->desc = SANE_DESC_THRESHOLD; 3201141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3202141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3203141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3204141cc406Sopenharmony_ci opt->constraint.range = &s->threshold_range; 3205141cc406Sopenharmony_ci s->threshold_range.min=0; 3206141cc406Sopenharmony_ci s->threshold_range.max=s->threshold_steps; 3207141cc406Sopenharmony_ci s->threshold_range.quant=1; 3208141cc406Sopenharmony_ci 3209141cc406Sopenharmony_ci if (s->threshold_steps){ 3210141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3211141cc406Sopenharmony_ci if(s->u_mode != MODE_LINEART){ 3212141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3213141cc406Sopenharmony_ci } 3214141cc406Sopenharmony_ci } 3215141cc406Sopenharmony_ci else { 3216141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3217141cc406Sopenharmony_ci } 3218141cc406Sopenharmony_ci } 3219141cc406Sopenharmony_ci 3220141cc406Sopenharmony_ci /* =============== common ipc params ================================ */ 3221141cc406Sopenharmony_ci if(option==OPT_RIF){ 3222141cc406Sopenharmony_ci opt->name = "rif"; 3223141cc406Sopenharmony_ci opt->title = SANE_I18N ("RIF"); 3224141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Reverse image format"); 3225141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3226141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3227141cc406Sopenharmony_ci if (s->has_rif) 3228141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3229141cc406Sopenharmony_ci else 3230141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3231141cc406Sopenharmony_ci } 3232141cc406Sopenharmony_ci 3233141cc406Sopenharmony_ci if(option==OPT_HT_TYPE){ 3234141cc406Sopenharmony_ci i=0; 3235141cc406Sopenharmony_ci s->ht_type_list[i++]=STRING_DEFAULT; 3236141cc406Sopenharmony_ci s->ht_type_list[i++]=STRING_DITHER; 3237141cc406Sopenharmony_ci s->ht_type_list[i++]=STRING_DIFFUSION; 3238141cc406Sopenharmony_ci s->ht_type_list[i]=NULL; 3239141cc406Sopenharmony_ci 3240141cc406Sopenharmony_ci opt->name = "ht-type"; 3241141cc406Sopenharmony_ci opt->title = SANE_I18N ("Halftone type"); 3242141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Control type of halftone filter"); 3243141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3244141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3245141cc406Sopenharmony_ci 3246141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3247141cc406Sopenharmony_ci opt->constraint.string_list = s->ht_type_list; 3248141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3249141cc406Sopenharmony_ci 3250141cc406Sopenharmony_ci if(s->has_diffusion){ 3251141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3252141cc406Sopenharmony_ci if(s->s_mode != MODE_HALFTONE){ 3253141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3254141cc406Sopenharmony_ci } 3255141cc406Sopenharmony_ci } 3256141cc406Sopenharmony_ci else 3257141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3258141cc406Sopenharmony_ci } 3259141cc406Sopenharmony_ci 3260141cc406Sopenharmony_ci if(option==OPT_HT_PATTERN){ 3261141cc406Sopenharmony_ci opt->name = "ht-pattern"; 3262141cc406Sopenharmony_ci opt->title = SANE_I18N ("Halftone pattern"); 3263141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Control pattern of halftone filter"); 3264141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3265141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3266141cc406Sopenharmony_ci 3267141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3268141cc406Sopenharmony_ci opt->constraint.range = &s->ht_pattern_range; 3269141cc406Sopenharmony_ci s->ht_pattern_range.min=0; 3270141cc406Sopenharmony_ci s->ht_pattern_range.max=s->num_internal_dither - 1; 3271141cc406Sopenharmony_ci s->ht_pattern_range.quant=1; 3272141cc406Sopenharmony_ci 3273141cc406Sopenharmony_ci if (s->num_internal_dither){ 3274141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3275141cc406Sopenharmony_ci if(s->s_mode != MODE_HALFTONE){ 3276141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3277141cc406Sopenharmony_ci } 3278141cc406Sopenharmony_ci } 3279141cc406Sopenharmony_ci else 3280141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3281141cc406Sopenharmony_ci } 3282141cc406Sopenharmony_ci 3283141cc406Sopenharmony_ci if(option==OPT_OUTLINE){ 3284141cc406Sopenharmony_ci opt->name = "outline"; 3285141cc406Sopenharmony_ci opt->title = SANE_I18N ("Outline"); 3286141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Perform outline extraction"); 3287141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3288141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3289141cc406Sopenharmony_ci if (s->has_outline) 3290141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3291141cc406Sopenharmony_ci else 3292141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3293141cc406Sopenharmony_ci } 3294141cc406Sopenharmony_ci 3295141cc406Sopenharmony_ci if(option==OPT_EMPHASIS){ 3296141cc406Sopenharmony_ci opt->name = "emphasis"; 3297141cc406Sopenharmony_ci opt->title = SANE_I18N ("Emphasis"); 3298141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Negative to smooth or positive to sharpen image"); 3299141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3300141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3301141cc406Sopenharmony_ci 3302141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3303141cc406Sopenharmony_ci opt->constraint.range = &s->emphasis_range; 3304141cc406Sopenharmony_ci s->emphasis_range.min=-128; 3305141cc406Sopenharmony_ci s->emphasis_range.max=127; 3306141cc406Sopenharmony_ci s->emphasis_range.quant=1; 3307141cc406Sopenharmony_ci 3308141cc406Sopenharmony_ci if (s->has_emphasis) 3309141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3310141cc406Sopenharmony_ci else 3311141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3312141cc406Sopenharmony_ci } 3313141cc406Sopenharmony_ci 3314141cc406Sopenharmony_ci if(option==OPT_SEPARATION){ 3315141cc406Sopenharmony_ci opt->name = "separation"; 3316141cc406Sopenharmony_ci opt->title = SANE_I18N ("Separation"); 3317141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Enable automatic separation of image and text"); 3318141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3319141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3320141cc406Sopenharmony_ci if (s->has_autosep) 3321141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3322141cc406Sopenharmony_ci else 3323141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3324141cc406Sopenharmony_ci } 3325141cc406Sopenharmony_ci 3326141cc406Sopenharmony_ci if(option==OPT_MIRRORING){ 3327141cc406Sopenharmony_ci opt->name = "mirroring"; 3328141cc406Sopenharmony_ci opt->title = SANE_I18N ("Mirroring"); 3329141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Reflect output image horizontally"); 3330141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3331141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3332141cc406Sopenharmony_ci if (s->has_mirroring) 3333141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3334141cc406Sopenharmony_ci else 3335141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3336141cc406Sopenharmony_ci } 3337141cc406Sopenharmony_ci 3338141cc406Sopenharmony_ci if(option==OPT_WL_FOLLOW){ 3339141cc406Sopenharmony_ci i=0; 3340141cc406Sopenharmony_ci s->wl_follow_list[i++]=STRING_DEFAULT; 3341141cc406Sopenharmony_ci s->wl_follow_list[i++]=STRING_ON; 3342141cc406Sopenharmony_ci s->wl_follow_list[i++]=STRING_OFF; 3343141cc406Sopenharmony_ci s->wl_follow_list[i]=NULL; 3344141cc406Sopenharmony_ci 3345141cc406Sopenharmony_ci opt->name = "wl-follow"; 3346141cc406Sopenharmony_ci opt->title = SANE_I18N ("White level follower"); 3347141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Control white level follower"); 3348141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3349141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3350141cc406Sopenharmony_ci 3351141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3352141cc406Sopenharmony_ci opt->constraint.string_list = s->wl_follow_list; 3353141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3354141cc406Sopenharmony_ci 3355141cc406Sopenharmony_ci if (s->has_wl_follow) 3356141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3357141cc406Sopenharmony_ci else 3358141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3359141cc406Sopenharmony_ci } 3360141cc406Sopenharmony_ci 3361141cc406Sopenharmony_ci /* =============== DTC params ================================ */ 3362141cc406Sopenharmony_ci /* enabled when in dtc mode (manually or by default) */ 3363141cc406Sopenharmony_ci if(option==OPT_BP_FILTER){ 3364141cc406Sopenharmony_ci opt->name = "bp-filter"; 3365141cc406Sopenharmony_ci opt->title = SANE_I18N ("BP filter"); 3366141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Improves quality of high resolution ball-point pen text"); 3367141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3368141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3369141cc406Sopenharmony_ci 3370141cc406Sopenharmony_ci if ( s->has_dtc ){ 3371141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3372141cc406Sopenharmony_ci if(get_ipc_mode(s) == WD_ipc_SDTC){ 3373141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3374141cc406Sopenharmony_ci } 3375141cc406Sopenharmony_ci } 3376141cc406Sopenharmony_ci else 3377141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3378141cc406Sopenharmony_ci } 3379141cc406Sopenharmony_ci 3380141cc406Sopenharmony_ci if(option==OPT_SMOOTHING){ 3381141cc406Sopenharmony_ci opt->name = "smoothing"; 3382141cc406Sopenharmony_ci opt->title = SANE_I18N ("Smoothing"); 3383141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Enable smoothing for improved OCR"); 3384141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3385141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3386141cc406Sopenharmony_ci 3387141cc406Sopenharmony_ci if ( s->has_dtc ){ 3388141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3389141cc406Sopenharmony_ci if(get_ipc_mode(s) == WD_ipc_SDTC){ 3390141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3391141cc406Sopenharmony_ci } 3392141cc406Sopenharmony_ci } 3393141cc406Sopenharmony_ci else 3394141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3395141cc406Sopenharmony_ci } 3396141cc406Sopenharmony_ci 3397141cc406Sopenharmony_ci if(option==OPT_GAMMA_CURVE){ 3398141cc406Sopenharmony_ci opt->name = "gamma-curve"; 3399141cc406Sopenharmony_ci opt->title = SANE_I18N ("Gamma curve"); 3400141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Gamma curve, from light to dark, but upper two may not work"); 3401141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3402141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3403141cc406Sopenharmony_ci 3404141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3405141cc406Sopenharmony_ci opt->constraint.range = &s->gamma_curve_range; 3406141cc406Sopenharmony_ci s->gamma_curve_range.min=0; 3407141cc406Sopenharmony_ci s->gamma_curve_range.max=3; 3408141cc406Sopenharmony_ci s->gamma_curve_range.quant=1; 3409141cc406Sopenharmony_ci 3410141cc406Sopenharmony_ci if ( s->has_dtc ){ 3411141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3412141cc406Sopenharmony_ci if(get_ipc_mode(s) == WD_ipc_SDTC){ 3413141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3414141cc406Sopenharmony_ci } 3415141cc406Sopenharmony_ci } 3416141cc406Sopenharmony_ci else 3417141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3418141cc406Sopenharmony_ci } 3419141cc406Sopenharmony_ci 3420141cc406Sopenharmony_ci if(option==OPT_THRESHOLD_CURVE){ 3421141cc406Sopenharmony_ci opt->name = "threshold-curve"; 3422141cc406Sopenharmony_ci opt->title = SANE_I18N ("Threshold curve"); 3423141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Threshold curve, from light to dark, but upper two may not be linear"); 3424141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3425141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3426141cc406Sopenharmony_ci 3427141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3428141cc406Sopenharmony_ci opt->constraint.range = &s->threshold_curve_range; 3429141cc406Sopenharmony_ci s->threshold_curve_range.min=0; 3430141cc406Sopenharmony_ci s->threshold_curve_range.max=7; 3431141cc406Sopenharmony_ci s->threshold_curve_range.quant=1; 3432141cc406Sopenharmony_ci 3433141cc406Sopenharmony_ci if ( s->has_dtc ){ 3434141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3435141cc406Sopenharmony_ci if(get_ipc_mode(s) == WD_ipc_SDTC){ 3436141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3437141cc406Sopenharmony_ci } 3438141cc406Sopenharmony_ci } 3439141cc406Sopenharmony_ci else 3440141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3441141cc406Sopenharmony_ci } 3442141cc406Sopenharmony_ci 3443141cc406Sopenharmony_ci if(option==OPT_THRESHOLD_WHITE){ 3444141cc406Sopenharmony_ci opt->name = "threshold-white"; 3445141cc406Sopenharmony_ci opt->title = SANE_I18N ("Threshold white"); 3446141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Set pixels equal to threshold to white instead of black"); 3447141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3448141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3449141cc406Sopenharmony_ci 3450141cc406Sopenharmony_ci if ( s->has_dtc ){ 3451141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3452141cc406Sopenharmony_ci if(get_ipc_mode(s) == WD_ipc_SDTC){ 3453141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3454141cc406Sopenharmony_ci } 3455141cc406Sopenharmony_ci } 3456141cc406Sopenharmony_ci else 3457141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3458141cc406Sopenharmony_ci } 3459141cc406Sopenharmony_ci 3460141cc406Sopenharmony_ci if(option==OPT_NOISE_REMOVAL){ 3461141cc406Sopenharmony_ci opt->name = "noise-removal"; 3462141cc406Sopenharmony_ci opt->title = SANE_I18N ("Noise removal"); 3463141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Noise removal"); 3464141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3465141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3466141cc406Sopenharmony_ci 3467141cc406Sopenharmony_ci if ( s->has_dtc ){ 3468141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3469141cc406Sopenharmony_ci if(get_ipc_mode(s) == WD_ipc_SDTC){ 3470141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3471141cc406Sopenharmony_ci } 3472141cc406Sopenharmony_ci } 3473141cc406Sopenharmony_ci else 3474141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3475141cc406Sopenharmony_ci } 3476141cc406Sopenharmony_ci 3477141cc406Sopenharmony_ci if(option==OPT_MATRIX_5){ 3478141cc406Sopenharmony_ci opt->name = "matrix-5x5"; 3479141cc406Sopenharmony_ci opt->title = SANE_I18N ("Matrix 5x5"); 3480141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Remove 5 pixel square noise"); 3481141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3482141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3483141cc406Sopenharmony_ci 3484141cc406Sopenharmony_ci if ( s->has_dtc ){ 3485141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3486141cc406Sopenharmony_ci if(!s->noise_removal){ 3487141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3488141cc406Sopenharmony_ci } 3489141cc406Sopenharmony_ci } 3490141cc406Sopenharmony_ci else 3491141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3492141cc406Sopenharmony_ci } 3493141cc406Sopenharmony_ci 3494141cc406Sopenharmony_ci if(option==OPT_MATRIX_4){ 3495141cc406Sopenharmony_ci opt->name = "matrix-4x4"; 3496141cc406Sopenharmony_ci opt->title = SANE_I18N ("Matrix 4x4"); 3497141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Remove 4 pixel square noise"); 3498141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3499141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3500141cc406Sopenharmony_ci 3501141cc406Sopenharmony_ci if ( s->has_dtc ){ 3502141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3503141cc406Sopenharmony_ci if(!s->noise_removal){ 3504141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3505141cc406Sopenharmony_ci } 3506141cc406Sopenharmony_ci } 3507141cc406Sopenharmony_ci else 3508141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3509141cc406Sopenharmony_ci } 3510141cc406Sopenharmony_ci 3511141cc406Sopenharmony_ci if(option==OPT_MATRIX_3){ 3512141cc406Sopenharmony_ci opt->name = "matrix-3x3"; 3513141cc406Sopenharmony_ci opt->title = SANE_I18N ("Matrix 3x3"); 3514141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Remove 3 pixel square noise"); 3515141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3516141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3517141cc406Sopenharmony_ci 3518141cc406Sopenharmony_ci if ( s->has_dtc ){ 3519141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3520141cc406Sopenharmony_ci if(!s->noise_removal){ 3521141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3522141cc406Sopenharmony_ci } 3523141cc406Sopenharmony_ci } 3524141cc406Sopenharmony_ci else 3525141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3526141cc406Sopenharmony_ci } 3527141cc406Sopenharmony_ci 3528141cc406Sopenharmony_ci if(option==OPT_MATRIX_2){ 3529141cc406Sopenharmony_ci opt->name = "matrix-2x2"; 3530141cc406Sopenharmony_ci opt->title = SANE_I18N ("Matrix 2x2"); 3531141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Remove 2 pixel square noise"); 3532141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3533141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3534141cc406Sopenharmony_ci 3535141cc406Sopenharmony_ci if ( s->has_dtc ){ 3536141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3537141cc406Sopenharmony_ci if(!s->noise_removal){ 3538141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3539141cc406Sopenharmony_ci } 3540141cc406Sopenharmony_ci } 3541141cc406Sopenharmony_ci else 3542141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3543141cc406Sopenharmony_ci } 3544141cc406Sopenharmony_ci 3545141cc406Sopenharmony_ci /* =============== SDTC param ================================ */ 3546141cc406Sopenharmony_ci /* enabled when in sdtc mode (manually or by default) */ 3547141cc406Sopenharmony_ci /* called variance with ipc2, sensitivity with ipc3 */ 3548141cc406Sopenharmony_ci if(option==OPT_VARIANCE){ 3549141cc406Sopenharmony_ci opt->name = "variance"; 3550141cc406Sopenharmony_ci opt->title = SANE_I18N ("Variance"); 3551141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Set SDTC variance rate (sensitivity), 0 equals 127"); 3552141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3553141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3554141cc406Sopenharmony_ci 3555141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3556141cc406Sopenharmony_ci opt->constraint.range = &s->variance_range; 3557141cc406Sopenharmony_ci s->variance_range.min=0; 3558141cc406Sopenharmony_ci s->variance_range.max=255; 3559141cc406Sopenharmony_ci s->variance_range.quant=1; 3560141cc406Sopenharmony_ci 3561141cc406Sopenharmony_ci if ( s->has_sdtc ){ 3562141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3563141cc406Sopenharmony_ci if(get_ipc_mode(s) == WD_ipc_DTC){ 3564141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3565141cc406Sopenharmony_ci } 3566141cc406Sopenharmony_ci } 3567141cc406Sopenharmony_ci else 3568141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3569141cc406Sopenharmony_ci } 3570141cc406Sopenharmony_ci 3571141cc406Sopenharmony_ci /* "Advanced" group ------------------------------------------------------ */ 3572141cc406Sopenharmony_ci if(option==OPT_ADVANCED_GROUP){ 3573141cc406Sopenharmony_ci opt->name = SANE_NAME_ADVANCED; 3574141cc406Sopenharmony_ci opt->title = SANE_TITLE_ADVANCED; 3575141cc406Sopenharmony_ci opt->desc = SANE_DESC_ADVANCED; 3576141cc406Sopenharmony_ci opt->type = SANE_TYPE_GROUP; 3577141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 3578141cc406Sopenharmony_ci } 3579141cc406Sopenharmony_ci 3580141cc406Sopenharmony_ci /*automatic width detection */ 3581141cc406Sopenharmony_ci if(option==OPT_AWD){ 3582141cc406Sopenharmony_ci 3583141cc406Sopenharmony_ci opt->name = "awd"; 3584141cc406Sopenharmony_ci opt->title = SANE_I18N ("Auto width detection"); 3585141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Scanner detects paper sides. May reduce scanning speed."); 3586141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3587141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3588141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 3589141cc406Sopenharmony_ci 3590141cc406Sopenharmony_ci /* this option is useless by itself? */ 3591141cc406Sopenharmony_ci if (0 && s->has_MS_auto && s->has_hybrid_crop_deskew){ 3592141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3593141cc406Sopenharmony_ci } 3594141cc406Sopenharmony_ci else 3595141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3596141cc406Sopenharmony_ci } 3597141cc406Sopenharmony_ci 3598141cc406Sopenharmony_ci /*automatic length detection */ 3599141cc406Sopenharmony_ci if(option==OPT_ALD){ 3600141cc406Sopenharmony_ci 3601141cc406Sopenharmony_ci opt->name = "ald"; 3602141cc406Sopenharmony_ci opt->title = SANE_I18N ("Auto length detection"); 3603141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Scanner detects paper lower edge. May confuse some frontends."); 3604141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3605141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3606141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 3607141cc406Sopenharmony_ci 3608141cc406Sopenharmony_ci if (s->has_MS_auto){ 3609141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3610141cc406Sopenharmony_ci } 3611141cc406Sopenharmony_ci else 3612141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3613141cc406Sopenharmony_ci } 3614141cc406Sopenharmony_ci 3615141cc406Sopenharmony_ci /*image compression*/ 3616141cc406Sopenharmony_ci if(option==OPT_COMPRESS){ 3617141cc406Sopenharmony_ci i=0; 3618141cc406Sopenharmony_ci s->compress_list[i++]=STRING_NONE; 3619141cc406Sopenharmony_ci 3620141cc406Sopenharmony_ci if(s->has_comp_JPG1){ 3621141cc406Sopenharmony_ci#ifndef SANE_JPEG_DISABLED 3622141cc406Sopenharmony_ci s->compress_list[i++]=STRING_JPEG; 3623141cc406Sopenharmony_ci#endif 3624141cc406Sopenharmony_ci } 3625141cc406Sopenharmony_ci 3626141cc406Sopenharmony_ci s->compress_list[i]=NULL; 3627141cc406Sopenharmony_ci 3628141cc406Sopenharmony_ci opt->name = "compression"; 3629141cc406Sopenharmony_ci opt->title = SANE_I18N ("Compression"); 3630141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Enable compressed data. May crash your front-end program"); 3631141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3632141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3633141cc406Sopenharmony_ci opt->constraint.string_list = s->compress_list; 3634141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3635141cc406Sopenharmony_ci 3636141cc406Sopenharmony_ci if (i > 1){ 3637141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3638141cc406Sopenharmony_ci if ( must_downsample(s) || s->s_mode < MODE_GRAYSCALE ){ 3639141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3640141cc406Sopenharmony_ci } 3641141cc406Sopenharmony_ci } 3642141cc406Sopenharmony_ci else 3643141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3644141cc406Sopenharmony_ci } 3645141cc406Sopenharmony_ci 3646141cc406Sopenharmony_ci /*image compression arg*/ 3647141cc406Sopenharmony_ci if(option==OPT_COMPRESS_ARG){ 3648141cc406Sopenharmony_ci 3649141cc406Sopenharmony_ci opt->name = "compression-arg"; 3650141cc406Sopenharmony_ci opt->title = SANE_I18N ("Compression argument"); 3651141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4"); 3652141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3653141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3654141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3655141cc406Sopenharmony_ci opt->constraint.range = &s->compress_arg_range; 3656141cc406Sopenharmony_ci s->compress_arg_range.quant=1; 3657141cc406Sopenharmony_ci 3658141cc406Sopenharmony_ci if(s->has_comp_JPG1){ 3659141cc406Sopenharmony_ci s->compress_arg_range.min=0; 3660141cc406Sopenharmony_ci s->compress_arg_range.max=7; 3661141cc406Sopenharmony_ci#ifndef SANE_JPEG_DISABLED 3662141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 3663141cc406Sopenharmony_ci#endif 3664141cc406Sopenharmony_ci 3665141cc406Sopenharmony_ci if(s->compress != COMP_JPEG){ 3666141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3667141cc406Sopenharmony_ci } 3668141cc406Sopenharmony_ci } 3669141cc406Sopenharmony_ci else 3670141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3671141cc406Sopenharmony_ci } 3672141cc406Sopenharmony_ci 3673141cc406Sopenharmony_ci /*double feed detection*/ 3674141cc406Sopenharmony_ci if(option==OPT_DF_ACTION){ 3675141cc406Sopenharmony_ci s->df_action_list[0] = STRING_DEFAULT; 3676141cc406Sopenharmony_ci s->df_action_list[1] = STRING_CONTINUE; 3677141cc406Sopenharmony_ci s->df_action_list[2] = STRING_STOP; 3678141cc406Sopenharmony_ci s->df_action_list[3] = NULL; 3679141cc406Sopenharmony_ci 3680141cc406Sopenharmony_ci opt->name = "df-action"; 3681141cc406Sopenharmony_ci opt->title = SANE_I18N ("DF action"); 3682141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Action following double feed error"); 3683141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3684141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3685141cc406Sopenharmony_ci opt->constraint.string_list = s->df_action_list; 3686141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3687141cc406Sopenharmony_ci 3688141cc406Sopenharmony_ci if (s->has_MS_df) 3689141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3690141cc406Sopenharmony_ci else 3691141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3692141cc406Sopenharmony_ci } 3693141cc406Sopenharmony_ci 3694141cc406Sopenharmony_ci /*double feed by skew*/ 3695141cc406Sopenharmony_ci if(option==OPT_DF_SKEW){ 3696141cc406Sopenharmony_ci 3697141cc406Sopenharmony_ci opt->name = "df-skew"; 3698141cc406Sopenharmony_ci opt->title = SANE_I18N ("DF skew"); 3699141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Enable double feed error due to skew"); 3700141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3701141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3702141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 3703141cc406Sopenharmony_ci 3704141cc406Sopenharmony_ci if (s->has_MS_df){ 3705141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3706141cc406Sopenharmony_ci if(!s->df_action) 3707141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3708141cc406Sopenharmony_ci } 3709141cc406Sopenharmony_ci else 3710141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3711141cc406Sopenharmony_ci } 3712141cc406Sopenharmony_ci 3713141cc406Sopenharmony_ci /*double feed by thickness */ 3714141cc406Sopenharmony_ci if(option==OPT_DF_THICKNESS){ 3715141cc406Sopenharmony_ci 3716141cc406Sopenharmony_ci opt->name = "df-thickness"; 3717141cc406Sopenharmony_ci opt->title = SANE_I18N ("DF thickness"); 3718141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Enable double feed error due to paper thickness"); 3719141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3720141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3721141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 3722141cc406Sopenharmony_ci 3723141cc406Sopenharmony_ci if (s->has_MS_df){ 3724141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3725141cc406Sopenharmony_ci if(!s->df_action) 3726141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3727141cc406Sopenharmony_ci } 3728141cc406Sopenharmony_ci else 3729141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3730141cc406Sopenharmony_ci } 3731141cc406Sopenharmony_ci 3732141cc406Sopenharmony_ci /*double feed by length*/ 3733141cc406Sopenharmony_ci if(option==OPT_DF_LENGTH){ 3734141cc406Sopenharmony_ci 3735141cc406Sopenharmony_ci opt->name = "df-length"; 3736141cc406Sopenharmony_ci opt->title = SANE_I18N ("DF length"); 3737141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Enable double feed error due to paper length"); 3738141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 3739141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3740141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 3741141cc406Sopenharmony_ci 3742141cc406Sopenharmony_ci if (s->has_MS_df){ 3743141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3744141cc406Sopenharmony_ci if(!s->df_action) 3745141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3746141cc406Sopenharmony_ci } 3747141cc406Sopenharmony_ci else 3748141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3749141cc406Sopenharmony_ci } 3750141cc406Sopenharmony_ci 3751141cc406Sopenharmony_ci /*double feed length difference*/ 3752141cc406Sopenharmony_ci if(option==OPT_DF_DIFF){ 3753141cc406Sopenharmony_ci s->df_diff_list[0] = STRING_DEFAULT; 3754141cc406Sopenharmony_ci s->df_diff_list[1] = STRING_10MM; 3755141cc406Sopenharmony_ci s->df_diff_list[2] = STRING_15MM; 3756141cc406Sopenharmony_ci s->df_diff_list[3] = STRING_20MM; 3757141cc406Sopenharmony_ci s->df_diff_list[4] = NULL; 3758141cc406Sopenharmony_ci 3759141cc406Sopenharmony_ci opt->name = "df-diff"; 3760141cc406Sopenharmony_ci opt->title = SANE_I18N ("DF length difference"); 3761141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Difference in page length to trigger double feed error"); 3762141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3763141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3764141cc406Sopenharmony_ci opt->constraint.string_list = s->df_diff_list; 3765141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3766141cc406Sopenharmony_ci 3767141cc406Sopenharmony_ci if (s->has_MS_df){ 3768141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3769141cc406Sopenharmony_ci if(!s->df_action || !s->df_diff) 3770141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3771141cc406Sopenharmony_ci } 3772141cc406Sopenharmony_ci else 3773141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3774141cc406Sopenharmony_ci } 3775141cc406Sopenharmony_ci 3776141cc406Sopenharmony_ci /*df_recovery*/ 3777141cc406Sopenharmony_ci if(option==OPT_DF_RECOVERY){ 3778141cc406Sopenharmony_ci s->df_recovery_list[0] = STRING_DEFAULT; 3779141cc406Sopenharmony_ci s->df_recovery_list[1] = STRING_OFF; 3780141cc406Sopenharmony_ci s->df_recovery_list[2] = STRING_ON; 3781141cc406Sopenharmony_ci s->df_recovery_list[3] = NULL; 3782141cc406Sopenharmony_ci 3783141cc406Sopenharmony_ci opt->name = "df-recovery"; 3784141cc406Sopenharmony_ci opt->title = SANE_I18N ("DF recovery mode"); 3785141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request scanner to reverse feed on paper jam"); 3786141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3787141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3788141cc406Sopenharmony_ci opt->constraint.string_list = s->df_recovery_list; 3789141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3790141cc406Sopenharmony_ci if (s->has_MS_df && s->has_df_recovery) 3791141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3792141cc406Sopenharmony_ci else 3793141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3794141cc406Sopenharmony_ci } 3795141cc406Sopenharmony_ci 3796141cc406Sopenharmony_ci /*paper_protect*/ 3797141cc406Sopenharmony_ci if(option==OPT_PAPER_PROTECT){ 3798141cc406Sopenharmony_ci s->paper_protect_list[0] = STRING_DEFAULT; 3799141cc406Sopenharmony_ci s->paper_protect_list[1] = STRING_OFF; 3800141cc406Sopenharmony_ci s->paper_protect_list[2] = STRING_ON; 3801141cc406Sopenharmony_ci s->paper_protect_list[3] = NULL; 3802141cc406Sopenharmony_ci 3803141cc406Sopenharmony_ci opt->name = "paper-protect"; 3804141cc406Sopenharmony_ci opt->title = SANE_I18N ("Paper protection"); 3805141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request scanner to predict jams in the ADF"); 3806141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3807141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3808141cc406Sopenharmony_ci opt->constraint.string_list = s->paper_protect_list; 3809141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3810141cc406Sopenharmony_ci if (s->has_MS_df && s->has_paper_protect) 3811141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3812141cc406Sopenharmony_ci else 3813141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3814141cc406Sopenharmony_ci } 3815141cc406Sopenharmony_ci 3816141cc406Sopenharmony_ci /*adv_paper_prot*/ 3817141cc406Sopenharmony_ci if(option==OPT_ADV_PAPER_PROT){ 3818141cc406Sopenharmony_ci s->adv_paper_prot_list[0] = STRING_DEFAULT; 3819141cc406Sopenharmony_ci s->adv_paper_prot_list[1] = STRING_OFF; 3820141cc406Sopenharmony_ci s->adv_paper_prot_list[2] = STRING_ON; 3821141cc406Sopenharmony_ci s->adv_paper_prot_list[3] = NULL; 3822141cc406Sopenharmony_ci 3823141cc406Sopenharmony_ci opt->name = "adv-paper-protect"; 3824141cc406Sopenharmony_ci opt->title = SANE_I18N ("Advanced paper protection"); 3825141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request scanner to predict jams in the ADF using improved sensors"); 3826141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3827141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3828141cc406Sopenharmony_ci opt->constraint.string_list = s->adv_paper_prot_list; 3829141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3830141cc406Sopenharmony_ci if (s->has_MS_df && s->has_adv_paper_prot) 3831141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3832141cc406Sopenharmony_ci else 3833141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3834141cc406Sopenharmony_ci } 3835141cc406Sopenharmony_ci 3836141cc406Sopenharmony_ci /*staple detection*/ 3837141cc406Sopenharmony_ci if(option==OPT_STAPLE_DETECT){ 3838141cc406Sopenharmony_ci s->staple_detect_list[0] = STRING_DEFAULT; 3839141cc406Sopenharmony_ci s->staple_detect_list[1] = STRING_OFF; 3840141cc406Sopenharmony_ci s->staple_detect_list[2] = STRING_ON; 3841141cc406Sopenharmony_ci s->staple_detect_list[3] = NULL; 3842141cc406Sopenharmony_ci 3843141cc406Sopenharmony_ci opt->name = "staple-detect"; 3844141cc406Sopenharmony_ci opt->title = SANE_I18N ("Staple detection"); 3845141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request scanner to detect jams in the ADF caused by staples"); 3846141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3847141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3848141cc406Sopenharmony_ci opt->constraint.string_list = s->staple_detect_list; 3849141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3850141cc406Sopenharmony_ci if (s->has_MS_df && s->has_staple_detect) 3851141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3852141cc406Sopenharmony_ci else 3853141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3854141cc406Sopenharmony_ci } 3855141cc406Sopenharmony_ci 3856141cc406Sopenharmony_ci /*background color*/ 3857141cc406Sopenharmony_ci if(option==OPT_BG_COLOR){ 3858141cc406Sopenharmony_ci s->bg_color_list[0] = STRING_DEFAULT; 3859141cc406Sopenharmony_ci s->bg_color_list[1] = STRING_WHITE; 3860141cc406Sopenharmony_ci s->bg_color_list[2] = STRING_BLACK; 3861141cc406Sopenharmony_ci s->bg_color_list[3] = NULL; 3862141cc406Sopenharmony_ci 3863141cc406Sopenharmony_ci opt->name = "bgcolor"; 3864141cc406Sopenharmony_ci opt->title = SANE_I18N ("Background color"); 3865141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Set color of background for scans. May conflict with overscan option"); 3866141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3867141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3868141cc406Sopenharmony_ci opt->constraint.string_list = s->bg_color_list; 3869141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3870141cc406Sopenharmony_ci if (s->has_MS_bg) 3871141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3872141cc406Sopenharmony_ci else 3873141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3874141cc406Sopenharmony_ci } 3875141cc406Sopenharmony_ci 3876141cc406Sopenharmony_ci /*dropout color*/ 3877141cc406Sopenharmony_ci if(option==OPT_DROPOUT_COLOR){ 3878141cc406Sopenharmony_ci s->do_color_list[0] = STRING_DEFAULT; 3879141cc406Sopenharmony_ci s->do_color_list[1] = STRING_RED; 3880141cc406Sopenharmony_ci s->do_color_list[2] = STRING_GREEN; 3881141cc406Sopenharmony_ci s->do_color_list[3] = STRING_BLUE; 3882141cc406Sopenharmony_ci s->do_color_list[4] = NULL; 3883141cc406Sopenharmony_ci 3884141cc406Sopenharmony_ci opt->name = "dropoutcolor"; 3885141cc406Sopenharmony_ci opt->title = SANE_I18N ("Dropout color"); 3886141cc406Sopenharmony_ci opt->desc = SANE_I18N ("One-pass scanners use only one color during gray or binary scanning, useful for colored paper or ink"); 3887141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3888141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3889141cc406Sopenharmony_ci opt->constraint.string_list = s->do_color_list; 3890141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3891141cc406Sopenharmony_ci 3892141cc406Sopenharmony_ci if (s->has_MS_dropout || s->has_vuid_3091 || must_downsample(s)){ 3893141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; 3894141cc406Sopenharmony_ci if(s->u_mode == MODE_COLOR) 3895141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 3896141cc406Sopenharmony_ci } 3897141cc406Sopenharmony_ci else 3898141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3899141cc406Sopenharmony_ci } 3900141cc406Sopenharmony_ci 3901141cc406Sopenharmony_ci /*buffer mode*/ 3902141cc406Sopenharmony_ci if(option==OPT_BUFF_MODE){ 3903141cc406Sopenharmony_ci s->buff_mode_list[0] = STRING_DEFAULT; 3904141cc406Sopenharmony_ci s->buff_mode_list[1] = STRING_OFF; 3905141cc406Sopenharmony_ci s->buff_mode_list[2] = STRING_ON; 3906141cc406Sopenharmony_ci s->buff_mode_list[3] = NULL; 3907141cc406Sopenharmony_ci 3908141cc406Sopenharmony_ci opt->name = "buffermode"; 3909141cc406Sopenharmony_ci opt->title = SANE_I18N ("Buffer mode"); 3910141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request scanner to read pages quickly from ADF into internal memory"); 3911141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3912141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3913141cc406Sopenharmony_ci opt->constraint.string_list = s->buff_mode_list; 3914141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3915141cc406Sopenharmony_ci if (s->has_MS_buff) 3916141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3917141cc406Sopenharmony_ci else 3918141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3919141cc406Sopenharmony_ci } 3920141cc406Sopenharmony_ci 3921141cc406Sopenharmony_ci /*prepick*/ 3922141cc406Sopenharmony_ci if(option==OPT_PREPICK){ 3923141cc406Sopenharmony_ci s->prepick_list[0] = STRING_DEFAULT; 3924141cc406Sopenharmony_ci s->prepick_list[1] = STRING_OFF; 3925141cc406Sopenharmony_ci s->prepick_list[2] = STRING_ON; 3926141cc406Sopenharmony_ci s->prepick_list[3] = NULL; 3927141cc406Sopenharmony_ci 3928141cc406Sopenharmony_ci opt->name = "prepick"; 3929141cc406Sopenharmony_ci opt->title = SANE_I18N ("Prepick"); 3930141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request scanner to grab next page from ADF"); 3931141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3932141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3933141cc406Sopenharmony_ci opt->constraint.string_list = s->prepick_list; 3934141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3935141cc406Sopenharmony_ci if (s->has_MS_prepick) 3936141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3937141cc406Sopenharmony_ci else 3938141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3939141cc406Sopenharmony_ci } 3940141cc406Sopenharmony_ci 3941141cc406Sopenharmony_ci /*overscan*/ 3942141cc406Sopenharmony_ci if(option==OPT_OVERSCAN){ 3943141cc406Sopenharmony_ci s->overscan_list[0] = STRING_DEFAULT; 3944141cc406Sopenharmony_ci s->overscan_list[1] = STRING_OFF; 3945141cc406Sopenharmony_ci s->overscan_list[2] = STRING_ON; 3946141cc406Sopenharmony_ci s->overscan_list[3] = NULL; 3947141cc406Sopenharmony_ci 3948141cc406Sopenharmony_ci opt->name = "overscan"; 3949141cc406Sopenharmony_ci opt->title = SANE_I18N ("Overscan"); 3950141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor option"); 3951141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 3952141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 3953141cc406Sopenharmony_ci opt->constraint.string_list = s->overscan_list; 3954141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 3955141cc406Sopenharmony_ci if (s->has_MS_auto && (s->os_x_basic || s->os_y_basic)) 3956141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3957141cc406Sopenharmony_ci else 3958141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3959141cc406Sopenharmony_ci } 3960141cc406Sopenharmony_ci 3961141cc406Sopenharmony_ci /*sleep_time*/ 3962141cc406Sopenharmony_ci if(option==OPT_SLEEP_TIME){ 3963141cc406Sopenharmony_ci s->sleep_time_range.min = 0; 3964141cc406Sopenharmony_ci s->sleep_time_range.max = 60; 3965141cc406Sopenharmony_ci s->sleep_time_range.quant = 1; 3966141cc406Sopenharmony_ci 3967141cc406Sopenharmony_ci opt->name = "sleeptimer"; 3968141cc406Sopenharmony_ci opt->title = SANE_I18N ("Sleep timer"); 3969141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Time in minutes until the internal power supply switches to sleep mode"); 3970141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3971141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3972141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3973141cc406Sopenharmony_ci opt->constraint.range=&s->sleep_time_range; 3974141cc406Sopenharmony_ci if(s->has_MS_sleep) 3975141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3976141cc406Sopenharmony_ci else 3977141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3978141cc406Sopenharmony_ci } 3979141cc406Sopenharmony_ci 3980141cc406Sopenharmony_ci /*off_time*/ 3981141cc406Sopenharmony_ci if(option==OPT_OFF_TIME){ 3982141cc406Sopenharmony_ci s->off_time_range.min = 0; 3983141cc406Sopenharmony_ci s->off_time_range.max = 960; 3984141cc406Sopenharmony_ci s->off_time_range.quant = 1; 3985141cc406Sopenharmony_ci 3986141cc406Sopenharmony_ci opt->name = "offtimer"; 3987141cc406Sopenharmony_ci opt->title = SANE_I18N ("Off timer"); 3988141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off."); 3989141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 3990141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 3991141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 3992141cc406Sopenharmony_ci opt->constraint.range=&s->off_time_range; 3993141cc406Sopenharmony_ci if(s->has_off_mode) 3994141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 3995141cc406Sopenharmony_ci else 3996141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 3997141cc406Sopenharmony_ci } 3998141cc406Sopenharmony_ci 3999141cc406Sopenharmony_ci /*duplex offset*/ 4000141cc406Sopenharmony_ci if(option==OPT_DUPLEX_OFFSET){ 4001141cc406Sopenharmony_ci s->duplex_offset_range.min = -16; 4002141cc406Sopenharmony_ci s->duplex_offset_range.max = 16; 4003141cc406Sopenharmony_ci s->duplex_offset_range.quant = 1; 4004141cc406Sopenharmony_ci 4005141cc406Sopenharmony_ci opt->name = "duplexoffset"; 4006141cc406Sopenharmony_ci opt->title = SANE_I18N ("Duplex offset"); 4007141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Adjust front/back offset"); 4008141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4009141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4010141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4011141cc406Sopenharmony_ci opt->constraint.range = &s->duplex_offset_range; 4012141cc406Sopenharmony_ci if(s->duplex_interlace == DUPLEX_INTERLACE_3091) 4013141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4014141cc406Sopenharmony_ci else 4015141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4016141cc406Sopenharmony_ci } 4017141cc406Sopenharmony_ci 4018141cc406Sopenharmony_ci if(option==OPT_GREEN_OFFSET){ 4019141cc406Sopenharmony_ci s->green_offset_range.min = -16; 4020141cc406Sopenharmony_ci s->green_offset_range.max = 16; 4021141cc406Sopenharmony_ci s->green_offset_range.quant = 1; 4022141cc406Sopenharmony_ci 4023141cc406Sopenharmony_ci opt->name = "greenoffset"; 4024141cc406Sopenharmony_ci opt->title = SANE_I18N ("Green offset"); 4025141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Adjust green/red offset"); 4026141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4027141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4028141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4029141cc406Sopenharmony_ci opt->constraint.range = &s->green_offset_range; 4030141cc406Sopenharmony_ci if(s->color_interlace == COLOR_INTERLACE_3091) 4031141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4032141cc406Sopenharmony_ci else 4033141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4034141cc406Sopenharmony_ci } 4035141cc406Sopenharmony_ci 4036141cc406Sopenharmony_ci if(option==OPT_BLUE_OFFSET){ 4037141cc406Sopenharmony_ci s->blue_offset_range.min = -16; 4038141cc406Sopenharmony_ci s->blue_offset_range.max = 16; 4039141cc406Sopenharmony_ci s->blue_offset_range.quant = 1; 4040141cc406Sopenharmony_ci 4041141cc406Sopenharmony_ci opt->name = "blueoffset"; 4042141cc406Sopenharmony_ci opt->title = SANE_I18N ("Blue offset"); 4043141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Adjust blue/red offset"); 4044141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4045141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4046141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4047141cc406Sopenharmony_ci opt->constraint.range = &s->blue_offset_range; 4048141cc406Sopenharmony_ci if(s->color_interlace == COLOR_INTERLACE_3091) 4049141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4050141cc406Sopenharmony_ci else 4051141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4052141cc406Sopenharmony_ci } 4053141cc406Sopenharmony_ci 4054141cc406Sopenharmony_ci if(option==OPT_LOW_MEM){ 4055141cc406Sopenharmony_ci opt->name = "lowmemory"; 4056141cc406Sopenharmony_ci opt->title = SANE_I18N ("Low Memory"); 4057141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option 'side' can be used to determine correct image. This option should only be used with custom front-end software."); 4058141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4059141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4060141cc406Sopenharmony_ci opt->size = sizeof(SANE_Word); 4061141cc406Sopenharmony_ci 4062141cc406Sopenharmony_ci if (1) 4063141cc406Sopenharmony_ci opt->cap= SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4064141cc406Sopenharmony_ci else 4065141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4066141cc406Sopenharmony_ci 4067141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 4068141cc406Sopenharmony_ci } 4069141cc406Sopenharmony_ci 4070141cc406Sopenharmony_ci if(option==OPT_SIDE){ 4071141cc406Sopenharmony_ci opt->name = "side"; 4072141cc406Sopenharmony_ci opt->title = SANE_I18N ("Duplex side"); 4073141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Tells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return."); 4074141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4075141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4076141cc406Sopenharmony_ci opt->size = sizeof(SANE_Word); 4077141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4078141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 4079141cc406Sopenharmony_ci } 4080141cc406Sopenharmony_ci 4081141cc406Sopenharmony_ci /*deskew and crop by hardware*/ 4082141cc406Sopenharmony_ci if(option==OPT_HWDESKEWCROP){ 4083141cc406Sopenharmony_ci opt->name = "hwdeskewcrop"; 4084141cc406Sopenharmony_ci opt->title = SANE_I18N ("Hardware deskew and crop"); 4085141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request scanner to rotate and crop pages digitally."); 4086141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4087141cc406Sopenharmony_ci if (s->has_hybrid_crop_deskew) 4088141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4089141cc406Sopenharmony_ci else 4090141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4091141cc406Sopenharmony_ci } 4092141cc406Sopenharmony_ci 4093141cc406Sopenharmony_ci /*deskew by software*/ 4094141cc406Sopenharmony_ci if(option==OPT_SWDESKEW){ 4095141cc406Sopenharmony_ci opt->name = "swdeskew"; 4096141cc406Sopenharmony_ci opt->title = SANE_I18N ("Software deskew"); 4097141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request driver to rotate skewed pages digitally."); 4098141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4099141cc406Sopenharmony_ci if (1) 4100141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4101141cc406Sopenharmony_ci else 4102141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4103141cc406Sopenharmony_ci } 4104141cc406Sopenharmony_ci 4105141cc406Sopenharmony_ci /*software despeckle radius*/ 4106141cc406Sopenharmony_ci if(option==OPT_SWDESPECK){ 4107141cc406Sopenharmony_ci 4108141cc406Sopenharmony_ci opt->name = "swdespeck"; 4109141cc406Sopenharmony_ci opt->title = SANE_I18N ("Software despeckle diameter"); 4110141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Maximum diameter of lone dots to remove from scan."); 4111141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4112141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4113141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4114141cc406Sopenharmony_ci opt->constraint.range = &s->swdespeck_range; 4115141cc406Sopenharmony_ci s->swdespeck_range.quant=1; 4116141cc406Sopenharmony_ci 4117141cc406Sopenharmony_ci if(1){ 4118141cc406Sopenharmony_ci s->swdespeck_range.min=0; 4119141cc406Sopenharmony_ci s->swdespeck_range.max=9; 4120141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 4121141cc406Sopenharmony_ci } 4122141cc406Sopenharmony_ci else 4123141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4124141cc406Sopenharmony_ci } 4125141cc406Sopenharmony_ci 4126141cc406Sopenharmony_ci /*crop by software*/ 4127141cc406Sopenharmony_ci if(option==OPT_SWCROP){ 4128141cc406Sopenharmony_ci opt->name = "swcrop"; 4129141cc406Sopenharmony_ci opt->title = SANE_I18N ("Software crop"); 4130141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request driver to remove border from pages digitally."); 4131141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4132141cc406Sopenharmony_ci if (1) 4133141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4134141cc406Sopenharmony_ci else 4135141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4136141cc406Sopenharmony_ci } 4137141cc406Sopenharmony_ci 4138141cc406Sopenharmony_ci /* Software blank page skip */ 4139141cc406Sopenharmony_ci if(option==OPT_SWSKIP){ 4140141cc406Sopenharmony_ci 4141141cc406Sopenharmony_ci opt->name = "swskip"; 4142141cc406Sopenharmony_ci opt->title = SANE_I18N ("Software blank skip percentage"); 4143141cc406Sopenharmony_ci opt->desc = SANE_I18N("Request driver to discard pages with low percentage of dark pixels"); 4144141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 4145141cc406Sopenharmony_ci opt->unit = SANE_UNIT_PERCENT; 4146141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4147141cc406Sopenharmony_ci opt->constraint.range = &s->swskip_range; 4148141cc406Sopenharmony_ci 4149141cc406Sopenharmony_ci s->swskip_range.quant=SANE_FIX(0.10001); 4150141cc406Sopenharmony_ci s->swskip_range.min=SANE_FIX(0); 4151141cc406Sopenharmony_ci s->swskip_range.max=SANE_FIX(100); 4152141cc406Sopenharmony_ci 4153141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 4154141cc406Sopenharmony_ci } 4155141cc406Sopenharmony_ci 4156141cc406Sopenharmony_ci /*halt scanner feeder when cancelling*/ 4157141cc406Sopenharmony_ci if(option==OPT_HALT_ON_CANCEL){ 4158141cc406Sopenharmony_ci opt->name = "halt-on-cancel"; 4159141cc406Sopenharmony_ci opt->title = SANE_I18N ("Halt on Cancel"); 4160141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Request driver to halt the paper feed instead of eject during a cancel."); 4161141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4162141cc406Sopenharmony_ci if (s->has_op_halt) 4163141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4164141cc406Sopenharmony_ci else 4165141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4166141cc406Sopenharmony_ci } 4167141cc406Sopenharmony_ci 4168141cc406Sopenharmony_ci /* "Endorser" group ------------------------------------------------------ */ 4169141cc406Sopenharmony_ci if(option==OPT_ENDORSER_GROUP){ 4170141cc406Sopenharmony_ci opt->name = "endorser-options"; 4171141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser Options"); 4172141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Controls for endorser unit"); 4173141cc406Sopenharmony_ci opt->type = SANE_TYPE_GROUP; 4174141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 4175141cc406Sopenharmony_ci 4176141cc406Sopenharmony_ci /*flaming hack to get scanimage to hide group*/ 4177141cc406Sopenharmony_ci if ( !(s->has_endorser_f || s->has_endorser_b) ) 4178141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4179141cc406Sopenharmony_ci } 4180141cc406Sopenharmony_ci 4181141cc406Sopenharmony_ci if(option==OPT_ENDORSER){ 4182141cc406Sopenharmony_ci opt->name = "endorser"; 4183141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser"); 4184141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Enable endorser unit"); 4185141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4186141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4187141cc406Sopenharmony_ci opt->size = sizeof(SANE_Word); 4188141cc406Sopenharmony_ci 4189141cc406Sopenharmony_ci if (s->has_endorser_f || s->has_endorser_b) 4190141cc406Sopenharmony_ci opt->cap= SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4191141cc406Sopenharmony_ci else 4192141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4193141cc406Sopenharmony_ci 4194141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 4195141cc406Sopenharmony_ci } 4196141cc406Sopenharmony_ci 4197141cc406Sopenharmony_ci if(option==OPT_ENDORSER_BITS){ 4198141cc406Sopenharmony_ci opt->name = "endorser-bits"; 4199141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser bits"); 4200141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Determines maximum endorser counter value."); 4201141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4202141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4203141cc406Sopenharmony_ci opt->size = sizeof(SANE_Word); 4204141cc406Sopenharmony_ci 4205141cc406Sopenharmony_ci /*old type can't do this?*/ 4206141cc406Sopenharmony_ci if ((s->has_endorser_f && s->endorser_type_f != ET_OLD) 4207141cc406Sopenharmony_ci || (s->has_endorser_b && s->endorser_type_b != ET_OLD)){ 4208141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4209141cc406Sopenharmony_ci if(!s->u_endorser) 4210141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4211141cc406Sopenharmony_ci } 4212141cc406Sopenharmony_ci else 4213141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4214141cc406Sopenharmony_ci 4215141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4216141cc406Sopenharmony_ci opt->constraint.range = &s->endorser_bits_range; 4217141cc406Sopenharmony_ci 4218141cc406Sopenharmony_ci s->endorser_bits_range.min = 16; 4219141cc406Sopenharmony_ci s->endorser_bits_range.max = 24; 4220141cc406Sopenharmony_ci s->endorser_bits_range.quant = 8; 4221141cc406Sopenharmony_ci } 4222141cc406Sopenharmony_ci 4223141cc406Sopenharmony_ci if(option==OPT_ENDORSER_VAL){ 4224141cc406Sopenharmony_ci opt->name = "endorser-val"; 4225141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser value"); 4226141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Initial endorser counter value."); 4227141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4228141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4229141cc406Sopenharmony_ci opt->size = sizeof(SANE_Word); 4230141cc406Sopenharmony_ci 4231141cc406Sopenharmony_ci if (s->has_endorser_f || s->has_endorser_b){ 4232141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4233141cc406Sopenharmony_ci if(!s->u_endorser) 4234141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4235141cc406Sopenharmony_ci } 4236141cc406Sopenharmony_ci else 4237141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4238141cc406Sopenharmony_ci 4239141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4240141cc406Sopenharmony_ci opt->constraint.range = &s->endorser_val_range; 4241141cc406Sopenharmony_ci 4242141cc406Sopenharmony_ci s->endorser_val_range.min = 0; 4243141cc406Sopenharmony_ci s->endorser_val_range.max = (1 << s->u_endorser_bits)-1; 4244141cc406Sopenharmony_ci s->endorser_val_range.quant = 1; 4245141cc406Sopenharmony_ci } 4246141cc406Sopenharmony_ci 4247141cc406Sopenharmony_ci if(option==OPT_ENDORSER_STEP){ 4248141cc406Sopenharmony_ci opt->name = "endorser-step"; 4249141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser step"); 4250141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Change endorser counter value by this much for each page."); 4251141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4252141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4253141cc406Sopenharmony_ci opt->size = sizeof(SANE_Word); 4254141cc406Sopenharmony_ci 4255141cc406Sopenharmony_ci if (s->has_endorser_f || s->has_endorser_b){ 4256141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4257141cc406Sopenharmony_ci if(!s->u_endorser) 4258141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4259141cc406Sopenharmony_ci } 4260141cc406Sopenharmony_ci else 4261141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4262141cc406Sopenharmony_ci 4263141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4264141cc406Sopenharmony_ci opt->constraint.range = &s->endorser_step_range; 4265141cc406Sopenharmony_ci 4266141cc406Sopenharmony_ci s->endorser_step_range.min = -2; 4267141cc406Sopenharmony_ci s->endorser_step_range.max = 2; 4268141cc406Sopenharmony_ci s->endorser_step_range.quant = 1; 4269141cc406Sopenharmony_ci } 4270141cc406Sopenharmony_ci 4271141cc406Sopenharmony_ci if(option==OPT_ENDORSER_Y){ 4272141cc406Sopenharmony_ci opt->name = "endorser-y"; 4273141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser Y"); 4274141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Endorser print offset from top of paper."); 4275141cc406Sopenharmony_ci opt->type = SANE_TYPE_FIXED; 4276141cc406Sopenharmony_ci opt->unit = SANE_UNIT_MM; 4277141cc406Sopenharmony_ci opt->size = sizeof(SANE_Word); 4278141cc406Sopenharmony_ci 4279141cc406Sopenharmony_ci if (s->has_endorser_f || s->has_endorser_b){ 4280141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4281141cc406Sopenharmony_ci if(!s->u_endorser) 4282141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4283141cc406Sopenharmony_ci } 4284141cc406Sopenharmony_ci else 4285141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4286141cc406Sopenharmony_ci 4287141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_RANGE; 4288141cc406Sopenharmony_ci opt->constraint.range = &(s->endorser_y_range); 4289141cc406Sopenharmony_ci 4290141cc406Sopenharmony_ci /* values stored in 1200 dpi units */ 4291141cc406Sopenharmony_ci /* must be converted to MM for sane */ 4292141cc406Sopenharmony_ci s->endorser_y_range.min = SCANNER_UNIT_TO_FIXED_MM(0); 4293141cc406Sopenharmony_ci s->endorser_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); 4294141cc406Sopenharmony_ci s->endorser_y_range.quant = MM_PER_UNIT_FIX; 4295141cc406Sopenharmony_ci } 4296141cc406Sopenharmony_ci 4297141cc406Sopenharmony_ci if(option==OPT_ENDORSER_FONT){ 4298141cc406Sopenharmony_ci opt->name = "endorser-font"; 4299141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser font"); 4300141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Endorser printing font."); 4301141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 4302141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4303141cc406Sopenharmony_ci 4304141cc406Sopenharmony_ci /*only newest can do this?*/ 4305141cc406Sopenharmony_ci if ((s->has_endorser_f && s->endorser_type_f == ET_40) 4306141cc406Sopenharmony_ci || (s->has_endorser_b && s->endorser_type_b == ET_40)){ 4307141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4308141cc406Sopenharmony_ci if(!s->u_endorser) 4309141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4310141cc406Sopenharmony_ci } 4311141cc406Sopenharmony_ci else 4312141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4313141cc406Sopenharmony_ci 4314141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 4315141cc406Sopenharmony_ci opt->constraint.string_list = s->endorser_font_list; 4316141cc406Sopenharmony_ci 4317141cc406Sopenharmony_ci s->endorser_font_list[0] = STRING_HORIZONTAL; 4318141cc406Sopenharmony_ci s->endorser_font_list[1] = STRING_HORIZONTALBOLD; 4319141cc406Sopenharmony_ci s->endorser_font_list[2] = STRING_HORIZONTALNARROW; 4320141cc406Sopenharmony_ci s->endorser_font_list[3] = STRING_VERTICAL; 4321141cc406Sopenharmony_ci s->endorser_font_list[4] = STRING_VERTICALBOLD; 4322141cc406Sopenharmony_ci s->endorser_font_list[5] = NULL; 4323141cc406Sopenharmony_ci 4324141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 4325141cc406Sopenharmony_ci } 4326141cc406Sopenharmony_ci 4327141cc406Sopenharmony_ci if(option==OPT_ENDORSER_DIR){ 4328141cc406Sopenharmony_ci opt->name = "endorser-dir"; 4329141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser direction"); 4330141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Endorser printing direction."); 4331141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 4332141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4333141cc406Sopenharmony_ci 4334141cc406Sopenharmony_ci if (s->has_endorser_f || s->has_endorser_b){ 4335141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4336141cc406Sopenharmony_ci if(!s->u_endorser) 4337141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4338141cc406Sopenharmony_ci } 4339141cc406Sopenharmony_ci else 4340141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4341141cc406Sopenharmony_ci 4342141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 4343141cc406Sopenharmony_ci opt->constraint.string_list = s->endorser_dir_list; 4344141cc406Sopenharmony_ci 4345141cc406Sopenharmony_ci s->endorser_dir_list[0] = STRING_TOPTOBOTTOM; 4346141cc406Sopenharmony_ci s->endorser_dir_list[1] = STRING_BOTTOMTOTOP; 4347141cc406Sopenharmony_ci s->endorser_dir_list[2] = NULL; 4348141cc406Sopenharmony_ci 4349141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 4350141cc406Sopenharmony_ci } 4351141cc406Sopenharmony_ci 4352141cc406Sopenharmony_ci if(option==OPT_ENDORSER_SIDE){ 4353141cc406Sopenharmony_ci opt->name = "endorser-side"; 4354141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser side"); 4355141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Endorser printing side, requires hardware support to change"); 4356141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 4357141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4358141cc406Sopenharmony_ci 4359141cc406Sopenharmony_ci /* only show if both endorsers are installed */ 4360141cc406Sopenharmony_ci if (s->has_endorser_f && s->has_endorser_b){ 4361141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4362141cc406Sopenharmony_ci if(!s->u_endorser) 4363141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4364141cc406Sopenharmony_ci } 4365141cc406Sopenharmony_ci else 4366141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4367141cc406Sopenharmony_ci 4368141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; 4369141cc406Sopenharmony_ci opt->constraint.string_list = s->endorser_side_list; 4370141cc406Sopenharmony_ci 4371141cc406Sopenharmony_ci s->endorser_side_list[0] = STRING_FRONT; 4372141cc406Sopenharmony_ci s->endorser_side_list[1] = STRING_BACK; 4373141cc406Sopenharmony_ci s->endorser_side_list[2] = NULL; 4374141cc406Sopenharmony_ci 4375141cc406Sopenharmony_ci opt->size = maxStringSize (opt->constraint.string_list); 4376141cc406Sopenharmony_ci } 4377141cc406Sopenharmony_ci 4378141cc406Sopenharmony_ci if(option==OPT_ENDORSER_STRING){ 4379141cc406Sopenharmony_ci opt->name = "endorser-string"; 4380141cc406Sopenharmony_ci opt->title = SANE_I18N ("Endorser string"); 4381141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Endorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value."); 4382141cc406Sopenharmony_ci opt->type = SANE_TYPE_STRING; 4383141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4384141cc406Sopenharmony_ci opt->size = s->endorser_string_len + 1; 4385141cc406Sopenharmony_ci 4386141cc406Sopenharmony_ci if (s->has_endorser_f || s->has_endorser_b){ 4387141cc406Sopenharmony_ci opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 4388141cc406Sopenharmony_ci if(!s->u_endorser) 4389141cc406Sopenharmony_ci opt->cap |= SANE_CAP_INACTIVE; 4390141cc406Sopenharmony_ci } 4391141cc406Sopenharmony_ci else 4392141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4393141cc406Sopenharmony_ci 4394141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 4395141cc406Sopenharmony_ci } 4396141cc406Sopenharmony_ci 4397141cc406Sopenharmony_ci /* "Sensor" group ------------------------------------------------------ */ 4398141cc406Sopenharmony_ci if(option==OPT_SENSOR_GROUP){ 4399141cc406Sopenharmony_ci opt->name = SANE_NAME_SENSORS; 4400141cc406Sopenharmony_ci opt->title = SANE_TITLE_SENSORS; 4401141cc406Sopenharmony_ci opt->desc = SANE_DESC_SENSORS; 4402141cc406Sopenharmony_ci opt->type = SANE_TYPE_GROUP; 4403141cc406Sopenharmony_ci opt->constraint_type = SANE_CONSTRAINT_NONE; 4404141cc406Sopenharmony_ci } 4405141cc406Sopenharmony_ci 4406141cc406Sopenharmony_ci if(option==OPT_TOP){ 4407141cc406Sopenharmony_ci opt->name = "top-edge"; 4408141cc406Sopenharmony_ci opt->title = SANE_I18N ("Top edge"); 4409141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Paper is pulled partly into ADF"); 4410141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4411141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4412141cc406Sopenharmony_ci if (s->has_cmd_hw_status || s->ghs_in_rs) 4413141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4414141cc406Sopenharmony_ci else 4415141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4416141cc406Sopenharmony_ci } 4417141cc406Sopenharmony_ci 4418141cc406Sopenharmony_ci if(option==OPT_A3){ 4419141cc406Sopenharmony_ci opt->name = "a3-paper"; 4420141cc406Sopenharmony_ci opt->title = SANE_I18N ("A3 paper"); 4421141cc406Sopenharmony_ci opt->desc = SANE_I18N ("A3 paper detected"); 4422141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4423141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4424141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4425141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4426141cc406Sopenharmony_ci else 4427141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4428141cc406Sopenharmony_ci } 4429141cc406Sopenharmony_ci 4430141cc406Sopenharmony_ci if(option==OPT_B4){ 4431141cc406Sopenharmony_ci opt->name = "b4-paper"; 4432141cc406Sopenharmony_ci opt->title = SANE_I18N ("B4 paper"); 4433141cc406Sopenharmony_ci opt->desc = SANE_I18N ("B4 paper detected"); 4434141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4435141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4436141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4437141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4438141cc406Sopenharmony_ci else 4439141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4440141cc406Sopenharmony_ci } 4441141cc406Sopenharmony_ci 4442141cc406Sopenharmony_ci if(option==OPT_A4){ 4443141cc406Sopenharmony_ci opt->name = "a4-paper"; 4444141cc406Sopenharmony_ci opt->title = SANE_I18N ("A4 paper"); 4445141cc406Sopenharmony_ci opt->desc = SANE_I18N ("A4 paper detected"); 4446141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4447141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4448141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4449141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4450141cc406Sopenharmony_ci else 4451141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4452141cc406Sopenharmony_ci } 4453141cc406Sopenharmony_ci 4454141cc406Sopenharmony_ci if(option==OPT_B5){ 4455141cc406Sopenharmony_ci opt->name = "b5-paper"; 4456141cc406Sopenharmony_ci opt->title = SANE_I18N ("B5 paper"); 4457141cc406Sopenharmony_ci opt->desc = SANE_I18N ("B5 paper detected"); 4458141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4459141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4460141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4461141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4462141cc406Sopenharmony_ci else 4463141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4464141cc406Sopenharmony_ci } 4465141cc406Sopenharmony_ci 4466141cc406Sopenharmony_ci if(option==OPT_HOPPER){ 4467141cc406Sopenharmony_ci opt->name = SANE_NAME_PAGE_LOADED; 4468141cc406Sopenharmony_ci opt->title = SANE_TITLE_PAGE_LOADED; 4469141cc406Sopenharmony_ci opt->desc = SANE_DESC_PAGE_LOADED; 4470141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4471141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4472141cc406Sopenharmony_ci if (s->has_cmd_hw_status || s->ghs_in_rs) 4473141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4474141cc406Sopenharmony_ci else 4475141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4476141cc406Sopenharmony_ci } 4477141cc406Sopenharmony_ci 4478141cc406Sopenharmony_ci if(option==OPT_OMR){ 4479141cc406Sopenharmony_ci opt->name = "omr-df"; 4480141cc406Sopenharmony_ci opt->title = SANE_I18N ("OMR or DF"); 4481141cc406Sopenharmony_ci opt->desc = SANE_I18N ("OMR or double feed detected"); 4482141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4483141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4484141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4485141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4486141cc406Sopenharmony_ci else 4487141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4488141cc406Sopenharmony_ci } 4489141cc406Sopenharmony_ci 4490141cc406Sopenharmony_ci if(option==OPT_ADF_OPEN){ 4491141cc406Sopenharmony_ci opt->name = SANE_NAME_COVER_OPEN; 4492141cc406Sopenharmony_ci opt->title = SANE_TITLE_COVER_OPEN; 4493141cc406Sopenharmony_ci opt->desc = SANE_DESC_COVER_OPEN; 4494141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4495141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4496141cc406Sopenharmony_ci if (s->has_cmd_hw_status || s->ghs_in_rs) 4497141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4498141cc406Sopenharmony_ci else 4499141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4500141cc406Sopenharmony_ci } 4501141cc406Sopenharmony_ci 4502141cc406Sopenharmony_ci if(option==OPT_CARD_LOADED){ 4503141cc406Sopenharmony_ci opt->name = "card-loaded"; 4504141cc406Sopenharmony_ci opt->title = SANE_I18N ("Card loaded"); 4505141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Card slot contains paper"); 4506141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4507141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4508141cc406Sopenharmony_ci if (s->has_cmd_hw_status && s->has_return_path) 4509141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4510141cc406Sopenharmony_ci else 4511141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4512141cc406Sopenharmony_ci } 4513141cc406Sopenharmony_ci 4514141cc406Sopenharmony_ci if(option==OPT_SLEEP){ 4515141cc406Sopenharmony_ci opt->name = "power-save"; 4516141cc406Sopenharmony_ci opt->title = SANE_I18N ("Power saving"); 4517141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Scanner in power saving mode"); 4518141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4519141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4520141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4521141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4522141cc406Sopenharmony_ci else 4523141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4524141cc406Sopenharmony_ci } 4525141cc406Sopenharmony_ci 4526141cc406Sopenharmony_ci if(option==OPT_SEND_SW){ 4527141cc406Sopenharmony_ci opt->name = SANE_NAME_EMAIL; 4528141cc406Sopenharmony_ci opt->title = SANE_TITLE_EMAIL; 4529141cc406Sopenharmony_ci opt->desc = SANE_DESC_EMAIL; 4530141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4531141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4532141cc406Sopenharmony_ci if (s->has_cmd_hw_status || s->ghs_in_rs) 4533141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4534141cc406Sopenharmony_ci else 4535141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4536141cc406Sopenharmony_ci } 4537141cc406Sopenharmony_ci 4538141cc406Sopenharmony_ci if(option==OPT_MANUAL_FEED){ 4539141cc406Sopenharmony_ci opt->name = "manual-feed"; 4540141cc406Sopenharmony_ci opt->title = SANE_I18N ("Manual feed"); 4541141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Manual feed selected"); 4542141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4543141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4544141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4545141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4546141cc406Sopenharmony_ci else 4547141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4548141cc406Sopenharmony_ci } 4549141cc406Sopenharmony_ci 4550141cc406Sopenharmony_ci if(option==OPT_SCAN_SW){ 4551141cc406Sopenharmony_ci opt->name = SANE_NAME_SCAN; 4552141cc406Sopenharmony_ci opt->title = SANE_TITLE_SCAN; 4553141cc406Sopenharmony_ci opt->desc = SANE_DESC_SCAN; 4554141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4555141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4556141cc406Sopenharmony_ci if (s->has_cmd_hw_status || s->ghs_in_rs) 4557141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4558141cc406Sopenharmony_ci else 4559141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4560141cc406Sopenharmony_ci } 4561141cc406Sopenharmony_ci 4562141cc406Sopenharmony_ci if(option==OPT_FUNCTION){ 4563141cc406Sopenharmony_ci opt->name = "function"; 4564141cc406Sopenharmony_ci opt->title = SANE_I18N ("Function"); 4565141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Function character on screen"); 4566141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4567141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4568141cc406Sopenharmony_ci if (s->has_cmd_hw_status || s->ghs_in_rs) 4569141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4570141cc406Sopenharmony_ci else 4571141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4572141cc406Sopenharmony_ci } 4573141cc406Sopenharmony_ci 4574141cc406Sopenharmony_ci if(option==OPT_INK_EMPTY){ 4575141cc406Sopenharmony_ci opt->name = "ink-low"; 4576141cc406Sopenharmony_ci opt->title = SANE_I18N ("Ink low"); 4577141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Imprinter ink running low"); 4578141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4579141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4580141cc406Sopenharmony_ci if (s->has_cmd_hw_status && (s->has_endorser_f || s->has_endorser_b)) 4581141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4582141cc406Sopenharmony_ci else 4583141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4584141cc406Sopenharmony_ci } 4585141cc406Sopenharmony_ci 4586141cc406Sopenharmony_ci if(option==OPT_DOUBLE_FEED){ 4587141cc406Sopenharmony_ci opt->name = "double-feed"; 4588141cc406Sopenharmony_ci opt->title = SANE_I18N ("Double feed"); 4589141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Double feed detected"); 4590141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4591141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4592141cc406Sopenharmony_ci if (s->has_cmd_hw_status || s->ghs_in_rs) 4593141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4594141cc406Sopenharmony_ci else 4595141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4596141cc406Sopenharmony_ci } 4597141cc406Sopenharmony_ci 4598141cc406Sopenharmony_ci if(option==OPT_ERROR_CODE){ 4599141cc406Sopenharmony_ci opt->name = "error-code"; 4600141cc406Sopenharmony_ci opt->title = SANE_I18N ("Error code"); 4601141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Hardware error code"); 4602141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4603141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4604141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4605141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4606141cc406Sopenharmony_ci else 4607141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4608141cc406Sopenharmony_ci } 4609141cc406Sopenharmony_ci 4610141cc406Sopenharmony_ci if(option==OPT_SKEW_ANGLE){ 4611141cc406Sopenharmony_ci opt->name = "skew-angle"; 4612141cc406Sopenharmony_ci opt->title = SANE_I18N ("Skew angle"); 4613141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Requires black background for scanning"); 4614141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4615141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4616141cc406Sopenharmony_ci if (s->has_cmd_hw_status) 4617141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4618141cc406Sopenharmony_ci else 4619141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4620141cc406Sopenharmony_ci } 4621141cc406Sopenharmony_ci 4622141cc406Sopenharmony_ci if(option==OPT_INK_REMAIN){ 4623141cc406Sopenharmony_ci opt->name = "ink-remain"; 4624141cc406Sopenharmony_ci opt->title = SANE_I18N ("Ink remaining"); 4625141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Imprinter ink level"); 4626141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4627141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4628141cc406Sopenharmony_ci if (s->has_cmd_hw_status && (s->has_endorser_f || s->has_endorser_b)) 4629141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4630141cc406Sopenharmony_ci else 4631141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4632141cc406Sopenharmony_ci } 4633141cc406Sopenharmony_ci 4634141cc406Sopenharmony_ci if(option==OPT_DENSITY_SW){ 4635141cc406Sopenharmony_ci opt->name = "density"; 4636141cc406Sopenharmony_ci opt->title = SANE_I18N ("Density"); 4637141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Density dial"); 4638141cc406Sopenharmony_ci opt->type = SANE_TYPE_INT; 4639141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4640141cc406Sopenharmony_ci if (s->ghs_in_rs) 4641141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4642141cc406Sopenharmony_ci else 4643141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4644141cc406Sopenharmony_ci } 4645141cc406Sopenharmony_ci 4646141cc406Sopenharmony_ci if(option==OPT_DUPLEX_SW){ 4647141cc406Sopenharmony_ci opt->name = "duplex"; 4648141cc406Sopenharmony_ci opt->title = SANE_I18N ("Duplex switch"); 4649141cc406Sopenharmony_ci opt->desc = SANE_I18N ("Duplex switch"); 4650141cc406Sopenharmony_ci opt->type = SANE_TYPE_BOOL; 4651141cc406Sopenharmony_ci opt->unit = SANE_UNIT_NONE; 4652141cc406Sopenharmony_ci if (s->ghs_in_rs) 4653141cc406Sopenharmony_ci opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; 4654141cc406Sopenharmony_ci else 4655141cc406Sopenharmony_ci opt->cap = SANE_CAP_INACTIVE; 4656141cc406Sopenharmony_ci } 4657141cc406Sopenharmony_ci 4658141cc406Sopenharmony_ci return opt; 4659141cc406Sopenharmony_ci} 4660141cc406Sopenharmony_ci 4661141cc406Sopenharmony_ci/** 4662141cc406Sopenharmony_ci * Gets or sets an option value. 4663141cc406Sopenharmony_ci * 4664141cc406Sopenharmony_ci * From the SANE spec: 4665141cc406Sopenharmony_ci * This function is used to set or inquire the current value of option 4666141cc406Sopenharmony_ci * number n of the device represented by handle h. The manner in which 4667141cc406Sopenharmony_ci * the option is controlled is specified by parameter action. The 4668141cc406Sopenharmony_ci * possible values of this parameter are described in more detail 4669141cc406Sopenharmony_ci * below. The value of the option is passed through argument val. It 4670141cc406Sopenharmony_ci * is a pointer to the memory that holds the option value. The memory 4671141cc406Sopenharmony_ci * area pointed to by v must be big enough to hold the entire option 4672141cc406Sopenharmony_ci * value (determined by member size in the corresponding option 4673141cc406Sopenharmony_ci * descriptor). 4674141cc406Sopenharmony_ci * 4675141cc406Sopenharmony_ci * The only exception to this rule is that when setting the value of a 4676141cc406Sopenharmony_ci * string option, the string pointed to by argument v may be shorter 4677141cc406Sopenharmony_ci * since the backend will stop reading the option value upon 4678141cc406Sopenharmony_ci * encountering the first NUL terminator in the string. If argument i 4679141cc406Sopenharmony_ci * is not NULL, the value of *i will be set to provide details on how 4680141cc406Sopenharmony_ci * well the request has been met. 4681141cc406Sopenharmony_ci */ 4682141cc406Sopenharmony_ciSANE_Status 4683141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 4684141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 4685141cc406Sopenharmony_ci{ 4686141cc406Sopenharmony_ci struct fujitsu *s = (struct fujitsu *) handle; 4687141cc406Sopenharmony_ci SANE_Int dummy = 0; 4688141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 4689141cc406Sopenharmony_ci 4690141cc406Sopenharmony_ci /* Make sure that all those statements involving *info cannot break (better 4691141cc406Sopenharmony_ci * than having to do "if (info) ..." everywhere!) 4692141cc406Sopenharmony_ci */ 4693141cc406Sopenharmony_ci if (info == 0) 4694141cc406Sopenharmony_ci info = &dummy; 4695141cc406Sopenharmony_ci 4696141cc406Sopenharmony_ci /*blast info in case frontend forgot*/ 4697141cc406Sopenharmony_ci *info = 0; 4698141cc406Sopenharmony_ci 4699141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) { 4700141cc406Sopenharmony_ci DBG (5, "sane_control_option: %d too big\n", option); 4701141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4702141cc406Sopenharmony_ci } 4703141cc406Sopenharmony_ci 4704141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) { 4705141cc406Sopenharmony_ci DBG (5, "sane_control_option: %d inactive\n", option); 4706141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4707141cc406Sopenharmony_ci } 4708141cc406Sopenharmony_ci 4709141cc406Sopenharmony_ci /* 4710141cc406Sopenharmony_ci * SANE_ACTION_GET_VALUE: We have to find out the current setting and 4711141cc406Sopenharmony_ci * return it in a human-readable form (often, text). 4712141cc406Sopenharmony_ci */ 4713141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) { 4714141cc406Sopenharmony_ci SANE_Word * val_p = (SANE_Word *) val; 4715141cc406Sopenharmony_ci 4716141cc406Sopenharmony_ci DBG (20, "sane_control_option: get value for '%s' (%d)\n", s->opt[option].name,option); 4717141cc406Sopenharmony_ci 4718141cc406Sopenharmony_ci switch (option) { 4719141cc406Sopenharmony_ci 4720141cc406Sopenharmony_ci case OPT_NUM_OPTS: 4721141cc406Sopenharmony_ci *val_p = NUM_OPTIONS; 4722141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4723141cc406Sopenharmony_ci 4724141cc406Sopenharmony_ci case OPT_SOURCE: 4725141cc406Sopenharmony_ci if(s->source == SOURCE_FLATBED){ 4726141cc406Sopenharmony_ci strcpy (val, STRING_FLATBED); 4727141cc406Sopenharmony_ci } 4728141cc406Sopenharmony_ci else if(s->source == SOURCE_ADF_FRONT){ 4729141cc406Sopenharmony_ci strcpy (val, STRING_ADFFRONT); 4730141cc406Sopenharmony_ci } 4731141cc406Sopenharmony_ci else if(s->source == SOURCE_ADF_BACK){ 4732141cc406Sopenharmony_ci strcpy (val, STRING_ADFBACK); 4733141cc406Sopenharmony_ci } 4734141cc406Sopenharmony_ci else if(s->source == SOURCE_ADF_DUPLEX){ 4735141cc406Sopenharmony_ci strcpy (val, STRING_ADFDUPLEX); 4736141cc406Sopenharmony_ci } 4737141cc406Sopenharmony_ci else if(s->source == SOURCE_CARD_FRONT){ 4738141cc406Sopenharmony_ci strcpy (val, STRING_CARDFRONT); 4739141cc406Sopenharmony_ci } 4740141cc406Sopenharmony_ci else if(s->source == SOURCE_CARD_BACK){ 4741141cc406Sopenharmony_ci strcpy (val, STRING_CARDBACK); 4742141cc406Sopenharmony_ci } 4743141cc406Sopenharmony_ci else if(s->source == SOURCE_CARD_DUPLEX){ 4744141cc406Sopenharmony_ci strcpy (val, STRING_CARDDUPLEX); 4745141cc406Sopenharmony_ci } 4746141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4747141cc406Sopenharmony_ci 4748141cc406Sopenharmony_ci case OPT_MODE: 4749141cc406Sopenharmony_ci if(s->u_mode == MODE_LINEART){ 4750141cc406Sopenharmony_ci strcpy (val, STRING_LINEART); 4751141cc406Sopenharmony_ci } 4752141cc406Sopenharmony_ci else if(s->u_mode == MODE_HALFTONE){ 4753141cc406Sopenharmony_ci strcpy (val, STRING_HALFTONE); 4754141cc406Sopenharmony_ci } 4755141cc406Sopenharmony_ci else if(s->u_mode == MODE_GRAYSCALE){ 4756141cc406Sopenharmony_ci strcpy (val, STRING_GRAYSCALE); 4757141cc406Sopenharmony_ci } 4758141cc406Sopenharmony_ci else if(s->u_mode == MODE_COLOR){ 4759141cc406Sopenharmony_ci strcpy (val, STRING_COLOR); 4760141cc406Sopenharmony_ci } 4761141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4762141cc406Sopenharmony_ci 4763141cc406Sopenharmony_ci case OPT_RES: 4764141cc406Sopenharmony_ci *val_p = s->resolution_x; 4765141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4766141cc406Sopenharmony_ci 4767141cc406Sopenharmony_ci case OPT_TL_X: 4768141cc406Sopenharmony_ci *val_p = SCANNER_UNIT_TO_FIXED_MM(s->tl_x); 4769141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4770141cc406Sopenharmony_ci 4771141cc406Sopenharmony_ci case OPT_TL_Y: 4772141cc406Sopenharmony_ci *val_p = SCANNER_UNIT_TO_FIXED_MM(s->tl_y); 4773141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4774141cc406Sopenharmony_ci 4775141cc406Sopenharmony_ci case OPT_BR_X: 4776141cc406Sopenharmony_ci *val_p = SCANNER_UNIT_TO_FIXED_MM(s->br_x); 4777141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4778141cc406Sopenharmony_ci 4779141cc406Sopenharmony_ci case OPT_BR_Y: 4780141cc406Sopenharmony_ci *val_p = SCANNER_UNIT_TO_FIXED_MM(s->br_y); 4781141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4782141cc406Sopenharmony_ci 4783141cc406Sopenharmony_ci case OPT_PAGE_WIDTH: 4784141cc406Sopenharmony_ci *val_p = SCANNER_UNIT_TO_FIXED_MM(s->page_width); 4785141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4786141cc406Sopenharmony_ci 4787141cc406Sopenharmony_ci case OPT_PAGE_HEIGHT: 4788141cc406Sopenharmony_ci *val_p = SCANNER_UNIT_TO_FIXED_MM(s->page_height); 4789141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4790141cc406Sopenharmony_ci 4791141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 4792141cc406Sopenharmony_ci *val_p = s->brightness; 4793141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4794141cc406Sopenharmony_ci 4795141cc406Sopenharmony_ci case OPT_CONTRAST: 4796141cc406Sopenharmony_ci *val_p = s->contrast; 4797141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4798141cc406Sopenharmony_ci 4799141cc406Sopenharmony_ci case OPT_GAMMA: 4800141cc406Sopenharmony_ci *val_p = SANE_FIX(s->gamma); 4801141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4802141cc406Sopenharmony_ci 4803141cc406Sopenharmony_ci case OPT_THRESHOLD: 4804141cc406Sopenharmony_ci *val_p = s->threshold; 4805141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4806141cc406Sopenharmony_ci 4807141cc406Sopenharmony_ci /* IPC */ 4808141cc406Sopenharmony_ci case OPT_RIF: 4809141cc406Sopenharmony_ci *val_p = s->rif; 4810141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4811141cc406Sopenharmony_ci 4812141cc406Sopenharmony_ci case OPT_HT_TYPE: 4813141cc406Sopenharmony_ci switch (s->ht_type) { 4814141cc406Sopenharmony_ci case WD_ht_type_DEFAULT: 4815141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 4816141cc406Sopenharmony_ci break; 4817141cc406Sopenharmony_ci case WD_ht_type_DITHER: 4818141cc406Sopenharmony_ci strcpy (val, STRING_DITHER); 4819141cc406Sopenharmony_ci break; 4820141cc406Sopenharmony_ci case WD_ht_type_DIFFUSION: 4821141cc406Sopenharmony_ci strcpy (val, STRING_DIFFUSION); 4822141cc406Sopenharmony_ci break; 4823141cc406Sopenharmony_ci } 4824141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4825141cc406Sopenharmony_ci 4826141cc406Sopenharmony_ci case OPT_HT_PATTERN: 4827141cc406Sopenharmony_ci *val_p = s->ht_pattern; 4828141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4829141cc406Sopenharmony_ci 4830141cc406Sopenharmony_ci case OPT_OUTLINE: 4831141cc406Sopenharmony_ci *val_p = s->outline; 4832141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4833141cc406Sopenharmony_ci 4834141cc406Sopenharmony_ci case OPT_EMPHASIS: 4835141cc406Sopenharmony_ci *val_p = s->emphasis; 4836141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4837141cc406Sopenharmony_ci 4838141cc406Sopenharmony_ci case OPT_SEPARATION: 4839141cc406Sopenharmony_ci *val_p = s->separation; 4840141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4841141cc406Sopenharmony_ci 4842141cc406Sopenharmony_ci case OPT_MIRRORING: 4843141cc406Sopenharmony_ci *val_p = s->mirroring; 4844141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4845141cc406Sopenharmony_ci 4846141cc406Sopenharmony_ci case OPT_WL_FOLLOW: 4847141cc406Sopenharmony_ci switch (s->wl_follow) { 4848141cc406Sopenharmony_ci case WD_wl_follow_DEFAULT: 4849141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 4850141cc406Sopenharmony_ci break; 4851141cc406Sopenharmony_ci case WD_wl_follow_ON: 4852141cc406Sopenharmony_ci strcpy (val, STRING_ON); 4853141cc406Sopenharmony_ci break; 4854141cc406Sopenharmony_ci case WD_wl_follow_OFF: 4855141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 4856141cc406Sopenharmony_ci break; 4857141cc406Sopenharmony_ci } 4858141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4859141cc406Sopenharmony_ci 4860141cc406Sopenharmony_ci /* DTC params*/ 4861141cc406Sopenharmony_ci case OPT_BP_FILTER: 4862141cc406Sopenharmony_ci *val_p = s->bp_filter; 4863141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4864141cc406Sopenharmony_ci 4865141cc406Sopenharmony_ci case OPT_SMOOTHING: 4866141cc406Sopenharmony_ci *val_p = s->smoothing; 4867141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4868141cc406Sopenharmony_ci 4869141cc406Sopenharmony_ci case OPT_GAMMA_CURVE: 4870141cc406Sopenharmony_ci *val_p = s->gamma_curve; 4871141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4872141cc406Sopenharmony_ci 4873141cc406Sopenharmony_ci case OPT_THRESHOLD_CURVE: 4874141cc406Sopenharmony_ci *val_p = s->threshold_curve; 4875141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4876141cc406Sopenharmony_ci 4877141cc406Sopenharmony_ci case OPT_THRESHOLD_WHITE: 4878141cc406Sopenharmony_ci *val_p = s->threshold_white; 4879141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4880141cc406Sopenharmony_ci 4881141cc406Sopenharmony_ci case OPT_NOISE_REMOVAL: 4882141cc406Sopenharmony_ci *val_p = s->noise_removal; 4883141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4884141cc406Sopenharmony_ci 4885141cc406Sopenharmony_ci case OPT_MATRIX_5: 4886141cc406Sopenharmony_ci *val_p = s->matrix_5; 4887141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4888141cc406Sopenharmony_ci 4889141cc406Sopenharmony_ci case OPT_MATRIX_4: 4890141cc406Sopenharmony_ci *val_p = s->matrix_4; 4891141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4892141cc406Sopenharmony_ci 4893141cc406Sopenharmony_ci case OPT_MATRIX_3: 4894141cc406Sopenharmony_ci *val_p = s->matrix_3; 4895141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4896141cc406Sopenharmony_ci 4897141cc406Sopenharmony_ci case OPT_MATRIX_2: 4898141cc406Sopenharmony_ci *val_p = s->matrix_2; 4899141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4900141cc406Sopenharmony_ci 4901141cc406Sopenharmony_ci /* SDTC params*/ 4902141cc406Sopenharmony_ci case OPT_VARIANCE: 4903141cc406Sopenharmony_ci *val_p = s->variance; 4904141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4905141cc406Sopenharmony_ci 4906141cc406Sopenharmony_ci /* Advanced Group */ 4907141cc406Sopenharmony_ci case OPT_AWD: 4908141cc406Sopenharmony_ci *val_p = s->awd; 4909141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4910141cc406Sopenharmony_ci 4911141cc406Sopenharmony_ci case OPT_ALD: 4912141cc406Sopenharmony_ci *val_p = s->ald; 4913141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4914141cc406Sopenharmony_ci 4915141cc406Sopenharmony_ci case OPT_COMPRESS: 4916141cc406Sopenharmony_ci if(s->compress == COMP_JPEG){ 4917141cc406Sopenharmony_ci strcpy (val, STRING_JPEG); 4918141cc406Sopenharmony_ci } 4919141cc406Sopenharmony_ci else{ 4920141cc406Sopenharmony_ci strcpy (val, STRING_NONE); 4921141cc406Sopenharmony_ci } 4922141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4923141cc406Sopenharmony_ci 4924141cc406Sopenharmony_ci case OPT_COMPRESS_ARG: 4925141cc406Sopenharmony_ci *val_p = s->compress_arg; 4926141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4927141cc406Sopenharmony_ci 4928141cc406Sopenharmony_ci case OPT_DF_ACTION: 4929141cc406Sopenharmony_ci switch (s->df_action) { 4930141cc406Sopenharmony_ci case DF_DEFAULT: 4931141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 4932141cc406Sopenharmony_ci break; 4933141cc406Sopenharmony_ci case DF_CONTINUE: 4934141cc406Sopenharmony_ci strcpy (val, STRING_CONTINUE); 4935141cc406Sopenharmony_ci break; 4936141cc406Sopenharmony_ci case DF_STOP: 4937141cc406Sopenharmony_ci strcpy (val, STRING_STOP); 4938141cc406Sopenharmony_ci break; 4939141cc406Sopenharmony_ci } 4940141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4941141cc406Sopenharmony_ci 4942141cc406Sopenharmony_ci case OPT_DF_SKEW: 4943141cc406Sopenharmony_ci *val_p = s->df_skew; 4944141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4945141cc406Sopenharmony_ci 4946141cc406Sopenharmony_ci case OPT_DF_THICKNESS: 4947141cc406Sopenharmony_ci *val_p = s->df_thickness; 4948141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4949141cc406Sopenharmony_ci 4950141cc406Sopenharmony_ci case OPT_DF_LENGTH: 4951141cc406Sopenharmony_ci *val_p = s->df_length; 4952141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4953141cc406Sopenharmony_ci 4954141cc406Sopenharmony_ci case OPT_DF_DIFF: 4955141cc406Sopenharmony_ci switch (s->df_diff) { 4956141cc406Sopenharmony_ci case MSEL_df_diff_DEFAULT: 4957141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 4958141cc406Sopenharmony_ci break; 4959141cc406Sopenharmony_ci case MSEL_df_diff_10MM: 4960141cc406Sopenharmony_ci strcpy (val, STRING_10MM); 4961141cc406Sopenharmony_ci break; 4962141cc406Sopenharmony_ci case MSEL_df_diff_15MM: 4963141cc406Sopenharmony_ci strcpy (val, STRING_15MM); 4964141cc406Sopenharmony_ci break; 4965141cc406Sopenharmony_ci case MSEL_df_diff_20MM: 4966141cc406Sopenharmony_ci strcpy (val, STRING_20MM); 4967141cc406Sopenharmony_ci break; 4968141cc406Sopenharmony_ci } 4969141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4970141cc406Sopenharmony_ci 4971141cc406Sopenharmony_ci case OPT_DF_RECOVERY: 4972141cc406Sopenharmony_ci switch (s->df_recovery) { 4973141cc406Sopenharmony_ci case MSEL_DEFAULT: 4974141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 4975141cc406Sopenharmony_ci break; 4976141cc406Sopenharmony_ci case MSEL_ON: 4977141cc406Sopenharmony_ci strcpy (val, STRING_ON); 4978141cc406Sopenharmony_ci break; 4979141cc406Sopenharmony_ci case MSEL_OFF: 4980141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 4981141cc406Sopenharmony_ci break; 4982141cc406Sopenharmony_ci } 4983141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4984141cc406Sopenharmony_ci 4985141cc406Sopenharmony_ci case OPT_PAPER_PROTECT: 4986141cc406Sopenharmony_ci switch (s->paper_protect) { 4987141cc406Sopenharmony_ci case MSEL_DEFAULT: 4988141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 4989141cc406Sopenharmony_ci break; 4990141cc406Sopenharmony_ci case MSEL_ON: 4991141cc406Sopenharmony_ci strcpy (val, STRING_ON); 4992141cc406Sopenharmony_ci break; 4993141cc406Sopenharmony_ci case MSEL_OFF: 4994141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 4995141cc406Sopenharmony_ci break; 4996141cc406Sopenharmony_ci } 4997141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4998141cc406Sopenharmony_ci 4999141cc406Sopenharmony_ci case OPT_ADV_PAPER_PROT: 5000141cc406Sopenharmony_ci switch (s->adv_paper_prot) { 5001141cc406Sopenharmony_ci case MSEL_DEFAULT: 5002141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 5003141cc406Sopenharmony_ci break; 5004141cc406Sopenharmony_ci case MSEL_ON: 5005141cc406Sopenharmony_ci strcpy (val, STRING_ON); 5006141cc406Sopenharmony_ci break; 5007141cc406Sopenharmony_ci case MSEL_OFF: 5008141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 5009141cc406Sopenharmony_ci break; 5010141cc406Sopenharmony_ci } 5011141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5012141cc406Sopenharmony_ci 5013141cc406Sopenharmony_ci case OPT_STAPLE_DETECT: 5014141cc406Sopenharmony_ci switch (s->staple_detect) { 5015141cc406Sopenharmony_ci case MSEL_DEFAULT: 5016141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 5017141cc406Sopenharmony_ci break; 5018141cc406Sopenharmony_ci case MSEL_ON: 5019141cc406Sopenharmony_ci strcpy (val, STRING_ON); 5020141cc406Sopenharmony_ci break; 5021141cc406Sopenharmony_ci case MSEL_OFF: 5022141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 5023141cc406Sopenharmony_ci break; 5024141cc406Sopenharmony_ci } 5025141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5026141cc406Sopenharmony_ci 5027141cc406Sopenharmony_ci case OPT_BG_COLOR: 5028141cc406Sopenharmony_ci switch (s->bg_color) { 5029141cc406Sopenharmony_ci case COLOR_DEFAULT: 5030141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 5031141cc406Sopenharmony_ci break; 5032141cc406Sopenharmony_ci case COLOR_WHITE: 5033141cc406Sopenharmony_ci strcpy (val, STRING_WHITE); 5034141cc406Sopenharmony_ci break; 5035141cc406Sopenharmony_ci case COLOR_BLACK: 5036141cc406Sopenharmony_ci strcpy (val, STRING_BLACK); 5037141cc406Sopenharmony_ci break; 5038141cc406Sopenharmony_ci } 5039141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5040141cc406Sopenharmony_ci 5041141cc406Sopenharmony_ci case OPT_DROPOUT_COLOR: 5042141cc406Sopenharmony_ci switch (s->dropout_color) { 5043141cc406Sopenharmony_ci case COLOR_DEFAULT: 5044141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 5045141cc406Sopenharmony_ci break; 5046141cc406Sopenharmony_ci case COLOR_RED: 5047141cc406Sopenharmony_ci strcpy (val, STRING_RED); 5048141cc406Sopenharmony_ci break; 5049141cc406Sopenharmony_ci case COLOR_GREEN: 5050141cc406Sopenharmony_ci strcpy (val, STRING_GREEN); 5051141cc406Sopenharmony_ci break; 5052141cc406Sopenharmony_ci case COLOR_BLUE: 5053141cc406Sopenharmony_ci strcpy (val, STRING_BLUE); 5054141cc406Sopenharmony_ci break; 5055141cc406Sopenharmony_ci } 5056141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5057141cc406Sopenharmony_ci 5058141cc406Sopenharmony_ci case OPT_BUFF_MODE: 5059141cc406Sopenharmony_ci switch (s->buff_mode) { 5060141cc406Sopenharmony_ci case MSEL_DEFAULT: 5061141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 5062141cc406Sopenharmony_ci break; 5063141cc406Sopenharmony_ci case MSEL_ON: 5064141cc406Sopenharmony_ci strcpy (val, STRING_ON); 5065141cc406Sopenharmony_ci break; 5066141cc406Sopenharmony_ci case MSEL_OFF: 5067141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 5068141cc406Sopenharmony_ci break; 5069141cc406Sopenharmony_ci } 5070141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5071141cc406Sopenharmony_ci 5072141cc406Sopenharmony_ci case OPT_PREPICK: 5073141cc406Sopenharmony_ci switch (s->prepick) { 5074141cc406Sopenharmony_ci case MSEL_DEFAULT: 5075141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 5076141cc406Sopenharmony_ci break; 5077141cc406Sopenharmony_ci case MSEL_ON: 5078141cc406Sopenharmony_ci strcpy (val, STRING_ON); 5079141cc406Sopenharmony_ci break; 5080141cc406Sopenharmony_ci case MSEL_OFF: 5081141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 5082141cc406Sopenharmony_ci break; 5083141cc406Sopenharmony_ci } 5084141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5085141cc406Sopenharmony_ci 5086141cc406Sopenharmony_ci case OPT_OVERSCAN: 5087141cc406Sopenharmony_ci switch (s->overscan) { 5088141cc406Sopenharmony_ci case MSEL_DEFAULT: 5089141cc406Sopenharmony_ci strcpy (val, STRING_DEFAULT); 5090141cc406Sopenharmony_ci break; 5091141cc406Sopenharmony_ci case MSEL_ON: 5092141cc406Sopenharmony_ci strcpy (val, STRING_ON); 5093141cc406Sopenharmony_ci break; 5094141cc406Sopenharmony_ci case MSEL_OFF: 5095141cc406Sopenharmony_ci strcpy (val, STRING_OFF); 5096141cc406Sopenharmony_ci break; 5097141cc406Sopenharmony_ci } 5098141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5099141cc406Sopenharmony_ci 5100141cc406Sopenharmony_ci case OPT_SLEEP_TIME: 5101141cc406Sopenharmony_ci *val_p = s->sleep_time; 5102141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5103141cc406Sopenharmony_ci 5104141cc406Sopenharmony_ci case OPT_OFF_TIME: 5105141cc406Sopenharmony_ci *val_p = s->off_time; 5106141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5107141cc406Sopenharmony_ci 5108141cc406Sopenharmony_ci case OPT_DUPLEX_OFFSET: 5109141cc406Sopenharmony_ci *val_p = s->duplex_offset; 5110141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5111141cc406Sopenharmony_ci 5112141cc406Sopenharmony_ci case OPT_GREEN_OFFSET: 5113141cc406Sopenharmony_ci *val_p = s->green_offset; 5114141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5115141cc406Sopenharmony_ci 5116141cc406Sopenharmony_ci case OPT_BLUE_OFFSET: 5117141cc406Sopenharmony_ci *val_p = s->blue_offset; 5118141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5119141cc406Sopenharmony_ci 5120141cc406Sopenharmony_ci case OPT_LOW_MEM: 5121141cc406Sopenharmony_ci *val_p = s->low_mem; 5122141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5123141cc406Sopenharmony_ci 5124141cc406Sopenharmony_ci case OPT_SIDE: 5125141cc406Sopenharmony_ci *val_p = s->side; 5126141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5127141cc406Sopenharmony_ci 5128141cc406Sopenharmony_ci case OPT_HWDESKEWCROP: 5129141cc406Sopenharmony_ci *val_p = s->hwdeskewcrop; 5130141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5131141cc406Sopenharmony_ci 5132141cc406Sopenharmony_ci case OPT_SWDESKEW: 5133141cc406Sopenharmony_ci *val_p = s->swdeskew; 5134141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5135141cc406Sopenharmony_ci 5136141cc406Sopenharmony_ci case OPT_SWDESPECK: 5137141cc406Sopenharmony_ci *val_p = s->swdespeck; 5138141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5139141cc406Sopenharmony_ci 5140141cc406Sopenharmony_ci case OPT_SWCROP: 5141141cc406Sopenharmony_ci *val_p = s->swcrop; 5142141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5143141cc406Sopenharmony_ci 5144141cc406Sopenharmony_ci case OPT_SWSKIP: 5145141cc406Sopenharmony_ci *val_p = SANE_FIX(s->swskip); 5146141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5147141cc406Sopenharmony_ci 5148141cc406Sopenharmony_ci case OPT_HALT_ON_CANCEL: 5149141cc406Sopenharmony_ci *val_p = s->halt_on_cancel; 5150141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5151141cc406Sopenharmony_ci 5152141cc406Sopenharmony_ci /* Endorser Group */ 5153141cc406Sopenharmony_ci case OPT_ENDORSER: 5154141cc406Sopenharmony_ci *val_p = s->u_endorser; 5155141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5156141cc406Sopenharmony_ci 5157141cc406Sopenharmony_ci case OPT_ENDORSER_BITS: 5158141cc406Sopenharmony_ci *val_p = s->u_endorser_bits; 5159141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5160141cc406Sopenharmony_ci 5161141cc406Sopenharmony_ci case OPT_ENDORSER_VAL: 5162141cc406Sopenharmony_ci *val_p = s->u_endorser_val; 5163141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5164141cc406Sopenharmony_ci 5165141cc406Sopenharmony_ci case OPT_ENDORSER_STEP: 5166141cc406Sopenharmony_ci *val_p = s->u_endorser_step; 5167141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5168141cc406Sopenharmony_ci 5169141cc406Sopenharmony_ci case OPT_ENDORSER_Y: 5170141cc406Sopenharmony_ci *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_endorser_y); 5171141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5172141cc406Sopenharmony_ci 5173141cc406Sopenharmony_ci case OPT_ENDORSER_FONT: 5174141cc406Sopenharmony_ci switch (s->u_endorser_font) { 5175141cc406Sopenharmony_ci case FONT_H: 5176141cc406Sopenharmony_ci strcpy (val, STRING_HORIZONTAL); 5177141cc406Sopenharmony_ci break; 5178141cc406Sopenharmony_ci case FONT_HB: 5179141cc406Sopenharmony_ci strcpy (val, STRING_HORIZONTALBOLD); 5180141cc406Sopenharmony_ci break; 5181141cc406Sopenharmony_ci case FONT_HN: 5182141cc406Sopenharmony_ci strcpy (val, STRING_HORIZONTALNARROW); 5183141cc406Sopenharmony_ci break; 5184141cc406Sopenharmony_ci case FONT_V: 5185141cc406Sopenharmony_ci strcpy (val, STRING_VERTICAL); 5186141cc406Sopenharmony_ci break; 5187141cc406Sopenharmony_ci case FONT_VB: 5188141cc406Sopenharmony_ci strcpy (val, STRING_VERTICALBOLD); 5189141cc406Sopenharmony_ci break; 5190141cc406Sopenharmony_ci } 5191141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5192141cc406Sopenharmony_ci 5193141cc406Sopenharmony_ci case OPT_ENDORSER_DIR: 5194141cc406Sopenharmony_ci switch (s->u_endorser_dir) { 5195141cc406Sopenharmony_ci case DIR_TTB: 5196141cc406Sopenharmony_ci strcpy (val, STRING_TOPTOBOTTOM); 5197141cc406Sopenharmony_ci break; 5198141cc406Sopenharmony_ci case DIR_BTT: 5199141cc406Sopenharmony_ci strcpy (val, STRING_BOTTOMTOTOP); 5200141cc406Sopenharmony_ci break; 5201141cc406Sopenharmony_ci } 5202141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5203141cc406Sopenharmony_ci 5204141cc406Sopenharmony_ci case OPT_ENDORSER_SIDE: 5205141cc406Sopenharmony_ci switch (s->u_endorser_side) { 5206141cc406Sopenharmony_ci case ED_front: 5207141cc406Sopenharmony_ci strcpy (val, STRING_FRONT); 5208141cc406Sopenharmony_ci break; 5209141cc406Sopenharmony_ci case ED_back: 5210141cc406Sopenharmony_ci strcpy (val, STRING_BACK); 5211141cc406Sopenharmony_ci break; 5212141cc406Sopenharmony_ci } 5213141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5214141cc406Sopenharmony_ci 5215141cc406Sopenharmony_ci case OPT_ENDORSER_STRING: 5216141cc406Sopenharmony_ci strncpy( 5217141cc406Sopenharmony_ci (SANE_String)val, 5218141cc406Sopenharmony_ci (SANE_String)s->u_endorser_string, 5219141cc406Sopenharmony_ci s->endorser_string_len+1 5220141cc406Sopenharmony_ci ); 5221141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5222141cc406Sopenharmony_ci 5223141cc406Sopenharmony_ci /* Sensor Group */ 5224141cc406Sopenharmony_ci case OPT_TOP: 5225141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5226141cc406Sopenharmony_ci *val_p = s->hw_top; 5227141cc406Sopenharmony_ci return ret; 5228141cc406Sopenharmony_ci 5229141cc406Sopenharmony_ci case OPT_A3: 5230141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5231141cc406Sopenharmony_ci *val_p = s->hw_A3; 5232141cc406Sopenharmony_ci return ret; 5233141cc406Sopenharmony_ci 5234141cc406Sopenharmony_ci case OPT_B4: 5235141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5236141cc406Sopenharmony_ci *val_p = s->hw_B4; 5237141cc406Sopenharmony_ci return ret; 5238141cc406Sopenharmony_ci 5239141cc406Sopenharmony_ci case OPT_A4: 5240141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5241141cc406Sopenharmony_ci *val_p = s->hw_A4; 5242141cc406Sopenharmony_ci return ret; 5243141cc406Sopenharmony_ci 5244141cc406Sopenharmony_ci case OPT_B5: 5245141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5246141cc406Sopenharmony_ci *val_p = s->hw_B5; 5247141cc406Sopenharmony_ci return ret; 5248141cc406Sopenharmony_ci 5249141cc406Sopenharmony_ci case OPT_HOPPER: 5250141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5251141cc406Sopenharmony_ci *val_p = s->hw_hopper; 5252141cc406Sopenharmony_ci return ret; 5253141cc406Sopenharmony_ci 5254141cc406Sopenharmony_ci case OPT_OMR: 5255141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5256141cc406Sopenharmony_ci *val_p = s->hw_omr; 5257141cc406Sopenharmony_ci return ret; 5258141cc406Sopenharmony_ci 5259141cc406Sopenharmony_ci case OPT_ADF_OPEN: 5260141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5261141cc406Sopenharmony_ci *val_p = s->hw_adf_open; 5262141cc406Sopenharmony_ci return ret; 5263141cc406Sopenharmony_ci 5264141cc406Sopenharmony_ci case OPT_CARD_LOADED: 5265141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5266141cc406Sopenharmony_ci *val_p = s->hw_card_loaded; 5267141cc406Sopenharmony_ci return ret; 5268141cc406Sopenharmony_ci 5269141cc406Sopenharmony_ci case OPT_SLEEP: 5270141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5271141cc406Sopenharmony_ci *val_p = s->hw_sleep; 5272141cc406Sopenharmony_ci return ret; 5273141cc406Sopenharmony_ci 5274141cc406Sopenharmony_ci case OPT_SEND_SW: 5275141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5276141cc406Sopenharmony_ci *val_p = s->hw_send_sw; 5277141cc406Sopenharmony_ci return ret; 5278141cc406Sopenharmony_ci 5279141cc406Sopenharmony_ci case OPT_MANUAL_FEED: 5280141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5281141cc406Sopenharmony_ci *val_p = s->hw_manual_feed; 5282141cc406Sopenharmony_ci return ret; 5283141cc406Sopenharmony_ci 5284141cc406Sopenharmony_ci case OPT_SCAN_SW: 5285141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5286141cc406Sopenharmony_ci *val_p = s->hw_scan_sw; 5287141cc406Sopenharmony_ci return ret; 5288141cc406Sopenharmony_ci 5289141cc406Sopenharmony_ci case OPT_FUNCTION: 5290141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5291141cc406Sopenharmony_ci *val_p = s->hw_function; 5292141cc406Sopenharmony_ci return ret; 5293141cc406Sopenharmony_ci 5294141cc406Sopenharmony_ci case OPT_INK_EMPTY: 5295141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5296141cc406Sopenharmony_ci *val_p = s->hw_ink_empty; 5297141cc406Sopenharmony_ci return ret; 5298141cc406Sopenharmony_ci 5299141cc406Sopenharmony_ci case OPT_DOUBLE_FEED: 5300141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5301141cc406Sopenharmony_ci *val_p = s->hw_double_feed; 5302141cc406Sopenharmony_ci return ret; 5303141cc406Sopenharmony_ci 5304141cc406Sopenharmony_ci case OPT_ERROR_CODE: 5305141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5306141cc406Sopenharmony_ci *val_p = s->hw_error_code; 5307141cc406Sopenharmony_ci return ret; 5308141cc406Sopenharmony_ci 5309141cc406Sopenharmony_ci case OPT_SKEW_ANGLE: 5310141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5311141cc406Sopenharmony_ci *val_p = s->hw_skew_angle; 5312141cc406Sopenharmony_ci return ret; 5313141cc406Sopenharmony_ci 5314141cc406Sopenharmony_ci case OPT_INK_REMAIN: 5315141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5316141cc406Sopenharmony_ci *val_p = s->hw_ink_remain; 5317141cc406Sopenharmony_ci return ret; 5318141cc406Sopenharmony_ci 5319141cc406Sopenharmony_ci case OPT_DENSITY_SW: 5320141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5321141cc406Sopenharmony_ci *val_p = s->hw_density_sw; 5322141cc406Sopenharmony_ci return ret; 5323141cc406Sopenharmony_ci 5324141cc406Sopenharmony_ci case OPT_DUPLEX_SW: 5325141cc406Sopenharmony_ci ret = get_hardware_status(s,option); 5326141cc406Sopenharmony_ci *val_p = s->hw_duplex_sw; 5327141cc406Sopenharmony_ci return ret; 5328141cc406Sopenharmony_ci 5329141cc406Sopenharmony_ci } 5330141cc406Sopenharmony_ci } 5331141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) { 5332141cc406Sopenharmony_ci int tmp; 5333141cc406Sopenharmony_ci SANE_Word val_c; 5334141cc406Sopenharmony_ci SANE_Status status; 5335141cc406Sopenharmony_ci 5336141cc406Sopenharmony_ci DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); 5337141cc406Sopenharmony_ci 5338141cc406Sopenharmony_ci if ( s->started ) { 5339141cc406Sopenharmony_ci DBG (5, "sane_control_option: can't set, device busy\n"); 5340141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 5341141cc406Sopenharmony_ci } 5342141cc406Sopenharmony_ci 5343141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) { 5344141cc406Sopenharmony_ci DBG (5, "sane_control_option: not settable\n"); 5345141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5346141cc406Sopenharmony_ci } 5347141cc406Sopenharmony_ci 5348141cc406Sopenharmony_ci status = sanei_constrain_value (s->opt + option, val, info); 5349141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 5350141cc406Sopenharmony_ci DBG (5, "sane_control_option: bad value\n"); 5351141cc406Sopenharmony_ci return status; 5352141cc406Sopenharmony_ci } 5353141cc406Sopenharmony_ci 5354141cc406Sopenharmony_ci /* may have been changed by constrain, so don't copy until now */ 5355141cc406Sopenharmony_ci val_c = *(SANE_Word *)val; 5356141cc406Sopenharmony_ci 5357141cc406Sopenharmony_ci /* 5358141cc406Sopenharmony_ci * Note - for those options which can assume one of a list of 5359141cc406Sopenharmony_ci * valid values, we can safely assume that they will have 5360141cc406Sopenharmony_ci * exactly one of those values because that's what 5361141cc406Sopenharmony_ci * sanei_constrain_value does. Hence no "else: invalid" branches 5362141cc406Sopenharmony_ci * below. 5363141cc406Sopenharmony_ci */ 5364141cc406Sopenharmony_ci switch (option) { 5365141cc406Sopenharmony_ci 5366141cc406Sopenharmony_ci /* Mode Group */ 5367141cc406Sopenharmony_ci case OPT_SOURCE: 5368141cc406Sopenharmony_ci if (!strcmp (val, STRING_ADFFRONT)) { 5369141cc406Sopenharmony_ci tmp = SOURCE_ADF_FRONT; 5370141cc406Sopenharmony_ci } 5371141cc406Sopenharmony_ci else if (!strcmp (val, STRING_ADFBACK)) { 5372141cc406Sopenharmony_ci tmp = SOURCE_ADF_BACK; 5373141cc406Sopenharmony_ci } 5374141cc406Sopenharmony_ci else if (!strcmp (val, STRING_ADFDUPLEX)) { 5375141cc406Sopenharmony_ci tmp = SOURCE_ADF_DUPLEX; 5376141cc406Sopenharmony_ci } 5377141cc406Sopenharmony_ci else if (!strcmp (val, STRING_CARDFRONT)) { 5378141cc406Sopenharmony_ci tmp = SOURCE_CARD_FRONT; 5379141cc406Sopenharmony_ci } 5380141cc406Sopenharmony_ci else if (!strcmp (val, STRING_CARDBACK)) { 5381141cc406Sopenharmony_ci tmp = SOURCE_CARD_BACK; 5382141cc406Sopenharmony_ci } 5383141cc406Sopenharmony_ci else if (!strcmp (val, STRING_CARDDUPLEX)) { 5384141cc406Sopenharmony_ci tmp = SOURCE_CARD_DUPLEX; 5385141cc406Sopenharmony_ci } 5386141cc406Sopenharmony_ci else{ 5387141cc406Sopenharmony_ci tmp = SOURCE_FLATBED; 5388141cc406Sopenharmony_ci } 5389141cc406Sopenharmony_ci 5390141cc406Sopenharmony_ci if (s->source == tmp) 5391141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5392141cc406Sopenharmony_ci 5393141cc406Sopenharmony_ci s->source = tmp; 5394141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 5395141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5396141cc406Sopenharmony_ci 5397141cc406Sopenharmony_ci case OPT_MODE: 5398141cc406Sopenharmony_ci if (!strcmp (val, STRING_LINEART)) { 5399141cc406Sopenharmony_ci tmp = MODE_LINEART; 5400141cc406Sopenharmony_ci } 5401141cc406Sopenharmony_ci else if (!strcmp (val, STRING_HALFTONE)) { 5402141cc406Sopenharmony_ci tmp = MODE_HALFTONE; 5403141cc406Sopenharmony_ci } 5404141cc406Sopenharmony_ci else if (!strcmp (val, STRING_GRAYSCALE)) { 5405141cc406Sopenharmony_ci tmp = MODE_GRAYSCALE; 5406141cc406Sopenharmony_ci } 5407141cc406Sopenharmony_ci else{ 5408141cc406Sopenharmony_ci tmp = MODE_COLOR; 5409141cc406Sopenharmony_ci } 5410141cc406Sopenharmony_ci 5411141cc406Sopenharmony_ci if (tmp == s->u_mode) 5412141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5413141cc406Sopenharmony_ci 5414141cc406Sopenharmony_ci set_mode(s,tmp); 5415141cc406Sopenharmony_ci 5416141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 5417141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5418141cc406Sopenharmony_ci 5419141cc406Sopenharmony_ci case OPT_RES: 5420141cc406Sopenharmony_ci 5421141cc406Sopenharmony_ci if (s->resolution_x == val_c) 5422141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5423141cc406Sopenharmony_ci 5424141cc406Sopenharmony_ci s->resolution_x = val_c; 5425141cc406Sopenharmony_ci s->resolution_y = val_c; 5426141cc406Sopenharmony_ci set_max_y(s); 5427141cc406Sopenharmony_ci 5428141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 5429141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5430141cc406Sopenharmony_ci 5431141cc406Sopenharmony_ci /* Geometry Group */ 5432141cc406Sopenharmony_ci case OPT_TL_X: 5433141cc406Sopenharmony_ci if (s->tl_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) 5434141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5435141cc406Sopenharmony_ci 5436141cc406Sopenharmony_ci s->tl_x = FIXED_MM_TO_SCANNER_UNIT(val_c); 5437141cc406Sopenharmony_ci 5438141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 5439141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5440141cc406Sopenharmony_ci 5441141cc406Sopenharmony_ci case OPT_TL_Y: 5442141cc406Sopenharmony_ci if (s->tl_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) 5443141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5444141cc406Sopenharmony_ci 5445141cc406Sopenharmony_ci s->tl_y = FIXED_MM_TO_SCANNER_UNIT(val_c); 5446141cc406Sopenharmony_ci 5447141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 5448141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5449141cc406Sopenharmony_ci 5450141cc406Sopenharmony_ci case OPT_BR_X: 5451141cc406Sopenharmony_ci if (s->br_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) 5452141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5453141cc406Sopenharmony_ci 5454141cc406Sopenharmony_ci s->br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); 5455141cc406Sopenharmony_ci 5456141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 5457141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5458141cc406Sopenharmony_ci 5459141cc406Sopenharmony_ci case OPT_BR_Y: 5460141cc406Sopenharmony_ci if (s->br_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) 5461141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5462141cc406Sopenharmony_ci 5463141cc406Sopenharmony_ci s->br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); 5464141cc406Sopenharmony_ci 5465141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 5466141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5467141cc406Sopenharmony_ci 5468141cc406Sopenharmony_ci case OPT_PAGE_WIDTH: 5469141cc406Sopenharmony_ci if (s->page_width == FIXED_MM_TO_SCANNER_UNIT(val_c)) 5470141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5471141cc406Sopenharmony_ci 5472141cc406Sopenharmony_ci /* if full width image, and paper size is changed, 5473141cc406Sopenharmony_ci change the image size to match new paper */ 5474141cc406Sopenharmony_ci if (s->tl_x == 0 && s->br_x == s->page_width){ 5475141cc406Sopenharmony_ci DBG (20, "sane_control_option: br_x tracking page_width\n"); 5476141cc406Sopenharmony_ci s->br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); 5477141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 5478141cc406Sopenharmony_ci } 5479141cc406Sopenharmony_ci 5480141cc406Sopenharmony_ci s->page_width = FIXED_MM_TO_SCANNER_UNIT(val_c); 5481141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5482141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5483141cc406Sopenharmony_ci 5484141cc406Sopenharmony_ci case OPT_PAGE_HEIGHT: 5485141cc406Sopenharmony_ci if (s->page_height == FIXED_MM_TO_SCANNER_UNIT(val_c)) 5486141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5487141cc406Sopenharmony_ci 5488141cc406Sopenharmony_ci /* if full height image, and paper size is changed, 5489141cc406Sopenharmony_ci change the image size to match new paper */ 5490141cc406Sopenharmony_ci if (s->tl_y == 0 && s->br_y == s->page_height){ 5491141cc406Sopenharmony_ci DBG (20, "sane_control_option: br_y tracking page_height\n"); 5492141cc406Sopenharmony_ci s->br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); 5493141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 5494141cc406Sopenharmony_ci } 5495141cc406Sopenharmony_ci 5496141cc406Sopenharmony_ci s->page_height = FIXED_MM_TO_SCANNER_UNIT(val_c); 5497141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5498141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5499141cc406Sopenharmony_ci 5500141cc406Sopenharmony_ci /* Enhancement Group */ 5501141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 5502141cc406Sopenharmony_ci s->brightness = val_c; 5503141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5504141cc406Sopenharmony_ci 5505141cc406Sopenharmony_ci case OPT_CONTRAST: 5506141cc406Sopenharmony_ci s->contrast = val_c; 5507141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5508141cc406Sopenharmony_ci 5509141cc406Sopenharmony_ci case OPT_GAMMA: 5510141cc406Sopenharmony_ci s->gamma = SANE_UNFIX(val_c); 5511141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5512141cc406Sopenharmony_ci 5513141cc406Sopenharmony_ci case OPT_THRESHOLD: 5514141cc406Sopenharmony_ci s->threshold = val_c; 5515141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5516141cc406Sopenharmony_ci 5517141cc406Sopenharmony_ci /* IPC */ 5518141cc406Sopenharmony_ci case OPT_RIF: 5519141cc406Sopenharmony_ci s->rif = val_c; 5520141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5521141cc406Sopenharmony_ci 5522141cc406Sopenharmony_ci case OPT_HT_TYPE: 5523141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5524141cc406Sopenharmony_ci s->ht_type = WD_ht_type_DEFAULT; 5525141cc406Sopenharmony_ci else if (!strcmp(val, STRING_DITHER)) 5526141cc406Sopenharmony_ci s->ht_type = WD_ht_type_DITHER; 5527141cc406Sopenharmony_ci else if (!strcmp(val, STRING_DIFFUSION)) 5528141cc406Sopenharmony_ci s->ht_type = WD_ht_type_DIFFUSION; 5529141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5530141cc406Sopenharmony_ci 5531141cc406Sopenharmony_ci case OPT_HT_PATTERN: 5532141cc406Sopenharmony_ci s->ht_pattern = val_c; 5533141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5534141cc406Sopenharmony_ci 5535141cc406Sopenharmony_ci case OPT_OUTLINE: 5536141cc406Sopenharmony_ci s->outline = val_c; 5537141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5538141cc406Sopenharmony_ci 5539141cc406Sopenharmony_ci case OPT_EMPHASIS: 5540141cc406Sopenharmony_ci s->emphasis = val_c; 5541141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5542141cc406Sopenharmony_ci 5543141cc406Sopenharmony_ci case OPT_SEPARATION: 5544141cc406Sopenharmony_ci s->separation = val_c; 5545141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5546141cc406Sopenharmony_ci 5547141cc406Sopenharmony_ci case OPT_MIRRORING: 5548141cc406Sopenharmony_ci s->mirroring = val_c; 5549141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5550141cc406Sopenharmony_ci 5551141cc406Sopenharmony_ci case OPT_WL_FOLLOW: 5552141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5553141cc406Sopenharmony_ci s->wl_follow = WD_wl_follow_DEFAULT; 5554141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5555141cc406Sopenharmony_ci s->wl_follow = WD_wl_follow_ON; 5556141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5557141cc406Sopenharmony_ci s->wl_follow = WD_wl_follow_OFF; 5558141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5559141cc406Sopenharmony_ci 5560141cc406Sopenharmony_ci /* DTC params*/ 5561141cc406Sopenharmony_ci case OPT_BP_FILTER: 5562141cc406Sopenharmony_ci s->bp_filter = val_c; 5563141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5564141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5565141cc406Sopenharmony_ci 5566141cc406Sopenharmony_ci case OPT_SMOOTHING: 5567141cc406Sopenharmony_ci s->smoothing = val_c; 5568141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5569141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5570141cc406Sopenharmony_ci 5571141cc406Sopenharmony_ci case OPT_GAMMA_CURVE: 5572141cc406Sopenharmony_ci s->gamma_curve = val_c; 5573141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5574141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5575141cc406Sopenharmony_ci 5576141cc406Sopenharmony_ci case OPT_THRESHOLD_CURVE: 5577141cc406Sopenharmony_ci s->threshold_curve = val_c; 5578141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5579141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5580141cc406Sopenharmony_ci 5581141cc406Sopenharmony_ci case OPT_THRESHOLD_WHITE: 5582141cc406Sopenharmony_ci s->threshold_white = val_c; 5583141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5584141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5585141cc406Sopenharmony_ci 5586141cc406Sopenharmony_ci case OPT_NOISE_REMOVAL: 5587141cc406Sopenharmony_ci s->noise_removal = val_c; 5588141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5589141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5590141cc406Sopenharmony_ci 5591141cc406Sopenharmony_ci case OPT_MATRIX_5: 5592141cc406Sopenharmony_ci s->matrix_5 = val_c; 5593141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5594141cc406Sopenharmony_ci 5595141cc406Sopenharmony_ci case OPT_MATRIX_4: 5596141cc406Sopenharmony_ci s->matrix_4 = val_c; 5597141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5598141cc406Sopenharmony_ci 5599141cc406Sopenharmony_ci case OPT_MATRIX_3: 5600141cc406Sopenharmony_ci s->matrix_3 = val_c; 5601141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5602141cc406Sopenharmony_ci 5603141cc406Sopenharmony_ci case OPT_MATRIX_2: 5604141cc406Sopenharmony_ci s->matrix_2 = val_c; 5605141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5606141cc406Sopenharmony_ci 5607141cc406Sopenharmony_ci /* SDTC params*/ 5608141cc406Sopenharmony_ci case OPT_VARIANCE: 5609141cc406Sopenharmony_ci s->variance = val_c; 5610141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5611141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5612141cc406Sopenharmony_ci 5613141cc406Sopenharmony_ci /* Advanced Group */ 5614141cc406Sopenharmony_ci case OPT_AWD: 5615141cc406Sopenharmony_ci s->awd = val_c; 5616141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5617141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5618141cc406Sopenharmony_ci 5619141cc406Sopenharmony_ci case OPT_ALD: 5620141cc406Sopenharmony_ci s->ald = val_c; 5621141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5622141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5623141cc406Sopenharmony_ci 5624141cc406Sopenharmony_ci case OPT_COMPRESS: 5625141cc406Sopenharmony_ci if (!strcmp (val, STRING_JPEG)) { 5626141cc406Sopenharmony_ci tmp = COMP_JPEG; 5627141cc406Sopenharmony_ci } 5628141cc406Sopenharmony_ci else{ 5629141cc406Sopenharmony_ci tmp = COMP_NONE; 5630141cc406Sopenharmony_ci } 5631141cc406Sopenharmony_ci 5632141cc406Sopenharmony_ci if (tmp == s->compress) 5633141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5634141cc406Sopenharmony_ci 5635141cc406Sopenharmony_ci s->compress = tmp; 5636141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5637141cc406Sopenharmony_ci 5638141cc406Sopenharmony_ci case OPT_COMPRESS_ARG: 5639141cc406Sopenharmony_ci s->compress_arg = val_c; 5640141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5641141cc406Sopenharmony_ci 5642141cc406Sopenharmony_ci case OPT_DF_ACTION: 5643141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5644141cc406Sopenharmony_ci s->df_action = DF_DEFAULT; 5645141cc406Sopenharmony_ci else if (!strcmp(val, STRING_CONTINUE)) 5646141cc406Sopenharmony_ci s->df_action = DF_CONTINUE; 5647141cc406Sopenharmony_ci else if (!strcmp(val, STRING_STOP)) 5648141cc406Sopenharmony_ci s->df_action = DF_STOP; 5649141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5650141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5651141cc406Sopenharmony_ci 5652141cc406Sopenharmony_ci case OPT_DF_SKEW: 5653141cc406Sopenharmony_ci s->df_skew = val_c; 5654141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5655141cc406Sopenharmony_ci 5656141cc406Sopenharmony_ci case OPT_DF_THICKNESS: 5657141cc406Sopenharmony_ci s->df_thickness = val_c; 5658141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5659141cc406Sopenharmony_ci 5660141cc406Sopenharmony_ci case OPT_DF_LENGTH: 5661141cc406Sopenharmony_ci s->df_length = val_c; 5662141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5663141cc406Sopenharmony_ci 5664141cc406Sopenharmony_ci case OPT_DF_DIFF: 5665141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5666141cc406Sopenharmony_ci s->df_diff = MSEL_df_diff_DEFAULT; 5667141cc406Sopenharmony_ci else if (!strcmp(val, STRING_10MM)) 5668141cc406Sopenharmony_ci s->df_diff = MSEL_df_diff_10MM; 5669141cc406Sopenharmony_ci else if (!strcmp(val, STRING_15MM)) 5670141cc406Sopenharmony_ci s->df_diff = MSEL_df_diff_15MM; 5671141cc406Sopenharmony_ci else if (!strcmp(val, STRING_20MM)) 5672141cc406Sopenharmony_ci s->df_diff = MSEL_df_diff_20MM; 5673141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5674141cc406Sopenharmony_ci 5675141cc406Sopenharmony_ci case OPT_DF_RECOVERY: 5676141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5677141cc406Sopenharmony_ci s->df_recovery = MSEL_DEFAULT; 5678141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5679141cc406Sopenharmony_ci s->df_recovery = MSEL_ON; 5680141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5681141cc406Sopenharmony_ci s->df_recovery = MSEL_OFF; 5682141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5683141cc406Sopenharmony_ci 5684141cc406Sopenharmony_ci case OPT_PAPER_PROTECT: 5685141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5686141cc406Sopenharmony_ci s->paper_protect = MSEL_DEFAULT; 5687141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5688141cc406Sopenharmony_ci s->paper_protect = MSEL_ON; 5689141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5690141cc406Sopenharmony_ci s->paper_protect = MSEL_OFF; 5691141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5692141cc406Sopenharmony_ci 5693141cc406Sopenharmony_ci case OPT_ADV_PAPER_PROT: 5694141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5695141cc406Sopenharmony_ci s->adv_paper_prot = MSEL_DEFAULT; 5696141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5697141cc406Sopenharmony_ci s->adv_paper_prot = MSEL_ON; 5698141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5699141cc406Sopenharmony_ci s->adv_paper_prot = MSEL_OFF; 5700141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5701141cc406Sopenharmony_ci 5702141cc406Sopenharmony_ci case OPT_STAPLE_DETECT: 5703141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5704141cc406Sopenharmony_ci s->staple_detect = MSEL_DEFAULT; 5705141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5706141cc406Sopenharmony_ci s->staple_detect = MSEL_ON; 5707141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5708141cc406Sopenharmony_ci s->staple_detect = MSEL_OFF; 5709141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5710141cc406Sopenharmony_ci 5711141cc406Sopenharmony_ci case OPT_BG_COLOR: 5712141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5713141cc406Sopenharmony_ci s->bg_color = COLOR_DEFAULT; 5714141cc406Sopenharmony_ci else if (!strcmp(val, STRING_WHITE)) 5715141cc406Sopenharmony_ci s->bg_color = COLOR_WHITE; 5716141cc406Sopenharmony_ci else if (!strcmp(val, STRING_BLACK)) 5717141cc406Sopenharmony_ci s->bg_color = COLOR_BLACK; 5718141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5719141cc406Sopenharmony_ci 5720141cc406Sopenharmony_ci case OPT_DROPOUT_COLOR: 5721141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5722141cc406Sopenharmony_ci s->dropout_color = COLOR_DEFAULT; 5723141cc406Sopenharmony_ci else if (!strcmp(val, STRING_RED)) 5724141cc406Sopenharmony_ci s->dropout_color = COLOR_RED; 5725141cc406Sopenharmony_ci else if (!strcmp(val, STRING_GREEN)) 5726141cc406Sopenharmony_ci s->dropout_color = COLOR_GREEN; 5727141cc406Sopenharmony_ci else if (!strcmp(val, STRING_BLUE)) 5728141cc406Sopenharmony_ci s->dropout_color = COLOR_BLUE; 5729141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5730141cc406Sopenharmony_ci 5731141cc406Sopenharmony_ci case OPT_BUFF_MODE: 5732141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5733141cc406Sopenharmony_ci s->buff_mode = MSEL_DEFAULT; 5734141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5735141cc406Sopenharmony_ci s->buff_mode= MSEL_ON; 5736141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5737141cc406Sopenharmony_ci s->buff_mode= MSEL_OFF; 5738141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5739141cc406Sopenharmony_ci 5740141cc406Sopenharmony_ci case OPT_PREPICK: 5741141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5742141cc406Sopenharmony_ci s->prepick = MSEL_DEFAULT; 5743141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5744141cc406Sopenharmony_ci s->prepick = MSEL_ON; 5745141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5746141cc406Sopenharmony_ci s->prepick = MSEL_OFF; 5747141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5748141cc406Sopenharmony_ci 5749141cc406Sopenharmony_ci case OPT_OVERSCAN: 5750141cc406Sopenharmony_ci if (!strcmp(val, STRING_DEFAULT)) 5751141cc406Sopenharmony_ci s->overscan = MSEL_DEFAULT; 5752141cc406Sopenharmony_ci else if (!strcmp(val, STRING_ON)) 5753141cc406Sopenharmony_ci s->overscan = MSEL_ON; 5754141cc406Sopenharmony_ci else if (!strcmp(val, STRING_OFF)) 5755141cc406Sopenharmony_ci s->overscan = MSEL_OFF; 5756141cc406Sopenharmony_ci 5757141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5758141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5759141cc406Sopenharmony_ci 5760141cc406Sopenharmony_ci case OPT_SLEEP_TIME: 5761141cc406Sopenharmony_ci s->sleep_time = val_c; 5762141cc406Sopenharmony_ci return set_sleep_mode(s); 5763141cc406Sopenharmony_ci 5764141cc406Sopenharmony_ci case OPT_OFF_TIME: 5765141cc406Sopenharmony_ci /* do our own constrain, because we want to round up */ 5766141cc406Sopenharmony_ci s->off_time = (val_c + 14)/15*15; 5767141cc406Sopenharmony_ci if(s->off_time != val_c){ 5768141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 5769141cc406Sopenharmony_ci } 5770141cc406Sopenharmony_ci return set_off_mode(s); 5771141cc406Sopenharmony_ci 5772141cc406Sopenharmony_ci case OPT_DUPLEX_OFFSET: 5773141cc406Sopenharmony_ci s->duplex_offset = val_c; 5774141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5775141cc406Sopenharmony_ci 5776141cc406Sopenharmony_ci case OPT_GREEN_OFFSET: 5777141cc406Sopenharmony_ci s->green_offset = val_c; 5778141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5779141cc406Sopenharmony_ci 5780141cc406Sopenharmony_ci case OPT_BLUE_OFFSET: 5781141cc406Sopenharmony_ci s->blue_offset = val_c; 5782141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5783141cc406Sopenharmony_ci 5784141cc406Sopenharmony_ci case OPT_LOW_MEM: 5785141cc406Sopenharmony_ci s->low_mem = val_c; 5786141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5787141cc406Sopenharmony_ci 5788141cc406Sopenharmony_ci case OPT_HWDESKEWCROP: 5789141cc406Sopenharmony_ci s->hwdeskewcrop = val_c; 5790141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5791141cc406Sopenharmony_ci 5792141cc406Sopenharmony_ci case OPT_SWDESKEW: 5793141cc406Sopenharmony_ci s->swdeskew = val_c; 5794141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5795141cc406Sopenharmony_ci 5796141cc406Sopenharmony_ci case OPT_SWDESPECK: 5797141cc406Sopenharmony_ci s->swdespeck = val_c; 5798141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5799141cc406Sopenharmony_ci 5800141cc406Sopenharmony_ci case OPT_SWCROP: 5801141cc406Sopenharmony_ci s->swcrop = val_c; 5802141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5803141cc406Sopenharmony_ci 5804141cc406Sopenharmony_ci case OPT_SWSKIP: 5805141cc406Sopenharmony_ci s->swskip = SANE_UNFIX(val_c); 5806141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5807141cc406Sopenharmony_ci 5808141cc406Sopenharmony_ci case OPT_HALT_ON_CANCEL: 5809141cc406Sopenharmony_ci s->halt_on_cancel = val_c; 5810141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5811141cc406Sopenharmony_ci 5812141cc406Sopenharmony_ci /* Endorser Group */ 5813141cc406Sopenharmony_ci case OPT_ENDORSER: 5814141cc406Sopenharmony_ci s->u_endorser = val_c; 5815141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 5816141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5817141cc406Sopenharmony_ci 5818141cc406Sopenharmony_ci case OPT_ENDORSER_BITS: 5819141cc406Sopenharmony_ci s->u_endorser_bits = val_c; 5820141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5821141cc406Sopenharmony_ci 5822141cc406Sopenharmony_ci /*this val not used in send_endorser*/ 5823141cc406Sopenharmony_ci case OPT_ENDORSER_VAL: 5824141cc406Sopenharmony_ci s->u_endorser_val = val_c; 5825141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5826141cc406Sopenharmony_ci 5827141cc406Sopenharmony_ci case OPT_ENDORSER_STEP: 5828141cc406Sopenharmony_ci s->u_endorser_step = val_c; 5829141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5830141cc406Sopenharmony_ci 5831141cc406Sopenharmony_ci case OPT_ENDORSER_Y: 5832141cc406Sopenharmony_ci s->u_endorser_y = FIXED_MM_TO_SCANNER_UNIT(val_c); 5833141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5834141cc406Sopenharmony_ci 5835141cc406Sopenharmony_ci case OPT_ENDORSER_FONT: 5836141cc406Sopenharmony_ci 5837141cc406Sopenharmony_ci if (!strcmp (val, STRING_HORIZONTAL)){ 5838141cc406Sopenharmony_ci s->u_endorser_font = FONT_H; 5839141cc406Sopenharmony_ci } 5840141cc406Sopenharmony_ci else if (!strcmp (val, STRING_HORIZONTALBOLD)){ 5841141cc406Sopenharmony_ci s->u_endorser_font = FONT_HB; 5842141cc406Sopenharmony_ci } 5843141cc406Sopenharmony_ci else if (!strcmp (val, STRING_HORIZONTALNARROW)){ 5844141cc406Sopenharmony_ci s->u_endorser_font = FONT_HN; 5845141cc406Sopenharmony_ci } 5846141cc406Sopenharmony_ci else if (!strcmp (val, STRING_VERTICAL)){ 5847141cc406Sopenharmony_ci s->u_endorser_font = FONT_V; 5848141cc406Sopenharmony_ci } 5849141cc406Sopenharmony_ci else if (!strcmp (val, STRING_VERTICALBOLD)){ 5850141cc406Sopenharmony_ci s->u_endorser_font = FONT_VB; 5851141cc406Sopenharmony_ci } 5852141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5853141cc406Sopenharmony_ci 5854141cc406Sopenharmony_ci case OPT_ENDORSER_DIR: 5855141cc406Sopenharmony_ci if (!strcmp (val, STRING_TOPTOBOTTOM)){ 5856141cc406Sopenharmony_ci s->u_endorser_dir = DIR_TTB; 5857141cc406Sopenharmony_ci } 5858141cc406Sopenharmony_ci else if (!strcmp (val, STRING_BOTTOMTOTOP)){ 5859141cc406Sopenharmony_ci s->u_endorser_dir = DIR_BTT; 5860141cc406Sopenharmony_ci } 5861141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5862141cc406Sopenharmony_ci 5863141cc406Sopenharmony_ci /*this val not used in send_endorser*/ 5864141cc406Sopenharmony_ci case OPT_ENDORSER_SIDE: 5865141cc406Sopenharmony_ci if (!strcmp (val, STRING_FRONT)){ 5866141cc406Sopenharmony_ci s->u_endorser_side = ED_front; 5867141cc406Sopenharmony_ci } 5868141cc406Sopenharmony_ci else if (!strcmp (val, STRING_BACK)){ 5869141cc406Sopenharmony_ci s->u_endorser_side = ED_back; 5870141cc406Sopenharmony_ci } 5871141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5872141cc406Sopenharmony_ci 5873141cc406Sopenharmony_ci case OPT_ENDORSER_STRING: 5874141cc406Sopenharmony_ci strncpy( 5875141cc406Sopenharmony_ci (SANE_String)s->u_endorser_string, 5876141cc406Sopenharmony_ci (SANE_String)val, 5877141cc406Sopenharmony_ci s->endorser_string_len+1 5878141cc406Sopenharmony_ci ); 5879141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5880141cc406Sopenharmony_ci } /* switch */ 5881141cc406Sopenharmony_ci } /* else */ 5882141cc406Sopenharmony_ci 5883141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5884141cc406Sopenharmony_ci} 5885141cc406Sopenharmony_ci 5886141cc406Sopenharmony_cistatic SANE_Status 5887141cc406Sopenharmony_ciset_sleep_mode(struct fujitsu *s) 5888141cc406Sopenharmony_ci{ 5889141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 5890141cc406Sopenharmony_ci 5891141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 5892141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 5893141cc406Sopenharmony_ci 5894141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_min_len]; 5895141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_min_len; 5896141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 5897141cc406Sopenharmony_ci 5898141cc406Sopenharmony_ci DBG (10, "set_sleep_mode: start\n"); 5899141cc406Sopenharmony_ci 5900141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 5901141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 5902141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 5903141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 5904141cc406Sopenharmony_ci 5905141cc406Sopenharmony_ci memset(out,0,outLen); 5906141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_sleep); 5907141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_min_len-2); 5908141cc406Sopenharmony_ci set_MSEL_sleep_mode(page, s->sleep_time); 5909141cc406Sopenharmony_ci 5910141cc406Sopenharmony_ci ret = do_cmd ( 5911141cc406Sopenharmony_ci s, 1, 0, 5912141cc406Sopenharmony_ci cmd, cmdLen, 5913141cc406Sopenharmony_ci out, outLen, 5914141cc406Sopenharmony_ci NULL, NULL 5915141cc406Sopenharmony_ci ); 5916141cc406Sopenharmony_ci 5917141cc406Sopenharmony_ci DBG (10, "set_sleep_mode: finish\n"); 5918141cc406Sopenharmony_ci 5919141cc406Sopenharmony_ci return ret; 5920141cc406Sopenharmony_ci} 5921141cc406Sopenharmony_ci 5922141cc406Sopenharmony_cistatic SANE_Status 5923141cc406Sopenharmony_ciset_off_mode(struct fujitsu *s) 5924141cc406Sopenharmony_ci{ 5925141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 5926141cc406Sopenharmony_ci 5927141cc406Sopenharmony_ci unsigned char cmd[SEND_DIAGNOSTIC_len]; /*also big enough for READ_DIAG*/ 5928141cc406Sopenharmony_ci size_t cmdLen = SEND_DIAGNOSTIC_len; 5929141cc406Sopenharmony_ci 5930141cc406Sopenharmony_ci unsigned char out[SD_powoff_len]; 5931141cc406Sopenharmony_ci size_t outLen = SD_powoff_len; 5932141cc406Sopenharmony_ci 5933141cc406Sopenharmony_ci DBG (10, "set_off_mode: start\n"); 5934141cc406Sopenharmony_ci 5935141cc406Sopenharmony_ci if (!s->has_cmd_sdiag || !s->has_cmd_rdiag || !s->has_off_mode){ 5936141cc406Sopenharmony_ci DBG (5, "set_off_mode: not supported, returning\n"); 5937141cc406Sopenharmony_ci return ret; 5938141cc406Sopenharmony_ci } 5939141cc406Sopenharmony_ci 5940141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 5941141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SEND_DIAGNOSTIC_code); 5942141cc406Sopenharmony_ci set_SD_slftst(cmd, 0); 5943141cc406Sopenharmony_ci set_SD_xferlen(cmd, outLen); 5944141cc406Sopenharmony_ci 5945141cc406Sopenharmony_ci memcpy(out,SD_powoff_string,SD_powoff_stringlen); 5946141cc406Sopenharmony_ci set_SD_powoff_disable(out,!s->off_time); 5947141cc406Sopenharmony_ci set_SD_powoff_interval(out,s->off_time/15); 5948141cc406Sopenharmony_ci 5949141cc406Sopenharmony_ci ret = do_cmd ( 5950141cc406Sopenharmony_ci s, 1, 0, 5951141cc406Sopenharmony_ci cmd, cmdLen, 5952141cc406Sopenharmony_ci out, outLen, 5953141cc406Sopenharmony_ci NULL, NULL 5954141cc406Sopenharmony_ci ); 5955141cc406Sopenharmony_ci 5956141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD){ 5957141cc406Sopenharmony_ci DBG (5, "set_off_mode: send diag error: %d\n", ret); 5958141cc406Sopenharmony_ci return ret; 5959141cc406Sopenharmony_ci } 5960141cc406Sopenharmony_ci 5961141cc406Sopenharmony_ci DBG (10, "set_off_mode: finish\n"); 5962141cc406Sopenharmony_ci 5963141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5964141cc406Sopenharmony_ci} 5965141cc406Sopenharmony_ci 5966141cc406Sopenharmony_cistatic SANE_Status 5967141cc406Sopenharmony_ciget_hardware_status (struct fujitsu *s, SANE_Int option) 5968141cc406Sopenharmony_ci{ 5969141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 5970141cc406Sopenharmony_ci 5971141cc406Sopenharmony_ci DBG (10, "get_hardware_status: start\n"); 5972141cc406Sopenharmony_ci 5973141cc406Sopenharmony_ci /* only run this if frontend has already read the last time we got it */ 5974141cc406Sopenharmony_ci /* or if we don't care for such bookkeeping (private use) */ 5975141cc406Sopenharmony_ci if (!option || !s->hw_data_avail[option-OPT_TOP]) { 5976141cc406Sopenharmony_ci 5977141cc406Sopenharmony_ci DBG (15, "get_hardware_status: running\n"); 5978141cc406Sopenharmony_ci 5979141cc406Sopenharmony_ci /* mark all values as available */ 5980141cc406Sopenharmony_ci memset(s->hw_data_avail,1,sizeof(s->hw_data_avail)); 5981141cc406Sopenharmony_ci 5982141cc406Sopenharmony_ci if (s->has_cmd_hw_status){ 5983141cc406Sopenharmony_ci unsigned char cmd[GET_HW_STATUS_len]; 5984141cc406Sopenharmony_ci size_t cmdLen = GET_HW_STATUS_len; 5985141cc406Sopenharmony_ci 5986141cc406Sopenharmony_ci unsigned char in[GHS_data_len]; 5987141cc406Sopenharmony_ci size_t inLen = GHS_data_len; 5988141cc406Sopenharmony_ci 5989141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 5990141cc406Sopenharmony_ci set_SCSI_opcode(cmd, GET_HW_STATUS_code); 5991141cc406Sopenharmony_ci set_GHS_allocation_length(cmd, inLen); 5992141cc406Sopenharmony_ci 5993141cc406Sopenharmony_ci DBG (15, "get_hardware_status: calling ghs\n"); 5994141cc406Sopenharmony_ci 5995141cc406Sopenharmony_ci ret = do_cmd ( 5996141cc406Sopenharmony_ci s, 1, 0, 5997141cc406Sopenharmony_ci cmd, cmdLen, 5998141cc406Sopenharmony_ci NULL, 0, 5999141cc406Sopenharmony_ci in, &inLen 6000141cc406Sopenharmony_ci ); 6001141cc406Sopenharmony_ci 6002141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { 6003141cc406Sopenharmony_ci 6004141cc406Sopenharmony_ci s->hw_top = get_GHS_top(in); 6005141cc406Sopenharmony_ci s->hw_A3 = get_GHS_A3(in); 6006141cc406Sopenharmony_ci s->hw_B4 = get_GHS_B4(in); 6007141cc406Sopenharmony_ci s->hw_A4 = get_GHS_A4(in); 6008141cc406Sopenharmony_ci s->hw_B5 = get_GHS_B5(in); 6009141cc406Sopenharmony_ci 6010141cc406Sopenharmony_ci s->hw_hopper = get_GHS_hopper(in); 6011141cc406Sopenharmony_ci s->hw_omr = get_GHS_omr(in); 6012141cc406Sopenharmony_ci s->hw_adf_open = get_GHS_adf_open(in); 6013141cc406Sopenharmony_ci s->hw_card_loaded = get_GHS_exit(in); 6014141cc406Sopenharmony_ci 6015141cc406Sopenharmony_ci s->hw_sleep = get_GHS_sleep(in); 6016141cc406Sopenharmony_ci s->hw_send_sw = get_GHS_send_sw(in); 6017141cc406Sopenharmony_ci s->hw_manual_feed = get_GHS_manual_feed(in); 6018141cc406Sopenharmony_ci s->hw_scan_sw = get_GHS_scan_sw(in); 6019141cc406Sopenharmony_ci 6020141cc406Sopenharmony_ci s->hw_function = get_GHS_function(in); 6021141cc406Sopenharmony_ci s->hw_ink_empty = get_GHS_ink_empty(in); 6022141cc406Sopenharmony_ci 6023141cc406Sopenharmony_ci s->hw_double_feed = get_GHS_double_feed(in); 6024141cc406Sopenharmony_ci 6025141cc406Sopenharmony_ci s->hw_error_code = get_GHS_error_code(in); 6026141cc406Sopenharmony_ci 6027141cc406Sopenharmony_ci s->hw_skew_angle = get_GHS_skew_angle(in); 6028141cc406Sopenharmony_ci 6029141cc406Sopenharmony_ci if(inLen > 9){ 6030141cc406Sopenharmony_ci s->hw_ink_remain = get_GHS_ink_remain(in); 6031141cc406Sopenharmony_ci } 6032141cc406Sopenharmony_ci 6033141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 6034141cc406Sopenharmony_ci } 6035141cc406Sopenharmony_ci } 6036141cc406Sopenharmony_ci 6037141cc406Sopenharmony_ci /* 3091/2 put hardware status in RS data */ 6038141cc406Sopenharmony_ci else if (s->ghs_in_rs){ 6039141cc406Sopenharmony_ci unsigned char cmd[REQUEST_SENSE_len]; 6040141cc406Sopenharmony_ci size_t cmdLen = REQUEST_SENSE_len; 6041141cc406Sopenharmony_ci 6042141cc406Sopenharmony_ci unsigned char in[RS_return_size]; 6043141cc406Sopenharmony_ci size_t inLen = RS_return_size; 6044141cc406Sopenharmony_ci 6045141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6046141cc406Sopenharmony_ci set_SCSI_opcode(cmd, REQUEST_SENSE_code); 6047141cc406Sopenharmony_ci set_RS_return_size(cmd, inLen); 6048141cc406Sopenharmony_ci 6049141cc406Sopenharmony_ci DBG(15,"get_hardware_status: calling rs\n"); 6050141cc406Sopenharmony_ci 6051141cc406Sopenharmony_ci ret = do_cmd( 6052141cc406Sopenharmony_ci s,0,0, 6053141cc406Sopenharmony_ci cmd, cmdLen, 6054141cc406Sopenharmony_ci NULL,0, 6055141cc406Sopenharmony_ci in, &inLen 6056141cc406Sopenharmony_ci ); 6057141cc406Sopenharmony_ci 6058141cc406Sopenharmony_ci /* parse the rs data */ 6059141cc406Sopenharmony_ci if(ret == SANE_STATUS_GOOD){ 6060141cc406Sopenharmony_ci if(get_RS_sense_key(in)==0 && get_RS_ASC(in)==0x80){ 6061141cc406Sopenharmony_ci 6062141cc406Sopenharmony_ci s->hw_adf_open = get_RS_adf_open(in); 6063141cc406Sopenharmony_ci s->hw_send_sw = get_RS_send_sw(in); 6064141cc406Sopenharmony_ci s->hw_scan_sw = get_RS_scan_sw(in); 6065141cc406Sopenharmony_ci s->hw_duplex_sw = get_RS_duplex_sw(in); 6066141cc406Sopenharmony_ci s->hw_top = get_RS_top(in); 6067141cc406Sopenharmony_ci s->hw_hopper = get_RS_hopper(in); 6068141cc406Sopenharmony_ci s->hw_function = get_RS_function(in); 6069141cc406Sopenharmony_ci s->hw_density_sw = get_RS_density(in); 6070141cc406Sopenharmony_ci } 6071141cc406Sopenharmony_ci else{ 6072141cc406Sopenharmony_ci DBG (10, "get_hardware_status: unexpected RS values\n"); 6073141cc406Sopenharmony_ci } 6074141cc406Sopenharmony_ci } 6075141cc406Sopenharmony_ci } 6076141cc406Sopenharmony_ci } 6077141cc406Sopenharmony_ci 6078141cc406Sopenharmony_ci if(option) 6079141cc406Sopenharmony_ci s->hw_data_avail[option-OPT_TOP] = 0; 6080141cc406Sopenharmony_ci 6081141cc406Sopenharmony_ci DBG (10, "get_hardware_status: finish\n"); 6082141cc406Sopenharmony_ci 6083141cc406Sopenharmony_ci return ret; 6084141cc406Sopenharmony_ci} 6085141cc406Sopenharmony_ci 6086141cc406Sopenharmony_cistatic SANE_Status 6087141cc406Sopenharmony_cisend_endorser(struct fujitsu *s) 6088141cc406Sopenharmony_ci{ 6089141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6090141cc406Sopenharmony_ci 6091141cc406Sopenharmony_ci unsigned char cmd[SEND_len]; 6092141cc406Sopenharmony_ci size_t cmdLen = SEND_len; 6093141cc406Sopenharmony_ci 6094141cc406Sopenharmony_ci size_t strLen = strlen(s->u_endorser_string); 6095141cc406Sopenharmony_ci 6096141cc406Sopenharmony_ci unsigned char out[S_e_data_max_len]; /*we probably send less below*/ 6097141cc406Sopenharmony_ci size_t outLen = S_e_data_min_len + strLen; /*fi-5900 might want 1 more byte?*/ 6098141cc406Sopenharmony_ci 6099141cc406Sopenharmony_ci DBG (10, "send_endorser: start\n"); 6100141cc406Sopenharmony_ci 6101141cc406Sopenharmony_ci if (!s->has_endorser_f && !s->has_endorser_b){ 6102141cc406Sopenharmony_ci DBG (10, "send_endorser: unsupported\n"); 6103141cc406Sopenharmony_ci return ret; 6104141cc406Sopenharmony_ci } 6105141cc406Sopenharmony_ci 6106141cc406Sopenharmony_ci /*build the payload*/ 6107141cc406Sopenharmony_ci memset(out,0,outLen); 6108141cc406Sopenharmony_ci 6109141cc406Sopenharmony_ci /*fi-5900 front side uses 0x80, assume all others*/ 6110141cc406Sopenharmony_ci if(s->u_endorser_side == ED_front){ 6111141cc406Sopenharmony_ci set_S_endorser_data_id(out,0x80); 6112141cc406Sopenharmony_ci } 6113141cc406Sopenharmony_ci else{ 6114141cc406Sopenharmony_ci set_S_endorser_data_id(out,0); 6115141cc406Sopenharmony_ci } 6116141cc406Sopenharmony_ci 6117141cc406Sopenharmony_ci set_S_endorser_stamp(out,0); 6118141cc406Sopenharmony_ci set_S_endorser_elec(out,0); 6119141cc406Sopenharmony_ci 6120141cc406Sopenharmony_ci if(s->u_endorser_step < 0){ 6121141cc406Sopenharmony_ci set_S_endorser_decr(out,S_e_decr_dec); 6122141cc406Sopenharmony_ci } 6123141cc406Sopenharmony_ci else{ 6124141cc406Sopenharmony_ci set_S_endorser_decr(out,S_e_decr_inc); 6125141cc406Sopenharmony_ci } 6126141cc406Sopenharmony_ci 6127141cc406Sopenharmony_ci if(s->u_endorser_bits == 24){ 6128141cc406Sopenharmony_ci set_S_endorser_lap24(out,S_e_lap_24bit); 6129141cc406Sopenharmony_ci } 6130141cc406Sopenharmony_ci else{ 6131141cc406Sopenharmony_ci set_S_endorser_lap24(out,S_e_lap_16bit); 6132141cc406Sopenharmony_ci } 6133141cc406Sopenharmony_ci 6134141cc406Sopenharmony_ci set_S_endorser_ctstep(out,abs(s->u_endorser_step)); 6135141cc406Sopenharmony_ci set_S_endorser_ulx(out,0); 6136141cc406Sopenharmony_ci set_S_endorser_uly(out,s->u_endorser_y); 6137141cc406Sopenharmony_ci 6138141cc406Sopenharmony_ci switch (s->u_endorser_font) { 6139141cc406Sopenharmony_ci case FONT_H: 6140141cc406Sopenharmony_ci set_S_endorser_font(out,S_e_font_horiz); 6141141cc406Sopenharmony_ci set_S_endorser_bold(out,0); 6142141cc406Sopenharmony_ci break; 6143141cc406Sopenharmony_ci case FONT_HB: 6144141cc406Sopenharmony_ci set_S_endorser_font(out,S_e_font_horiz); 6145141cc406Sopenharmony_ci set_S_endorser_bold(out,1); 6146141cc406Sopenharmony_ci break; 6147141cc406Sopenharmony_ci case FONT_HN: 6148141cc406Sopenharmony_ci set_S_endorser_font(out,S_e_font_horiz_narrow); 6149141cc406Sopenharmony_ci set_S_endorser_bold(out,0); 6150141cc406Sopenharmony_ci break; 6151141cc406Sopenharmony_ci case FONT_V: 6152141cc406Sopenharmony_ci set_S_endorser_font(out,S_e_font_vert); 6153141cc406Sopenharmony_ci set_S_endorser_bold(out,0); 6154141cc406Sopenharmony_ci break; 6155141cc406Sopenharmony_ci case FONT_VB: 6156141cc406Sopenharmony_ci set_S_endorser_font(out,S_e_font_vert); 6157141cc406Sopenharmony_ci set_S_endorser_bold(out,1); 6158141cc406Sopenharmony_ci break; 6159141cc406Sopenharmony_ci } 6160141cc406Sopenharmony_ci 6161141cc406Sopenharmony_ci set_S_endorser_size(out,0); 6162141cc406Sopenharmony_ci set_S_endorser_revs(out,0); 6163141cc406Sopenharmony_ci 6164141cc406Sopenharmony_ci if(s->u_endorser_dir == DIR_BTT){ 6165141cc406Sopenharmony_ci set_S_endorser_dirs(out,S_e_dir_bottom_top); 6166141cc406Sopenharmony_ci } 6167141cc406Sopenharmony_ci else{ 6168141cc406Sopenharmony_ci set_S_endorser_dirs(out,S_e_dir_top_bottom); 6169141cc406Sopenharmony_ci } 6170141cc406Sopenharmony_ci 6171141cc406Sopenharmony_ci set_S_endorser_string_length(out, strLen); 6172141cc406Sopenharmony_ci set_S_endorser_string(out, s->u_endorser_string, strLen); 6173141cc406Sopenharmony_ci 6174141cc406Sopenharmony_ci /*build the command*/ 6175141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6176141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SEND_code); 6177141cc406Sopenharmony_ci set_S_xfer_datatype (cmd, S_datatype_endorser_data); 6178141cc406Sopenharmony_ci set_S_xfer_length (cmd, outLen); 6179141cc406Sopenharmony_ci 6180141cc406Sopenharmony_ci ret = do_cmd ( 6181141cc406Sopenharmony_ci s, 1, 0, 6182141cc406Sopenharmony_ci cmd, cmdLen, 6183141cc406Sopenharmony_ci out, outLen, 6184141cc406Sopenharmony_ci NULL, NULL 6185141cc406Sopenharmony_ci ); 6186141cc406Sopenharmony_ci 6187141cc406Sopenharmony_ci DBG (10, "send_endorser: finish %d\n", ret); 6188141cc406Sopenharmony_ci 6189141cc406Sopenharmony_ci return ret; 6190141cc406Sopenharmony_ci} 6191141cc406Sopenharmony_ci 6192141cc406Sopenharmony_ci/* instead of internal brightness/contrast/gamma 6193141cc406Sopenharmony_ci most scanners use a 256x256 or 1024x256 LUT 6194141cc406Sopenharmony_ci default is linear table of slope 1 or 1/4 resp. 6195141cc406Sopenharmony_ci brightness and contrast inputs are -127 to +127 6196141cc406Sopenharmony_ci 6197141cc406Sopenharmony_ci contrast rotates slope of line around central input val 6198141cc406Sopenharmony_ci 6199141cc406Sopenharmony_ci high low 6200141cc406Sopenharmony_ci . x . 6201141cc406Sopenharmony_ci . x . xx 6202141cc406Sopenharmony_ci out . x . xxxxxxxx 6203141cc406Sopenharmony_ci . x xx 6204141cc406Sopenharmony_ci ....x....... ............ 6205141cc406Sopenharmony_ci in in 6206141cc406Sopenharmony_ci 6207141cc406Sopenharmony_ci then brightness moves line vertically, and clamps to 8bit 6208141cc406Sopenharmony_ci 6209141cc406Sopenharmony_ci bright dark 6210141cc406Sopenharmony_ci . xxxxxxxx . 6211141cc406Sopenharmony_ci . x . 6212141cc406Sopenharmony_ci out x . x 6213141cc406Sopenharmony_ci . . x 6214141cc406Sopenharmony_ci ............ xxxxxxxx.... 6215141cc406Sopenharmony_ci in in 6216141cc406Sopenharmony_ci */ 6217141cc406Sopenharmony_cistatic SANE_Status 6218141cc406Sopenharmony_cisend_lut (struct fujitsu *s) 6219141cc406Sopenharmony_ci{ 6220141cc406Sopenharmony_ci int i, j, bytes = 1 << s->adbits; 6221141cc406Sopenharmony_ci double b, slope, offset; 6222141cc406Sopenharmony_ci 6223141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6224141cc406Sopenharmony_ci 6225141cc406Sopenharmony_ci unsigned char cmd[SEND_len]; 6226141cc406Sopenharmony_ci size_t cmdLen = SEND_len; 6227141cc406Sopenharmony_ci 6228141cc406Sopenharmony_ci unsigned char out[S_lut_header_len + S_lut_data_max_len]; 6229141cc406Sopenharmony_ci size_t outLen = S_lut_header_len + S_lut_data_max_len; 6230141cc406Sopenharmony_ci unsigned char * p = out + S_lut_header_len; 6231141cc406Sopenharmony_ci 6232141cc406Sopenharmony_ci DBG (10, "send_lut: start\n"); 6233141cc406Sopenharmony_ci 6234141cc406Sopenharmony_ci if(!s->num_download_gamma || !s->adbits){ 6235141cc406Sopenharmony_ci DBG (10, "send_lut: unsupported\n"); 6236141cc406Sopenharmony_ci return ret; 6237141cc406Sopenharmony_ci } 6238141cc406Sopenharmony_ci 6239141cc406Sopenharmony_ci /* contrast is converted to a slope [0,90] degrees: 6240141cc406Sopenharmony_ci * first [-127,127] to [0,254] then to [0,1] 6241141cc406Sopenharmony_ci * then multiply by PI/2 to convert to radians 6242141cc406Sopenharmony_ci * then take the tangent to get slope (T.O.A) 6243141cc406Sopenharmony_ci * then multiply by the normal linear slope 6244141cc406Sopenharmony_ci * because the table may not be square, i.e. 1024x256*/ 6245141cc406Sopenharmony_ci slope = tan(((double)s->contrast+127)/254 * M_PI/2) * 256/bytes; 6246141cc406Sopenharmony_ci 6247141cc406Sopenharmony_ci /* contrast slope must stay centered, so figure 6248141cc406Sopenharmony_ci * out vertical offset at central input value */ 6249141cc406Sopenharmony_ci offset = 127.5-(slope*bytes/2); 6250141cc406Sopenharmony_ci 6251141cc406Sopenharmony_ci /* convert the user brightness setting (-127 to +127) 6252141cc406Sopenharmony_ci * into a scale that covers the range required 6253141cc406Sopenharmony_ci * to slide the contrast curve entirely off the table */ 6254141cc406Sopenharmony_ci b = ((double)s->brightness/127) * (256 - offset); 6255141cc406Sopenharmony_ci 6256141cc406Sopenharmony_ci DBG (15, "send_lut: %d %f %d %f %f\n", s->brightness, b, 6257141cc406Sopenharmony_ci s->contrast, slope, offset); 6258141cc406Sopenharmony_ci 6259141cc406Sopenharmony_ci outLen = S_lut_header_len + bytes; 6260141cc406Sopenharmony_ci 6261141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6262141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SEND_code); 6263141cc406Sopenharmony_ci 6264141cc406Sopenharmony_ci set_S_xfer_datatype (cmd, S_datatype_lut_data); 6265141cc406Sopenharmony_ci set_S_xfer_length (cmd, outLen); 6266141cc406Sopenharmony_ci 6267141cc406Sopenharmony_ci memset(out,0,outLen); 6268141cc406Sopenharmony_ci set_S_lut_order (out, S_lut_order_single); 6269141cc406Sopenharmony_ci set_S_lut_ssize (out, bytes); 6270141cc406Sopenharmony_ci set_S_lut_dsize (out, 256); 6271141cc406Sopenharmony_ci 6272141cc406Sopenharmony_ci for(i=0;i<bytes;i++){ 6273141cc406Sopenharmony_ci j=slope*i + offset + b; 6274141cc406Sopenharmony_ci 6275141cc406Sopenharmony_ci if(j<0){ 6276141cc406Sopenharmony_ci j=0; 6277141cc406Sopenharmony_ci } 6278141cc406Sopenharmony_ci 6279141cc406Sopenharmony_ci if(j>255){ 6280141cc406Sopenharmony_ci j=255; 6281141cc406Sopenharmony_ci } 6282141cc406Sopenharmony_ci 6283141cc406Sopenharmony_ci *p=j; 6284141cc406Sopenharmony_ci p++; 6285141cc406Sopenharmony_ci } 6286141cc406Sopenharmony_ci 6287141cc406Sopenharmony_ci ret = do_cmd ( 6288141cc406Sopenharmony_ci s, 1, 0, 6289141cc406Sopenharmony_ci cmd, cmdLen, 6290141cc406Sopenharmony_ci out, outLen, 6291141cc406Sopenharmony_ci NULL, NULL 6292141cc406Sopenharmony_ci ); 6293141cc406Sopenharmony_ci 6294141cc406Sopenharmony_ci DBG (10, "send_lut: finish\n"); 6295141cc406Sopenharmony_ci 6296141cc406Sopenharmony_ci return ret; 6297141cc406Sopenharmony_ci} 6298141cc406Sopenharmony_ci 6299141cc406Sopenharmony_cistatic SANE_Status 6300141cc406Sopenharmony_cisend_q_table (struct fujitsu *s) 6301141cc406Sopenharmony_ci{ 6302141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6303141cc406Sopenharmony_ci 6304141cc406Sopenharmony_ci unsigned char cmd[SEND_len]; 6305141cc406Sopenharmony_ci size_t cmdLen = SEND_len; 6306141cc406Sopenharmony_ci 6307141cc406Sopenharmony_ci unsigned char out[S_q_table_header_len + S_q_table_y_len + S_q_table_uv_len]; 6308141cc406Sopenharmony_ci size_t outLen = S_q_table_header_len + S_q_table_y_len + S_q_table_uv_len; 6309141cc406Sopenharmony_ci unsigned char * yp = out + S_q_table_header_len; 6310141cc406Sopenharmony_ci unsigned char * uvp = out + S_q_table_header_len + S_q_table_y_len; 6311141cc406Sopenharmony_ci 6312141cc406Sopenharmony_ci /* FIXME: generate these instead of hardcode */ 6313141cc406Sopenharmony_ci unsigned char ydata[] = { 6314141cc406Sopenharmony_ci 0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04, 6315141cc406Sopenharmony_ci 0x03, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0c, 6316141cc406Sopenharmony_ci 0x07, 0x07, 0x06, 0x06, 0x07, 0x0e, 0x0a, 0x0b, 6317141cc406Sopenharmony_ci 0x08, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f, 6318141cc406Sopenharmony_ci 0x10, 0x10, 0x13, 0x15, 0x1b, 0x17, 0x13, 0x14, 6319141cc406Sopenharmony_ci 0x1a, 0x14, 0x10, 0x10, 0x18, 0x20, 0x18, 0x1a, 6320141cc406Sopenharmony_ci 0x1c, 0x1d, 0x1e, 0x1f, 0x1e, 0x12, 0x17, 0x21, 6321141cc406Sopenharmony_ci 0x24, 0x21, 0x1e, 0x24, 0x1b, 0x1e, 0x1e, 0x1d }; 6322141cc406Sopenharmony_ci 6323141cc406Sopenharmony_ci unsigned char uvdata[] = { 6324141cc406Sopenharmony_ci 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0e, 0x07, 6325141cc406Sopenharmony_ci 0x07, 0x0e, 0x1d, 0x13, 0x10, 0x13, 0x1d, 0x1d, 6326141cc406Sopenharmony_ci 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 6327141cc406Sopenharmony_ci 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 6328141cc406Sopenharmony_ci 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 6329141cc406Sopenharmony_ci 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 6330141cc406Sopenharmony_ci 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 6331141cc406Sopenharmony_ci 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d }; 6332141cc406Sopenharmony_ci 6333141cc406Sopenharmony_ci DBG (10, "send_q_table: start\n"); 6334141cc406Sopenharmony_ci 6335141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6336141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SEND_code); 6337141cc406Sopenharmony_ci set_S_xfer_datatype (cmd, S_datatype_jpg_q_table); 6338141cc406Sopenharmony_ci set_S_xfer_length (cmd, outLen); 6339141cc406Sopenharmony_ci 6340141cc406Sopenharmony_ci memset(out,0,outLen); 6341141cc406Sopenharmony_ci set_S_q_table_y_len (out, S_q_table_y_len); 6342141cc406Sopenharmony_ci set_S_q_table_uv_len (out, S_q_table_uv_len); 6343141cc406Sopenharmony_ci memcpy (yp, ydata, S_q_table_y_len); 6344141cc406Sopenharmony_ci memcpy (uvp, uvdata, S_q_table_uv_len); 6345141cc406Sopenharmony_ci 6346141cc406Sopenharmony_ci ret = do_cmd ( 6347141cc406Sopenharmony_ci s, 1, 0, 6348141cc406Sopenharmony_ci cmd, cmdLen, 6349141cc406Sopenharmony_ci out, outLen, 6350141cc406Sopenharmony_ci NULL, NULL 6351141cc406Sopenharmony_ci ); 6352141cc406Sopenharmony_ci 6353141cc406Sopenharmony_ci DBG (10, "send_q_table: finish\n"); 6354141cc406Sopenharmony_ci 6355141cc406Sopenharmony_ci return ret; 6356141cc406Sopenharmony_ci} 6357141cc406Sopenharmony_ci 6358141cc406Sopenharmony_ci/* only used by iX500? */ 6359141cc406Sopenharmony_ci#if 0 6360141cc406Sopenharmony_cistatic SANE_Status 6361141cc406Sopenharmony_cimode_select_unk (struct fujitsu *s, int foo) 6362141cc406Sopenharmony_ci{ 6363141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6364141cc406Sopenharmony_ci 6365141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 6366141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 6367141cc406Sopenharmony_ci 6368141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_min_len]; 6369141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_min_len; 6370141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 6371141cc406Sopenharmony_ci 6372141cc406Sopenharmony_ci DBG (10, "mode_select_unk: start\n"); 6373141cc406Sopenharmony_ci 6374141cc406Sopenharmony_ci /*if (!s->has_MS_unk){ 6375141cc406Sopenharmony_ci DBG (10, "mode_select_unk: unsupported\n"); 6376141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6377141cc406Sopenharmony_ci }*/ 6378141cc406Sopenharmony_ci 6379141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6380141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 6381141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 6382141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 6383141cc406Sopenharmony_ci 6384141cc406Sopenharmony_ci memset(out,0,outLen); 6385141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_unk); 6386141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_min_len-2); 6387141cc406Sopenharmony_ci 6388141cc406Sopenharmony_ci *(page + 0x02) = foo; 6389141cc406Sopenharmony_ci 6390141cc406Sopenharmony_ci ret = do_cmd ( 6391141cc406Sopenharmony_ci s, 1, 0, 6392141cc406Sopenharmony_ci cmd, cmdLen, 6393141cc406Sopenharmony_ci out, outLen, 6394141cc406Sopenharmony_ci NULL, NULL 6395141cc406Sopenharmony_ci ); 6396141cc406Sopenharmony_ci 6397141cc406Sopenharmony_ci DBG (10, "mode_select_unk: finish\n"); 6398141cc406Sopenharmony_ci 6399141cc406Sopenharmony_ci return ret; 6400141cc406Sopenharmony_ci} 6401141cc406Sopenharmony_ci#endif 6402141cc406Sopenharmony_ci 6403141cc406Sopenharmony_ci/* only used by iX500? */ 6404141cc406Sopenharmony_cistatic SANE_Status 6405141cc406Sopenharmony_cidiag_preread (struct fujitsu *s) 6406141cc406Sopenharmony_ci{ 6407141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6408141cc406Sopenharmony_ci 6409141cc406Sopenharmony_ci unsigned char cmd[SEND_DIAGNOSTIC_len]; /*also big enough for READ_DIAG*/ 6410141cc406Sopenharmony_ci size_t cmdLen = SEND_DIAGNOSTIC_len; 6411141cc406Sopenharmony_ci 6412141cc406Sopenharmony_ci unsigned char out[SD_preread_len]; 6413141cc406Sopenharmony_ci size_t outLen = SD_preread_len; 6414141cc406Sopenharmony_ci 6415141cc406Sopenharmony_ci DBG (10, "diag_preread: start\n"); 6416141cc406Sopenharmony_ci 6417141cc406Sopenharmony_ci if (!s->has_cmd_sdiag || !s->has_cmd_rdiag || !s->need_diag_preread){ 6418141cc406Sopenharmony_ci DBG (5, "diag_preread: not supported, returning\n"); 6419141cc406Sopenharmony_ci return ret; 6420141cc406Sopenharmony_ci } 6421141cc406Sopenharmony_ci 6422141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6423141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SEND_DIAGNOSTIC_code); 6424141cc406Sopenharmony_ci set_SD_slftst(cmd, 0); 6425141cc406Sopenharmony_ci set_SD_xferlen(cmd, outLen); 6426141cc406Sopenharmony_ci 6427141cc406Sopenharmony_ci memcpy(out,SD_preread_string,SD_preread_stringlen); 6428141cc406Sopenharmony_ci set_SD_preread_xres(out,s->resolution_x); 6429141cc406Sopenharmony_ci set_SD_preread_yres(out,s->resolution_y); 6430141cc406Sopenharmony_ci /* call helper function, scanner wants lies about paper width */ 6431141cc406Sopenharmony_ci set_SD_preread_paper_width(out, get_page_width(s)); 6432141cc406Sopenharmony_ci /* don't call helper function, scanner wants actual length? */ 6433141cc406Sopenharmony_ci set_SD_preread_paper_length(out, s->page_height); 6434141cc406Sopenharmony_ci set_SD_preread_composition(out, s->s_mode); 6435141cc406Sopenharmony_ci 6436141cc406Sopenharmony_ci ret = do_cmd ( 6437141cc406Sopenharmony_ci s, 1, 0, 6438141cc406Sopenharmony_ci cmd, cmdLen, 6439141cc406Sopenharmony_ci out, outLen, 6440141cc406Sopenharmony_ci NULL, NULL 6441141cc406Sopenharmony_ci ); 6442141cc406Sopenharmony_ci 6443141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD){ 6444141cc406Sopenharmony_ci DBG (5, "diag_preread: send diag error: %d\n", ret); 6445141cc406Sopenharmony_ci return ret; 6446141cc406Sopenharmony_ci } 6447141cc406Sopenharmony_ci 6448141cc406Sopenharmony_ci DBG (10, "diag_preread: finish\n"); 6449141cc406Sopenharmony_ci 6450141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6451141cc406Sopenharmony_ci} 6452141cc406Sopenharmony_ci 6453141cc406Sopenharmony_cistatic SANE_Status 6454141cc406Sopenharmony_cimode_select_df (struct fujitsu *s) 6455141cc406Sopenharmony_ci{ 6456141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6457141cc406Sopenharmony_ci 6458141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 6459141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 6460141cc406Sopenharmony_ci 6461141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_min_len]; 6462141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_min_len; 6463141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 6464141cc406Sopenharmony_ci 6465141cc406Sopenharmony_ci DBG (10, "mode_select_df: start\n"); 6466141cc406Sopenharmony_ci 6467141cc406Sopenharmony_ci if(!s->has_MS_df){ 6468141cc406Sopenharmony_ci DBG (10, "mode_select_df: unsupported\n"); 6469141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6470141cc406Sopenharmony_ci } 6471141cc406Sopenharmony_ci 6472141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6473141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 6474141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 6475141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 6476141cc406Sopenharmony_ci 6477141cc406Sopenharmony_ci memset(out,0,outLen); 6478141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_df); 6479141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_min_len-2); 6480141cc406Sopenharmony_ci 6481141cc406Sopenharmony_ci /* continue/stop */ 6482141cc406Sopenharmony_ci if(s->df_action != DF_DEFAULT){ 6483141cc406Sopenharmony_ci set_MSEL_df_enable (page, 1); 6484141cc406Sopenharmony_ci 6485141cc406Sopenharmony_ci /* continue */ 6486141cc406Sopenharmony_ci if(s->df_action == DF_CONTINUE){ 6487141cc406Sopenharmony_ci set_MSEL_df_continue (page, 1); 6488141cc406Sopenharmony_ci } 6489141cc406Sopenharmony_ci 6490141cc406Sopenharmony_ci /* skew */ 6491141cc406Sopenharmony_ci if(s->df_skew){ 6492141cc406Sopenharmony_ci set_MSEL_df_skew (page, 1); 6493141cc406Sopenharmony_ci } 6494141cc406Sopenharmony_ci 6495141cc406Sopenharmony_ci /* thickness */ 6496141cc406Sopenharmony_ci if(s->df_thickness){ 6497141cc406Sopenharmony_ci set_MSEL_df_thickness (page, 1); 6498141cc406Sopenharmony_ci } 6499141cc406Sopenharmony_ci 6500141cc406Sopenharmony_ci /* length */ 6501141cc406Sopenharmony_ci if(s->df_length){ 6502141cc406Sopenharmony_ci set_MSEL_df_length (page, 1); 6503141cc406Sopenharmony_ci set_MSEL_df_diff (page, s->df_diff); 6504141cc406Sopenharmony_ci } 6505141cc406Sopenharmony_ci } 6506141cc406Sopenharmony_ci 6507141cc406Sopenharmony_ci set_MSEL_df_paperprot(page,s->paper_protect); 6508141cc406Sopenharmony_ci set_MSEL_df_stapledet(page,s->staple_detect); 6509141cc406Sopenharmony_ci set_MSEL_df_recovery(page,s->df_recovery); 6510141cc406Sopenharmony_ci set_MSEL_df_paperprot2(page,s->adv_paper_prot); 6511141cc406Sopenharmony_ci 6512141cc406Sopenharmony_ci ret = do_cmd ( 6513141cc406Sopenharmony_ci s, 1, 0, 6514141cc406Sopenharmony_ci cmd, cmdLen, 6515141cc406Sopenharmony_ci out, outLen, 6516141cc406Sopenharmony_ci NULL, NULL 6517141cc406Sopenharmony_ci ); 6518141cc406Sopenharmony_ci 6519141cc406Sopenharmony_ci DBG (10, "mode_select_df: finish\n"); 6520141cc406Sopenharmony_ci 6521141cc406Sopenharmony_ci return ret; 6522141cc406Sopenharmony_ci} 6523141cc406Sopenharmony_ci 6524141cc406Sopenharmony_cistatic SANE_Status 6525141cc406Sopenharmony_cimode_select_bg (struct fujitsu *s) 6526141cc406Sopenharmony_ci{ 6527141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6528141cc406Sopenharmony_ci 6529141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 6530141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 6531141cc406Sopenharmony_ci 6532141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_min_len]; 6533141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_min_len; 6534141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 6535141cc406Sopenharmony_ci 6536141cc406Sopenharmony_ci DBG (10, "mode_select_bg: start\n"); 6537141cc406Sopenharmony_ci 6538141cc406Sopenharmony_ci if(!s->has_MS_bg){ 6539141cc406Sopenharmony_ci DBG (10, "mode_select_bg: unsupported\n"); 6540141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6541141cc406Sopenharmony_ci } 6542141cc406Sopenharmony_ci 6543141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6544141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 6545141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 6546141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 6547141cc406Sopenharmony_ci 6548141cc406Sopenharmony_ci memset(out,0,outLen); 6549141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_bg); 6550141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_min_len-2); 6551141cc406Sopenharmony_ci 6552141cc406Sopenharmony_ci if(s->bg_color != COLOR_DEFAULT){ 6553141cc406Sopenharmony_ci set_MSEL_bg_enable (page, 1); 6554141cc406Sopenharmony_ci 6555141cc406Sopenharmony_ci if(s->bg_color == COLOR_BLACK){ 6556141cc406Sopenharmony_ci set_MSEL_bg_front (page, 1); 6557141cc406Sopenharmony_ci set_MSEL_bg_back (page, 1); 6558141cc406Sopenharmony_ci set_MSEL_bg_fb (page, 1); 6559141cc406Sopenharmony_ci } 6560141cc406Sopenharmony_ci } 6561141cc406Sopenharmony_ci 6562141cc406Sopenharmony_ci ret = do_cmd ( 6563141cc406Sopenharmony_ci s, 1, 0, 6564141cc406Sopenharmony_ci cmd, cmdLen, 6565141cc406Sopenharmony_ci out, outLen, 6566141cc406Sopenharmony_ci NULL, NULL 6567141cc406Sopenharmony_ci ); 6568141cc406Sopenharmony_ci 6569141cc406Sopenharmony_ci DBG (10, "mode_select_bg: finish\n"); 6570141cc406Sopenharmony_ci 6571141cc406Sopenharmony_ci return ret; 6572141cc406Sopenharmony_ci} 6573141cc406Sopenharmony_ci 6574141cc406Sopenharmony_cistatic SANE_Status 6575141cc406Sopenharmony_cimode_select_dropout (struct fujitsu *s) 6576141cc406Sopenharmony_ci{ 6577141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6578141cc406Sopenharmony_ci 6579141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 6580141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 6581141cc406Sopenharmony_ci 6582141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_max_len]; 6583141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_max_len; 6584141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 6585141cc406Sopenharmony_ci 6586141cc406Sopenharmony_ci DBG (10, "mode_select_dropout: start\n"); 6587141cc406Sopenharmony_ci 6588141cc406Sopenharmony_ci if(!s->has_MS_dropout){ 6589141cc406Sopenharmony_ci DBG (10, "mode_select_dropout: unsupported\n"); 6590141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6591141cc406Sopenharmony_ci } 6592141cc406Sopenharmony_ci 6593141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6594141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 6595141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 6596141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 6597141cc406Sopenharmony_ci 6598141cc406Sopenharmony_ci memset(out,0,outLen); 6599141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_dropout); 6600141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_max_len-2); 6601141cc406Sopenharmony_ci 6602141cc406Sopenharmony_ci set_MSEL_dropout_front (page, s->dropout_color); 6603141cc406Sopenharmony_ci set_MSEL_dropout_back (page, s->dropout_color); 6604141cc406Sopenharmony_ci 6605141cc406Sopenharmony_ci ret = do_cmd ( 6606141cc406Sopenharmony_ci s, 1, 0, 6607141cc406Sopenharmony_ci cmd, cmdLen, 6608141cc406Sopenharmony_ci out, outLen, 6609141cc406Sopenharmony_ci NULL, NULL 6610141cc406Sopenharmony_ci ); 6611141cc406Sopenharmony_ci 6612141cc406Sopenharmony_ci DBG (10, "mode_select_dropout: finish\n"); 6613141cc406Sopenharmony_ci 6614141cc406Sopenharmony_ci return ret; 6615141cc406Sopenharmony_ci} 6616141cc406Sopenharmony_ci 6617141cc406Sopenharmony_cistatic SANE_Status 6618141cc406Sopenharmony_cimode_select_buff (struct fujitsu *s) 6619141cc406Sopenharmony_ci{ 6620141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6621141cc406Sopenharmony_ci 6622141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 6623141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 6624141cc406Sopenharmony_ci 6625141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_min_len]; 6626141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_min_len; 6627141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 6628141cc406Sopenharmony_ci 6629141cc406Sopenharmony_ci DBG (10, "mode_select_buff: start\n"); 6630141cc406Sopenharmony_ci 6631141cc406Sopenharmony_ci if (!s->has_MS_buff){ 6632141cc406Sopenharmony_ci DBG (10, "mode_select_buff: unsupported\n"); 6633141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6634141cc406Sopenharmony_ci } 6635141cc406Sopenharmony_ci 6636141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6637141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 6638141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 6639141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 6640141cc406Sopenharmony_ci 6641141cc406Sopenharmony_ci memset(out,0,outLen); 6642141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_buff); 6643141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_min_len-2); 6644141cc406Sopenharmony_ci 6645141cc406Sopenharmony_ci set_MSEL_buff_mode(page, s->buff_mode); 6646141cc406Sopenharmony_ci set_MSEL_buff_clear(page, 3); 6647141cc406Sopenharmony_ci 6648141cc406Sopenharmony_ci ret = do_cmd ( 6649141cc406Sopenharmony_ci s, 1, 0, 6650141cc406Sopenharmony_ci cmd, cmdLen, 6651141cc406Sopenharmony_ci out, outLen, 6652141cc406Sopenharmony_ci NULL, NULL 6653141cc406Sopenharmony_ci ); 6654141cc406Sopenharmony_ci 6655141cc406Sopenharmony_ci DBG (10, "mode_select_buff: finish\n"); 6656141cc406Sopenharmony_ci 6657141cc406Sopenharmony_ci return ret; 6658141cc406Sopenharmony_ci} 6659141cc406Sopenharmony_ci 6660141cc406Sopenharmony_cistatic SANE_Status 6661141cc406Sopenharmony_cimode_select_prepick (struct fujitsu *s) 6662141cc406Sopenharmony_ci{ 6663141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6664141cc406Sopenharmony_ci 6665141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 6666141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 6667141cc406Sopenharmony_ci 6668141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_min_len]; 6669141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_min_len; 6670141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 6671141cc406Sopenharmony_ci 6672141cc406Sopenharmony_ci DBG (10, "mode_select_prepick: start\n"); 6673141cc406Sopenharmony_ci 6674141cc406Sopenharmony_ci if (!s->has_MS_prepick){ 6675141cc406Sopenharmony_ci DBG (10, "mode_select_prepick: unsupported\n"); 6676141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6677141cc406Sopenharmony_ci } 6678141cc406Sopenharmony_ci 6679141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6680141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 6681141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 6682141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 6683141cc406Sopenharmony_ci 6684141cc406Sopenharmony_ci memset(out,0,outLen); 6685141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_prepick); 6686141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_min_len-2); 6687141cc406Sopenharmony_ci 6688141cc406Sopenharmony_ci set_MSEL_prepick(page, s->prepick); 6689141cc406Sopenharmony_ci 6690141cc406Sopenharmony_ci ret = do_cmd ( 6691141cc406Sopenharmony_ci s, 1, 0, 6692141cc406Sopenharmony_ci cmd, cmdLen, 6693141cc406Sopenharmony_ci out, outLen, 6694141cc406Sopenharmony_ci NULL, NULL 6695141cc406Sopenharmony_ci ); 6696141cc406Sopenharmony_ci 6697141cc406Sopenharmony_ci DBG (10, "mode_select_prepick: finish\n"); 6698141cc406Sopenharmony_ci 6699141cc406Sopenharmony_ci return ret; 6700141cc406Sopenharmony_ci} 6701141cc406Sopenharmony_ci 6702141cc406Sopenharmony_cistatic SANE_Status 6703141cc406Sopenharmony_cimode_select_auto (struct fujitsu *s) 6704141cc406Sopenharmony_ci{ 6705141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6706141cc406Sopenharmony_ci 6707141cc406Sopenharmony_ci unsigned char cmd[MODE_SELECT_len]; 6708141cc406Sopenharmony_ci size_t cmdLen = MODE_SELECT_len; 6709141cc406Sopenharmony_ci 6710141cc406Sopenharmony_ci unsigned char out[MSEL_header_len + MSEL_data_min_len]; 6711141cc406Sopenharmony_ci size_t outLen = MSEL_header_len + MSEL_data_min_len; 6712141cc406Sopenharmony_ci unsigned char * page = out+MSEL_header_len; 6713141cc406Sopenharmony_ci 6714141cc406Sopenharmony_ci DBG (10, "mode_select_auto: start\n"); 6715141cc406Sopenharmony_ci 6716141cc406Sopenharmony_ci if(!s->has_MS_auto){ 6717141cc406Sopenharmony_ci DBG (10, "mode_select_auto: unsupported\n"); 6718141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6719141cc406Sopenharmony_ci } 6720141cc406Sopenharmony_ci 6721141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 6722141cc406Sopenharmony_ci set_SCSI_opcode(cmd, MODE_SELECT_code); 6723141cc406Sopenharmony_ci set_MSEL_pf(cmd, 1); 6724141cc406Sopenharmony_ci set_MSEL_xferlen(cmd, outLen); 6725141cc406Sopenharmony_ci 6726141cc406Sopenharmony_ci memset(out,0,outLen); 6727141cc406Sopenharmony_ci set_MSEL_pc(page, MS_pc_auto); 6728141cc406Sopenharmony_ci set_MSEL_page_len(page, MSEL_data_min_len-2); 6729141cc406Sopenharmony_ci 6730141cc406Sopenharmony_ci set_MSEL_overscan(page, s->overscan); 6731141cc406Sopenharmony_ci set_MSEL_ald(page, s->ald || s->hwdeskewcrop); 6732141cc406Sopenharmony_ci set_MSEL_awd(page, s->awd || s->hwdeskewcrop); 6733141cc406Sopenharmony_ci set_MSEL_req_driv_crop(page, s->hwdeskewcrop && (s->swcrop || s->swdeskew)); 6734141cc406Sopenharmony_ci set_MSEL_deskew(page, s->hwdeskewcrop); 6735141cc406Sopenharmony_ci 6736141cc406Sopenharmony_ci ret = do_cmd ( 6737141cc406Sopenharmony_ci s, 1, 0, 6738141cc406Sopenharmony_ci cmd, cmdLen, 6739141cc406Sopenharmony_ci out, outLen, 6740141cc406Sopenharmony_ci NULL, NULL 6741141cc406Sopenharmony_ci ); 6742141cc406Sopenharmony_ci 6743141cc406Sopenharmony_ci DBG (10, "mode_select_auto: finish\n"); 6744141cc406Sopenharmony_ci 6745141cc406Sopenharmony_ci return ret; 6746141cc406Sopenharmony_ci} 6747141cc406Sopenharmony_ci 6748141cc406Sopenharmony_ci 6749141cc406Sopenharmony_ci/* 6750141cc406Sopenharmony_ci * @@ Section 4 - SANE scanning functions 6751141cc406Sopenharmony_ci */ 6752141cc406Sopenharmony_ci/* 6753141cc406Sopenharmony_ci * Called by SANE to retrieve information about the type of data 6754141cc406Sopenharmony_ci * that the current scan will return. 6755141cc406Sopenharmony_ci * 6756141cc406Sopenharmony_ci * From the SANE spec: 6757141cc406Sopenharmony_ci * This function is used to obtain the current scan parameters. The 6758141cc406Sopenharmony_ci * returned parameters are guaranteed to be accurate between the time 6759141cc406Sopenharmony_ci * a scan has been started (sane_start() has been called) and the 6760141cc406Sopenharmony_ci * completion of that request. Outside of that window, the returned 6761141cc406Sopenharmony_ci * values are best-effort estimates of what the parameters will be 6762141cc406Sopenharmony_ci * when sane_start() gets invoked. 6763141cc406Sopenharmony_ci * 6764141cc406Sopenharmony_ci * Calling this function before a scan has actually started allows, 6765141cc406Sopenharmony_ci * for example, to get an estimate of how big the scanned image will 6766141cc406Sopenharmony_ci * be. The parameters passed to this function are the handle h of the 6767141cc406Sopenharmony_ci * device for which the parameters should be obtained and a pointer p 6768141cc406Sopenharmony_ci * to a parameter structure. 6769141cc406Sopenharmony_ci */ 6770141cc406Sopenharmony_ciSANE_Status 6771141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 6772141cc406Sopenharmony_ci{ 6773141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6774141cc406Sopenharmony_ci struct fujitsu *s = (struct fujitsu *) handle; 6775141cc406Sopenharmony_ci 6776141cc406Sopenharmony_ci DBG (10, "sane_get_parameters: start\n"); 6777141cc406Sopenharmony_ci 6778141cc406Sopenharmony_ci /* not started? update param data from user settings */ 6779141cc406Sopenharmony_ci if(!s->started){ 6780141cc406Sopenharmony_ci ret = update_params(s); 6781141cc406Sopenharmony_ci if(ret) 6782141cc406Sopenharmony_ci return ret; 6783141cc406Sopenharmony_ci } 6784141cc406Sopenharmony_ci 6785141cc406Sopenharmony_ci params->format = s->u_params.format; 6786141cc406Sopenharmony_ci params->last_frame = s->u_params.last_frame; 6787141cc406Sopenharmony_ci params->lines = s->u_params.lines; 6788141cc406Sopenharmony_ci params->depth = s->u_params.depth; 6789141cc406Sopenharmony_ci params->pixels_per_line = s->u_params.pixels_per_line; 6790141cc406Sopenharmony_ci params->bytes_per_line = s->u_params.bytes_per_line; 6791141cc406Sopenharmony_ci 6792141cc406Sopenharmony_ci /* we won't know the end until we get to it */ 6793141cc406Sopenharmony_ci if(s->ald && !must_fully_buffer(s)){ 6794141cc406Sopenharmony_ci DBG (15, "sane_get_parameters: hand-scanner mode\n"); 6795141cc406Sopenharmony_ci params->lines = -1; 6796141cc406Sopenharmony_ci } 6797141cc406Sopenharmony_ci 6798141cc406Sopenharmony_ci DBG (10, "sane_get_parameters: finish\n"); 6799141cc406Sopenharmony_ci return ret; 6800141cc406Sopenharmony_ci} 6801141cc406Sopenharmony_ci 6802141cc406Sopenharmony_ci/* set s_params and u_params data based on user settings 6803141cc406Sopenharmony_ci * and scanner capabilities. */ 6804141cc406Sopenharmony_ciSANE_Status 6805141cc406Sopenharmony_ciupdate_params (struct fujitsu * s) 6806141cc406Sopenharmony_ci{ 6807141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6808141cc406Sopenharmony_ci SANE_Parameters * params = &(s->s_params); 6809141cc406Sopenharmony_ci 6810141cc406Sopenharmony_ci DBG (10, "update_params: start\n"); 6811141cc406Sopenharmony_ci 6812141cc406Sopenharmony_ci /* first, we setup s_params to describe the image to the scanner */ 6813141cc406Sopenharmony_ci /* this backend only sends single frame images */ 6814141cc406Sopenharmony_ci params->last_frame = 1; 6815141cc406Sopenharmony_ci 6816141cc406Sopenharmony_ci /* initial ppl from user settings */ 6817141cc406Sopenharmony_ci params->pixels_per_line = s->resolution_x * (s->br_x - s->tl_x) / 1200; 6818141cc406Sopenharmony_ci 6819141cc406Sopenharmony_ci /* some scanners require even number of bytes in each transfer block, 6820141cc406Sopenharmony_ci * so we round to even # of total lines, to ensure last block is even */ 6821141cc406Sopenharmony_ci params->lines = s->resolution_y * (s->br_y - s->tl_y) / 1200; 6822141cc406Sopenharmony_ci params->lines -= params->lines % 2; 6823141cc406Sopenharmony_ci 6824141cc406Sopenharmony_ci if (s->s_mode == MODE_COLOR) { 6825141cc406Sopenharmony_ci params->depth = 8; 6826141cc406Sopenharmony_ci 6827141cc406Sopenharmony_ci /* jpeg requires 8x8 squares */ 6828141cc406Sopenharmony_ci if(s->compress == COMP_JPEG){ 6829141cc406Sopenharmony_ci params->format = SANE_FRAME_JPEG; 6830141cc406Sopenharmony_ci params->pixels_per_line -= params->pixels_per_line % 8; 6831141cc406Sopenharmony_ci params->lines -= params->lines % 8; 6832141cc406Sopenharmony_ci } 6833141cc406Sopenharmony_ci else{ 6834141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; 6835141cc406Sopenharmony_ci params->pixels_per_line -= params->pixels_per_line 6836141cc406Sopenharmony_ci % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); 6837141cc406Sopenharmony_ci } 6838141cc406Sopenharmony_ci 6839141cc406Sopenharmony_ci params->bytes_per_line = params->pixels_per_line * 3; 6840141cc406Sopenharmony_ci } 6841141cc406Sopenharmony_ci else if (s->s_mode == MODE_GRAYSCALE) { 6842141cc406Sopenharmony_ci params->depth = 8; 6843141cc406Sopenharmony_ci 6844141cc406Sopenharmony_ci /* jpeg requires 8x8 squares */ 6845141cc406Sopenharmony_ci if(s->compress == COMP_JPEG){ 6846141cc406Sopenharmony_ci params->format = SANE_FRAME_JPEG; 6847141cc406Sopenharmony_ci params->pixels_per_line -= params->pixels_per_line % 8; 6848141cc406Sopenharmony_ci params->lines -= params->lines % 8; 6849141cc406Sopenharmony_ci } 6850141cc406Sopenharmony_ci else{ 6851141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 6852141cc406Sopenharmony_ci params->pixels_per_line -= params->pixels_per_line 6853141cc406Sopenharmony_ci % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); 6854141cc406Sopenharmony_ci } 6855141cc406Sopenharmony_ci 6856141cc406Sopenharmony_ci params->bytes_per_line = params->pixels_per_line; 6857141cc406Sopenharmony_ci } 6858141cc406Sopenharmony_ci else { 6859141cc406Sopenharmony_ci params->depth = 1; 6860141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 6861141cc406Sopenharmony_ci params->pixels_per_line -= params->pixels_per_line 6862141cc406Sopenharmony_ci % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); 6863141cc406Sopenharmony_ci params->bytes_per_line = params->pixels_per_line / 8; 6864141cc406Sopenharmony_ci } 6865141cc406Sopenharmony_ci 6866141cc406Sopenharmony_ci DBG(15,"update_params: x: max=%d, page=%d, gpw=%d, res=%d\n", 6867141cc406Sopenharmony_ci s->max_x, s->page_width, get_page_width(s), s->resolution_x); 6868141cc406Sopenharmony_ci 6869141cc406Sopenharmony_ci DBG(15,"update_params: y: max=%d, page=%d, gph=%d, res=%d\n", 6870141cc406Sopenharmony_ci s->max_y, s->page_height, get_page_height(s), s->resolution_y); 6871141cc406Sopenharmony_ci 6872141cc406Sopenharmony_ci DBG(15,"update_params: area: tlx=%d, brx=%d, tly=%d, bry=%d\n", 6873141cc406Sopenharmony_ci s->tl_x, s->br_x, s->tl_y, s->br_y); 6874141cc406Sopenharmony_ci 6875141cc406Sopenharmony_ci DBG(15,"update_params: params: ppl=%d, Bpl=%d, lines=%d\n", 6876141cc406Sopenharmony_ci params->pixels_per_line, params->bytes_per_line, params->lines); 6877141cc406Sopenharmony_ci 6878141cc406Sopenharmony_ci DBG(15,"update_params: params: format=%d, depth=%d, last=%d\n", 6879141cc406Sopenharmony_ci params->format, params->depth, params->last_frame); 6880141cc406Sopenharmony_ci 6881141cc406Sopenharmony_ci /* second, we setup u_params to describe the image to the user */ 6882141cc406Sopenharmony_ci /* use a helper function cause it is called elsewhere */ 6883141cc406Sopenharmony_ci ret = update_u_params(s); 6884141cc406Sopenharmony_ci 6885141cc406Sopenharmony_ci DBG (10, "update_params: finish\n"); 6886141cc406Sopenharmony_ci return ret; 6887141cc406Sopenharmony_ci} 6888141cc406Sopenharmony_ci 6889141cc406Sopenharmony_ci/* set u_param data based on user settings, and s_params */ 6890141cc406Sopenharmony_ciSANE_Status 6891141cc406Sopenharmony_ciupdate_u_params (struct fujitsu * s) 6892141cc406Sopenharmony_ci{ 6893141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6894141cc406Sopenharmony_ci SANE_Parameters * params = &(s->u_params); 6895141cc406Sopenharmony_ci 6896141cc406Sopenharmony_ci DBG (10, "update_u_params: start\n"); 6897141cc406Sopenharmony_ci 6898141cc406Sopenharmony_ci /* for most machines, it is the same, so we just copy */ 6899141cc406Sopenharmony_ci memcpy(&(s->u_params), &(s->s_params), sizeof(SANE_Parameters)); 6900141cc406Sopenharmony_ci 6901141cc406Sopenharmony_ci /* some scanners don't support the user's mode, so params differ */ 6902141cc406Sopenharmony_ci /* but not in jpeg mode. we don't support that. */ 6903141cc406Sopenharmony_ci if(must_downsample(s)){ 6904141cc406Sopenharmony_ci 6905141cc406Sopenharmony_ci /* making gray from a color scan */ 6906141cc406Sopenharmony_ci if (s->u_mode == MODE_GRAYSCALE) { 6907141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 6908141cc406Sopenharmony_ci params->bytes_per_line = params->pixels_per_line; 6909141cc406Sopenharmony_ci } 6910141cc406Sopenharmony_ci /* making binary from a gray or color scan */ 6911141cc406Sopenharmony_ci else if (s->u_mode == MODE_LINEART) { 6912141cc406Sopenharmony_ci params->depth = 1; 6913141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 6914141cc406Sopenharmony_ci params->bytes_per_line = params->pixels_per_line / 8; 6915141cc406Sopenharmony_ci } 6916141cc406Sopenharmony_ci 6917141cc406Sopenharmony_ci DBG(15,"update_u_params: x: max=%d, page=%d, gpw=%d, res=%d\n", 6918141cc406Sopenharmony_ci s->max_x, s->page_width, get_page_width(s), s->resolution_x); 6919141cc406Sopenharmony_ci 6920141cc406Sopenharmony_ci DBG(15,"update_u_params: y: max=%d, page=%d, gph=%d, res=%d\n", 6921141cc406Sopenharmony_ci s->max_y, s->page_height, get_page_height(s), s->resolution_y); 6922141cc406Sopenharmony_ci 6923141cc406Sopenharmony_ci DBG(15,"update_u_params: area: tlx=%d, brx=%d, tly=%d, bry=%d\n", 6924141cc406Sopenharmony_ci s->tl_x, s->br_x, s->tl_y, s->br_y); 6925141cc406Sopenharmony_ci 6926141cc406Sopenharmony_ci DBG(15,"update_u_params: params: ppl=%d, Bpl=%d, lines=%d\n", 6927141cc406Sopenharmony_ci params->pixels_per_line, params->bytes_per_line, params->lines); 6928141cc406Sopenharmony_ci 6929141cc406Sopenharmony_ci DBG(15,"update_u_params: params: format=%d, depth=%d, last=%d\n", 6930141cc406Sopenharmony_ci params->format, params->depth, params->last_frame); 6931141cc406Sopenharmony_ci } 6932141cc406Sopenharmony_ci 6933141cc406Sopenharmony_ci DBG (10, "update_u_params: finish\n"); 6934141cc406Sopenharmony_ci return ret; 6935141cc406Sopenharmony_ci} 6936141cc406Sopenharmony_ci 6937141cc406Sopenharmony_ci/* 6938141cc406Sopenharmony_ci * Called by SANE when a page acquisition operation is to be started. 6939141cc406Sopenharmony_ci * commands: scanner control (lampon), send (lut), send (dither), 6940141cc406Sopenharmony_ci * set window, object pos, and scan 6941141cc406Sopenharmony_ci * 6942141cc406Sopenharmony_ci * this will be called between sides of a duplex scan, 6943141cc406Sopenharmony_ci * and at the start of each page of an adf batch. 6944141cc406Sopenharmony_ci * hence, we spend a lot of time playing with s->started, etc. 6945141cc406Sopenharmony_ci */ 6946141cc406Sopenharmony_ciSANE_Status 6947141cc406Sopenharmony_cisane_start (SANE_Handle handle) 6948141cc406Sopenharmony_ci{ 6949141cc406Sopenharmony_ci struct fujitsu *s = handle; 6950141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 6951141cc406Sopenharmony_ci 6952141cc406Sopenharmony_ci DBG (10, "sane_start: start\n"); 6953141cc406Sopenharmony_ci DBG (15, "started=%d, side=%d, source=%d\n", s->started, s->side, s->source); 6954141cc406Sopenharmony_ci 6955141cc406Sopenharmony_ci /* undo any prior sane_cancel calls */ 6956141cc406Sopenharmony_ci s->cancelled=0; 6957141cc406Sopenharmony_ci 6958141cc406Sopenharmony_ci /* protect this block from sane_cancel */ 6959141cc406Sopenharmony_ci s->reading=1; 6960141cc406Sopenharmony_ci 6961141cc406Sopenharmony_ci /* not finished with current side, error */ 6962141cc406Sopenharmony_ci if (s->started && !s->eof_tx[s->side]) { 6963141cc406Sopenharmony_ci DBG(5,"sane_start: previous transfer not finished?"); 6964141cc406Sopenharmony_ci ret = SANE_STATUS_INVAL; 6965141cc406Sopenharmony_ci goto errors; 6966141cc406Sopenharmony_ci } 6967141cc406Sopenharmony_ci 6968141cc406Sopenharmony_ci /* low mem mode messes up the side marker, reset it */ 6969141cc406Sopenharmony_ci if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) 6970141cc406Sopenharmony_ci && s->low_mem && s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK] 6971141cc406Sopenharmony_ci ){ 6972141cc406Sopenharmony_ci s->side = SIDE_BACK; 6973141cc406Sopenharmony_ci } 6974141cc406Sopenharmony_ci 6975141cc406Sopenharmony_ci /* batch start? initialize struct and scanner */ 6976141cc406Sopenharmony_ci if(!s->started){ 6977141cc406Sopenharmony_ci 6978141cc406Sopenharmony_ci /* load side marker */ 6979141cc406Sopenharmony_ci if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){ 6980141cc406Sopenharmony_ci s->side = SIDE_BACK; 6981141cc406Sopenharmony_ci } 6982141cc406Sopenharmony_ci else{ 6983141cc406Sopenharmony_ci s->side = SIDE_FRONT; 6984141cc406Sopenharmony_ci } 6985141cc406Sopenharmony_ci 6986141cc406Sopenharmony_ci /* load our own private copy of scan params */ 6987141cc406Sopenharmony_ci ret = update_params(s); 6988141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 6989141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot update params\n"); 6990141cc406Sopenharmony_ci goto errors; 6991141cc406Sopenharmony_ci } 6992141cc406Sopenharmony_ci 6993141cc406Sopenharmony_ci /* switch source */ 6994141cc406Sopenharmony_ci if(s->source == SOURCE_FLATBED){ 6995141cc406Sopenharmony_ci ret = scanner_control(s, SC_function_fb); 6996141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 6997141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot control fb, ignoring\n"); 6998141cc406Sopenharmony_ci } 6999141cc406Sopenharmony_ci } 7000141cc406Sopenharmony_ci else if(s->source == SOURCE_CARD_FRONT || s->source == SOURCE_CARD_BACK || s->source == SOURCE_CARD_DUPLEX){ 7001141cc406Sopenharmony_ci ret = scanner_control(s, SC_function_rpath); 7002141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7003141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot control rp, ignoring\n"); 7004141cc406Sopenharmony_ci } 7005141cc406Sopenharmony_ci } 7006141cc406Sopenharmony_ci else{ 7007141cc406Sopenharmony_ci ret = scanner_control(s, SC_function_adf); 7008141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7009141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot control ADF, ignoring\n"); 7010141cc406Sopenharmony_ci } 7011141cc406Sopenharmony_ci } 7012141cc406Sopenharmony_ci 7013141cc406Sopenharmony_ci /* required for hi res scans on iX500? */ 7014141cc406Sopenharmony_ci ret = diag_preread(s); 7015141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7016141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot diag_preread %d\n", ret); 7017141cc406Sopenharmony_ci 7018141cc406Sopenharmony_ci /* enable overscan/auto detection */ 7019141cc406Sopenharmony_ci ret = mode_select_auto(s); 7020141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7021141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot mode_select_auto %d\n", ret); 7022141cc406Sopenharmony_ci 7023141cc406Sopenharmony_ci /* enable double feed detection */ 7024141cc406Sopenharmony_ci ret = mode_select_df(s); 7025141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7026141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot mode_select_df %d\n", ret); 7027141cc406Sopenharmony_ci 7028141cc406Sopenharmony_ci /* enable background color setting */ 7029141cc406Sopenharmony_ci ret = mode_select_bg(s); 7030141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7031141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot mode_select_bg %d\n", ret); 7032141cc406Sopenharmony_ci 7033141cc406Sopenharmony_ci /* enable dropout color setting */ 7034141cc406Sopenharmony_ci ret = mode_select_dropout(s); 7035141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7036141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot mode_select_dropout %d\n", ret); 7037141cc406Sopenharmony_ci 7038141cc406Sopenharmony_ci /* enable buffering setting */ 7039141cc406Sopenharmony_ci ret = mode_select_buff(s); 7040141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7041141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot mode_select_buff %d\n", ret); 7042141cc406Sopenharmony_ci 7043141cc406Sopenharmony_ci /* enable prepick setting */ 7044141cc406Sopenharmony_ci ret = mode_select_prepick(s); 7045141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7046141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot mode_select_prepick %d\n", ret); 7047141cc406Sopenharmony_ci 7048141cc406Sopenharmony_ci /* send endorser config */ 7049141cc406Sopenharmony_ci ret = send_endorser(s); 7050141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7051141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot send_endorser %d\n", ret); 7052141cc406Sopenharmony_ci 7053141cc406Sopenharmony_ci /* set window command */ 7054141cc406Sopenharmony_ci ret = set_window(s); 7055141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7056141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot set window\n"); 7057141cc406Sopenharmony_ci goto errors; 7058141cc406Sopenharmony_ci } 7059141cc406Sopenharmony_ci 7060141cc406Sopenharmony_ci /* send lut if set_window said we would */ 7061141cc406Sopenharmony_ci if ( s->window_gamma ){ 7062141cc406Sopenharmony_ci ret = send_lut(s); 7063141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7064141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot send_lut %d\n", ret); 7065141cc406Sopenharmony_ci } 7066141cc406Sopenharmony_ci 7067141cc406Sopenharmony_ci /* some scanners need the q table sent, even when not scanning jpeg */ 7068141cc406Sopenharmony_ci if (s->need_q_table){ 7069141cc406Sopenharmony_ci ret = send_q_table(s); 7070141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7071141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot send_q_table %d\n", ret); 7072141cc406Sopenharmony_ci } 7073141cc406Sopenharmony_ci 7074141cc406Sopenharmony_ci /* start/stop endorser */ 7075141cc406Sopenharmony_ci ret = endorser(s); 7076141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7077141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot start/stop endorser\n"); 7078141cc406Sopenharmony_ci goto errors; 7079141cc406Sopenharmony_ci } 7080141cc406Sopenharmony_ci 7081141cc406Sopenharmony_ci /* turn lamp on */ 7082141cc406Sopenharmony_ci ret = scanner_control(s, SC_function_lamp_on); 7083141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7084141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: cannot start lamp, ignoring\n"); 7085141cc406Sopenharmony_ci } 7086141cc406Sopenharmony_ci 7087141cc406Sopenharmony_ci /* iX500 errors if op is called with no paper 7088141cc406Sopenharmony_ci * at the beginning of a batch, so we check */ 7089141cc406Sopenharmony_ci if(s->hopper_before_op && s->source != SOURCE_FLATBED){ 7090141cc406Sopenharmony_ci ret = get_hardware_status(s,0); 7091141cc406Sopenharmony_ci if(!s->hw_hopper){ 7092141cc406Sopenharmony_ci ret = SANE_STATUS_NO_DOCS; 7093141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: hopper empty\n"); 7094141cc406Sopenharmony_ci goto errors; 7095141cc406Sopenharmony_ci } 7096141cc406Sopenharmony_ci } 7097141cc406Sopenharmony_ci } 7098141cc406Sopenharmony_ci /* if already running, duplex needs to switch sides */ 7099141cc406Sopenharmony_ci else if(s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX){ 7100141cc406Sopenharmony_ci s->side = !s->side; 7101141cc406Sopenharmony_ci } 7102141cc406Sopenharmony_ci 7103141cc406Sopenharmony_ci /* set clean defaults with new sheet of paper */ 7104141cc406Sopenharmony_ci /* don't reset the transfer vars on backside of duplex page */ 7105141cc406Sopenharmony_ci /* otherwise buffered back page will be lost */ 7106141cc406Sopenharmony_ci /* ingest paper with adf (no-op for fb) */ 7107141cc406Sopenharmony_ci /* don't call object pos or scan on back side of duplex scan */ 7108141cc406Sopenharmony_ci if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){ 7109141cc406Sopenharmony_ci 7110141cc406Sopenharmony_ci s->bytes_rx[0]=0; 7111141cc406Sopenharmony_ci s->bytes_rx[1]=0; 7112141cc406Sopenharmony_ci s->lines_rx[0]=0; 7113141cc406Sopenharmony_ci s->lines_rx[1]=0; 7114141cc406Sopenharmony_ci s->eof_rx[0]=0; 7115141cc406Sopenharmony_ci s->eof_rx[1]=0; 7116141cc406Sopenharmony_ci s->ili_rx[0]=0; 7117141cc406Sopenharmony_ci s->ili_rx[1]=0; 7118141cc406Sopenharmony_ci s->eom_rx=0; 7119141cc406Sopenharmony_ci 7120141cc406Sopenharmony_ci s->bytes_tx[0]=0; 7121141cc406Sopenharmony_ci s->bytes_tx[1]=0; 7122141cc406Sopenharmony_ci s->eof_tx[0]=0; 7123141cc406Sopenharmony_ci s->eof_tx[1]=0; 7124141cc406Sopenharmony_ci 7125141cc406Sopenharmony_ci s->buff_rx[0]=0; 7126141cc406Sopenharmony_ci s->buff_rx[1]=0; 7127141cc406Sopenharmony_ci s->buff_tx[0]=0; 7128141cc406Sopenharmony_ci s->buff_tx[1]=0; 7129141cc406Sopenharmony_ci 7130141cc406Sopenharmony_ci /* reset jpeg just in case... */ 7131141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_NONE; 7132141cc406Sopenharmony_ci s->jpeg_ff_offset = -1; 7133141cc406Sopenharmony_ci s->jpeg_front_rst = 0; 7134141cc406Sopenharmony_ci s->jpeg_back_rst = 0; 7135141cc406Sopenharmony_ci 7136141cc406Sopenharmony_ci ret = object_position (s, OP_Feed); 7137141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7138141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot load page\n"); 7139141cc406Sopenharmony_ci goto errors; 7140141cc406Sopenharmony_ci } 7141141cc406Sopenharmony_ci 7142141cc406Sopenharmony_ci ret = start_scan (s); 7143141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7144141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot start_scan\n"); 7145141cc406Sopenharmony_ci goto errors; 7146141cc406Sopenharmony_ci } 7147141cc406Sopenharmony_ci 7148141cc406Sopenharmony_ci /* try to read scan size from scanner */ 7149141cc406Sopenharmony_ci ret = get_pixelsize(s,0); 7150141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7151141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot get pixelsize\n"); 7152141cc406Sopenharmony_ci goto errors; 7153141cc406Sopenharmony_ci } 7154141cc406Sopenharmony_ci 7155141cc406Sopenharmony_ci /* store the number of front bytes */ 7156141cc406Sopenharmony_ci if ( s->source != SOURCE_ADF_BACK && s->source != SOURCE_CARD_BACK ){ 7157141cc406Sopenharmony_ci s->bytes_tot[SIDE_FRONT] = s->s_params.bytes_per_line * s->s_params.lines; 7158141cc406Sopenharmony_ci s->buff_tot[SIDE_FRONT] = s->buffer_size; 7159141cc406Sopenharmony_ci 7160141cc406Sopenharmony_ci /* the front buffer is normally very small, but some scanners or 7161141cc406Sopenharmony_ci * option combinations can't handle it, so we make a big one */ 7162141cc406Sopenharmony_ci if( 7163141cc406Sopenharmony_ci (s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091) 7164141cc406Sopenharmony_ci || must_fully_buffer(s) 7165141cc406Sopenharmony_ci ){ 7166141cc406Sopenharmony_ci s->buff_tot[SIDE_FRONT] = s->bytes_tot[SIDE_FRONT]; 7167141cc406Sopenharmony_ci } 7168141cc406Sopenharmony_ci } 7169141cc406Sopenharmony_ci else{ 7170141cc406Sopenharmony_ci s->bytes_tot[SIDE_FRONT] = 0; 7171141cc406Sopenharmony_ci s->buff_tot[SIDE_FRONT] = 0; 7172141cc406Sopenharmony_ci } 7173141cc406Sopenharmony_ci 7174141cc406Sopenharmony_ci /* store the number of back bytes */ 7175141cc406Sopenharmony_ci if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK 7176141cc406Sopenharmony_ci || s->source == SOURCE_CARD_DUPLEX || s->source == SOURCE_CARD_BACK ){ 7177141cc406Sopenharmony_ci s->bytes_tot[SIDE_BACK] = s->s_params.bytes_per_line * s->s_params.lines; 7178141cc406Sopenharmony_ci s->buff_tot[SIDE_BACK] = s->bytes_tot[SIDE_BACK]; 7179141cc406Sopenharmony_ci 7180141cc406Sopenharmony_ci /* the back buffer is normally very large, but some scanners or 7181141cc406Sopenharmony_ci * option combinations don't need it, so we make a small one */ 7182141cc406Sopenharmony_ci if(s->low_mem || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK 7183141cc406Sopenharmony_ci || s->duplex_interlace == DUPLEX_INTERLACE_NONE) 7184141cc406Sopenharmony_ci s->buff_tot[SIDE_BACK] = s->buffer_size; 7185141cc406Sopenharmony_ci } 7186141cc406Sopenharmony_ci else{ 7187141cc406Sopenharmony_ci s->bytes_tot[SIDE_BACK] = 0; 7188141cc406Sopenharmony_ci s->buff_tot[SIDE_BACK] = 0; 7189141cc406Sopenharmony_ci } 7190141cc406Sopenharmony_ci 7191141cc406Sopenharmony_ci /* first page of batch */ 7192141cc406Sopenharmony_ci /* make large buffer to hold the images */ 7193141cc406Sopenharmony_ci /* and set started flag */ 7194141cc406Sopenharmony_ci if(!s->started){ 7195141cc406Sopenharmony_ci ret = setup_buffers(s); 7196141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7197141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot load buffers\n"); 7198141cc406Sopenharmony_ci goto errors; 7199141cc406Sopenharmony_ci } 7200141cc406Sopenharmony_ci 7201141cc406Sopenharmony_ci s->started=1; 7202141cc406Sopenharmony_ci } 7203141cc406Sopenharmony_ci } 7204141cc406Sopenharmony_ci else{ 7205141cc406Sopenharmony_ci /* try to read scan size from scanner */ 7206141cc406Sopenharmony_ci ret = get_pixelsize(s,0); 7207141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7208141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot get pixelsize\n"); 7209141cc406Sopenharmony_ci goto errors; 7210141cc406Sopenharmony_ci } 7211141cc406Sopenharmony_ci } 7212141cc406Sopenharmony_ci 7213141cc406Sopenharmony_ci DBG (15, "started=%d, side=%d, source=%d\n", s->started, s->side, s->source); 7214141cc406Sopenharmony_ci 7215141cc406Sopenharmony_ci /* certain options require the entire image to 7216141cc406Sopenharmony_ci * be collected from the scanner before we can 7217141cc406Sopenharmony_ci * tell the user the size of the image. the sane 7218141cc406Sopenharmony_ci * API has no way to inform the frontend of this, 7219141cc406Sopenharmony_ci * so we block and buffer. yuck */ 7220141cc406Sopenharmony_ci if( must_fully_buffer(s) ){ 7221141cc406Sopenharmony_ci 7222141cc406Sopenharmony_ci /* get image */ 7223141cc406Sopenharmony_ci while(!s->eof_rx[s->side] && !ret){ 7224141cc406Sopenharmony_ci SANE_Int len = 0; 7225141cc406Sopenharmony_ci ret = sane_read((SANE_Handle)s, NULL, 0, &len); 7226141cc406Sopenharmony_ci } 7227141cc406Sopenharmony_ci 7228141cc406Sopenharmony_ci /* check for errors */ 7229141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7230141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot buffer image\n"); 7231141cc406Sopenharmony_ci goto errors; 7232141cc406Sopenharmony_ci } 7233141cc406Sopenharmony_ci 7234141cc406Sopenharmony_ci DBG (5, "sane_start: OK: done buffering\n"); 7235141cc406Sopenharmony_ci 7236141cc406Sopenharmony_ci /* hardware deskew will tell image size after transfer */ 7237141cc406Sopenharmony_ci ret = get_pixelsize(s,1); 7238141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 7239141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: cannot get final pixelsize\n"); 7240141cc406Sopenharmony_ci goto errors; 7241141cc406Sopenharmony_ci } 7242141cc406Sopenharmony_ci 7243141cc406Sopenharmony_ci /* finished buffering, adjust image as required */ 7244141cc406Sopenharmony_ci if(s->swdeskew && (!s->hwdeskewcrop || s->req_driv_crop)){ 7245141cc406Sopenharmony_ci buffer_deskew(s,s->side); 7246141cc406Sopenharmony_ci } 7247141cc406Sopenharmony_ci if(s->swcrop && (!s->hwdeskewcrop || s->req_driv_crop)){ 7248141cc406Sopenharmony_ci buffer_crop(s,s->side); 7249141cc406Sopenharmony_ci } 7250141cc406Sopenharmony_ci if(s->swdespeck){ 7251141cc406Sopenharmony_ci buffer_despeck(s,s->side); 7252141cc406Sopenharmony_ci } 7253141cc406Sopenharmony_ci if(s->swskip){ 7254141cc406Sopenharmony_ci /* Skipping means throwing out this image. 7255141cc406Sopenharmony_ci * Pretend the user read the whole thing 7256141cc406Sopenharmony_ci * and call sane_start again. 7257141cc406Sopenharmony_ci * This assumes we are running in batch mode. */ 7258141cc406Sopenharmony_ci if(buffer_isblank(s,s->side)){ 7259141cc406Sopenharmony_ci s->bytes_tx[s->side] = s->bytes_rx[s->side]; 7260141cc406Sopenharmony_ci s->eof_tx[s->side] = 1; 7261141cc406Sopenharmony_ci return sane_start(handle); 7262141cc406Sopenharmony_ci } 7263141cc406Sopenharmony_ci } 7264141cc406Sopenharmony_ci 7265141cc406Sopenharmony_ci } 7266141cc406Sopenharmony_ci 7267141cc406Sopenharmony_ci /* check if user cancelled during this start */ 7268141cc406Sopenharmony_ci ret = check_for_cancel(s); 7269141cc406Sopenharmony_ci 7270141cc406Sopenharmony_ci /* unprotect this block from sane_cancel */ 7271141cc406Sopenharmony_ci s->reading=0; 7272141cc406Sopenharmony_ci 7273141cc406Sopenharmony_ci DBG (10, "sane_start: finish %d\n", ret); 7274141cc406Sopenharmony_ci return ret; 7275141cc406Sopenharmony_ci 7276141cc406Sopenharmony_ci errors: 7277141cc406Sopenharmony_ci DBG (10, "sane_start: error %d\n", ret); 7278141cc406Sopenharmony_ci 7279141cc406Sopenharmony_ci /* if we are started, but something went wrong, 7280141cc406Sopenharmony_ci * chances are there is image data inside scanner, 7281141cc406Sopenharmony_ci * which should be discarded via cancel command */ 7282141cc406Sopenharmony_ci if(s->started){ 7283141cc406Sopenharmony_ci s->cancelled = 1; 7284141cc406Sopenharmony_ci check_for_cancel(s); 7285141cc406Sopenharmony_ci } 7286141cc406Sopenharmony_ci 7287141cc406Sopenharmony_ci s->started = 0; 7288141cc406Sopenharmony_ci s->cancelled = 0; 7289141cc406Sopenharmony_ci s->reading = 0; 7290141cc406Sopenharmony_ci return ret; 7291141cc406Sopenharmony_ci} 7292141cc406Sopenharmony_ci 7293141cc406Sopenharmony_cistatic SANE_Status 7294141cc406Sopenharmony_ciendorser(struct fujitsu *s) 7295141cc406Sopenharmony_ci{ 7296141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 7297141cc406Sopenharmony_ci 7298141cc406Sopenharmony_ci unsigned char cmd[ENDORSER_len]; 7299141cc406Sopenharmony_ci size_t cmdLen = ENDORSER_len; 7300141cc406Sopenharmony_ci 7301141cc406Sopenharmony_ci unsigned char out[ED_max_len]; 7302141cc406Sopenharmony_ci size_t outLen = ED_max_len; 7303141cc406Sopenharmony_ci 7304141cc406Sopenharmony_ci DBG (10, "endorser: start\n"); 7305141cc406Sopenharmony_ci 7306141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 7307141cc406Sopenharmony_ci set_SCSI_opcode(cmd, ENDORSER_code); 7308141cc406Sopenharmony_ci 7309141cc406Sopenharmony_ci memset(out,0,outLen); 7310141cc406Sopenharmony_ci 7311141cc406Sopenharmony_ci if (s->has_endorser_f || s->has_endorser_b){ 7312141cc406Sopenharmony_ci 7313141cc406Sopenharmony_ci /*fi-5900 front side uses 0x80, assume all others*/ 7314141cc406Sopenharmony_ci if(s->u_endorser_side == ED_front){ 7315141cc406Sopenharmony_ci set_ED_endorser_data_id(out,0x80); 7316141cc406Sopenharmony_ci } 7317141cc406Sopenharmony_ci else{ 7318141cc406Sopenharmony_ci set_ED_endorser_data_id(out,0); 7319141cc406Sopenharmony_ci } 7320141cc406Sopenharmony_ci 7321141cc406Sopenharmony_ci if(s->u_endorser){ 7322141cc406Sopenharmony_ci set_ED_stop(out,ED_start); 7323141cc406Sopenharmony_ci } 7324141cc406Sopenharmony_ci else{ 7325141cc406Sopenharmony_ci set_ED_stop(out,ED_stop); 7326141cc406Sopenharmony_ci } 7327141cc406Sopenharmony_ci 7328141cc406Sopenharmony_ci set_ED_side(out,s->u_endorser_side); 7329141cc406Sopenharmony_ci 7330141cc406Sopenharmony_ci if(s->u_endorser_bits == 24){ 7331141cc406Sopenharmony_ci set_ED_lap24(out,ED_lap_24bit); 7332141cc406Sopenharmony_ci set_ED_initial_count_24(out,s->u_endorser_val); 7333141cc406Sopenharmony_ci } 7334141cc406Sopenharmony_ci 7335141cc406Sopenharmony_ci else{ 7336141cc406Sopenharmony_ci outLen = ED_min_len; 7337141cc406Sopenharmony_ci set_ED_lap24(out,ED_lap_16bit); 7338141cc406Sopenharmony_ci set_ED_initial_count_16(out,s->u_endorser_val); 7339141cc406Sopenharmony_ci } 7340141cc406Sopenharmony_ci 7341141cc406Sopenharmony_ci set_E_xferlen(cmd, outLen); 7342141cc406Sopenharmony_ci ret = do_cmd ( 7343141cc406Sopenharmony_ci s, 1, 0, 7344141cc406Sopenharmony_ci cmd, cmdLen, 7345141cc406Sopenharmony_ci out, outLen, 7346141cc406Sopenharmony_ci NULL, NULL 7347141cc406Sopenharmony_ci ); 7348141cc406Sopenharmony_ci } 7349141cc406Sopenharmony_ci 7350141cc406Sopenharmony_ci DBG (10, "endorser: finish %d\n", ret); 7351141cc406Sopenharmony_ci 7352141cc406Sopenharmony_ci return ret; 7353141cc406Sopenharmony_ci} 7354141cc406Sopenharmony_ci 7355141cc406Sopenharmony_cistatic SANE_Status 7356141cc406Sopenharmony_ciscanner_control (struct fujitsu *s, int function) 7357141cc406Sopenharmony_ci{ 7358141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 7359141cc406Sopenharmony_ci int tries = 0; 7360141cc406Sopenharmony_ci 7361141cc406Sopenharmony_ci unsigned char cmd[SCANNER_CONTROL_len]; 7362141cc406Sopenharmony_ci size_t cmdLen = SCANNER_CONTROL_len; 7363141cc406Sopenharmony_ci 7364141cc406Sopenharmony_ci DBG (10, "scanner_control: start\n"); 7365141cc406Sopenharmony_ci 7366141cc406Sopenharmony_ci if(s->has_cmd_scanner_ctl){ 7367141cc406Sopenharmony_ci 7368141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 7369141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SCANNER_CONTROL_code); 7370141cc406Sopenharmony_ci set_SC_function_1 (cmd, function); 7371141cc406Sopenharmony_ci set_SC_function_2 (cmd, function); 7372141cc406Sopenharmony_ci 7373141cc406Sopenharmony_ci DBG (15, "scanner_control: function %d\n",function); 7374141cc406Sopenharmony_ci 7375141cc406Sopenharmony_ci /* don't really need to ask for adf if that's the only option */ 7376141cc406Sopenharmony_ci /* doing so causes the 3091 to complain */ 7377141cc406Sopenharmony_ci if(function == SC_function_adf && !s->has_flatbed && !s->has_return_path){ 7378141cc406Sopenharmony_ci DBG (10, "scanner_control: adf function not required\n"); 7379141cc406Sopenharmony_ci return ret; 7380141cc406Sopenharmony_ci } 7381141cc406Sopenharmony_ci 7382141cc406Sopenharmony_ci /* extremely long retry period */ 7383141cc406Sopenharmony_ci while(tries++ < 120){ 7384141cc406Sopenharmony_ci 7385141cc406Sopenharmony_ci ret = do_cmd ( 7386141cc406Sopenharmony_ci s, 1, 0, 7387141cc406Sopenharmony_ci cmd, cmdLen, 7388141cc406Sopenharmony_ci NULL, 0, 7389141cc406Sopenharmony_ci NULL, NULL 7390141cc406Sopenharmony_ci ); 7391141cc406Sopenharmony_ci 7392141cc406Sopenharmony_ci if(ret == SANE_STATUS_GOOD || function != SC_function_lamp_on){ 7393141cc406Sopenharmony_ci break; 7394141cc406Sopenharmony_ci } 7395141cc406Sopenharmony_ci 7396141cc406Sopenharmony_ci usleep(500000); 7397141cc406Sopenharmony_ci } 7398141cc406Sopenharmony_ci 7399141cc406Sopenharmony_ci if(ret == SANE_STATUS_GOOD){ 7400141cc406Sopenharmony_ci DBG (15, "scanner_control: success, tries %d, ret %d\n",tries,ret); 7401141cc406Sopenharmony_ci } 7402141cc406Sopenharmony_ci else{ 7403141cc406Sopenharmony_ci DBG (5, "scanner_control: error, tries %d, ret %d\n",tries,ret); 7404141cc406Sopenharmony_ci } 7405141cc406Sopenharmony_ci } 7406141cc406Sopenharmony_ci 7407141cc406Sopenharmony_ci DBG (10, "scanner_control: finish\n"); 7408141cc406Sopenharmony_ci 7409141cc406Sopenharmony_ci return ret; 7410141cc406Sopenharmony_ci} 7411141cc406Sopenharmony_ci 7412141cc406Sopenharmony_cistatic SANE_Status 7413141cc406Sopenharmony_ciscanner_control_ric (struct fujitsu *s, int bytes, int side) 7414141cc406Sopenharmony_ci{ 7415141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 7416141cc406Sopenharmony_ci int tries = 0; 7417141cc406Sopenharmony_ci 7418141cc406Sopenharmony_ci unsigned char cmd[SCANNER_CONTROL_len]; 7419141cc406Sopenharmony_ci size_t cmdLen = SCANNER_CONTROL_len; 7420141cc406Sopenharmony_ci 7421141cc406Sopenharmony_ci DBG (10, "scanner_control_ric: start\n"); 7422141cc406Sopenharmony_ci 7423141cc406Sopenharmony_ci if(s->has_cmd_scanner_ctl){ 7424141cc406Sopenharmony_ci 7425141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 7426141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SCANNER_CONTROL_code); 7427141cc406Sopenharmony_ci 7428141cc406Sopenharmony_ci set_SC_ric(cmd, 1); 7429141cc406Sopenharmony_ci if (side == SIDE_BACK) { 7430141cc406Sopenharmony_ci set_SC_ric_dtq(cmd, WD_wid_back); 7431141cc406Sopenharmony_ci } 7432141cc406Sopenharmony_ci else{ 7433141cc406Sopenharmony_ci set_SC_ric_dtq(cmd, WD_wid_front); 7434141cc406Sopenharmony_ci } 7435141cc406Sopenharmony_ci 7436141cc406Sopenharmony_ci set_SC_ric_len(cmd, bytes); 7437141cc406Sopenharmony_ci 7438141cc406Sopenharmony_ci DBG (15, "scanner_control_ric: %d %d\n",bytes,side); 7439141cc406Sopenharmony_ci 7440141cc406Sopenharmony_ci /* extremely long retry period */ 7441141cc406Sopenharmony_ci while(tries++ < 120){ 7442141cc406Sopenharmony_ci 7443141cc406Sopenharmony_ci ret = do_cmd ( 7444141cc406Sopenharmony_ci s, 1, 0, 7445141cc406Sopenharmony_ci cmd, cmdLen, 7446141cc406Sopenharmony_ci NULL, 0, 7447141cc406Sopenharmony_ci NULL, NULL 7448141cc406Sopenharmony_ci ); 7449141cc406Sopenharmony_ci 7450141cc406Sopenharmony_ci if(ret != SANE_STATUS_DEVICE_BUSY){ 7451141cc406Sopenharmony_ci break; 7452141cc406Sopenharmony_ci } 7453141cc406Sopenharmony_ci 7454141cc406Sopenharmony_ci usleep(500000); 7455141cc406Sopenharmony_ci } 7456141cc406Sopenharmony_ci 7457141cc406Sopenharmony_ci if(ret == SANE_STATUS_GOOD){ 7458141cc406Sopenharmony_ci DBG (15, "scanner_control_ric: success, tries %d, ret %d\n",tries,ret); 7459141cc406Sopenharmony_ci } 7460141cc406Sopenharmony_ci /* some errors pass thru unchanged */ 7461141cc406Sopenharmony_ci else if(ret == SANE_STATUS_CANCELLED || ret == SANE_STATUS_JAMMED 7462141cc406Sopenharmony_ci || ret == SANE_STATUS_NO_DOCS || ret == SANE_STATUS_COVER_OPEN 7463141cc406Sopenharmony_ci ){ 7464141cc406Sopenharmony_ci DBG (5, "scanner_control_ric: error, tries %d, ret %d\n",tries,ret); 7465141cc406Sopenharmony_ci } 7466141cc406Sopenharmony_ci /* other errors are ignored, since scanner may not support RIC */ 7467141cc406Sopenharmony_ci else{ 7468141cc406Sopenharmony_ci DBG (5, "scanner_control_ric: ignoring, tries %d, ret %d\n",tries,ret); 7469141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 7470141cc406Sopenharmony_ci } 7471141cc406Sopenharmony_ci } 7472141cc406Sopenharmony_ci 7473141cc406Sopenharmony_ci DBG (10, "scanner_control_ric: finish\n"); 7474141cc406Sopenharmony_ci 7475141cc406Sopenharmony_ci return ret; 7476141cc406Sopenharmony_ci} 7477141cc406Sopenharmony_ci 7478141cc406Sopenharmony_ci/* 7479141cc406Sopenharmony_ci * callocs a buffer to hold the scan data 7480141cc406Sopenharmony_ci */ 7481141cc406Sopenharmony_cistatic SANE_Status 7482141cc406Sopenharmony_cisetup_buffers (struct fujitsu *s) 7483141cc406Sopenharmony_ci{ 7484141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 7485141cc406Sopenharmony_ci int side; 7486141cc406Sopenharmony_ci 7487141cc406Sopenharmony_ci DBG (10, "setup_buffers: start\n"); 7488141cc406Sopenharmony_ci 7489141cc406Sopenharmony_ci for(side=0;side<2;side++){ 7490141cc406Sopenharmony_ci 7491141cc406Sopenharmony_ci /* free old mem */ 7492141cc406Sopenharmony_ci if (s->buffers[side]) { 7493141cc406Sopenharmony_ci DBG (15, "setup_buffers: free buffer %d.\n",side); 7494141cc406Sopenharmony_ci free(s->buffers[side]); 7495141cc406Sopenharmony_ci s->buffers[side] = NULL; 7496141cc406Sopenharmony_ci } 7497141cc406Sopenharmony_ci 7498141cc406Sopenharmony_ci if(s->buff_tot[side]){ 7499141cc406Sopenharmony_ci s->buffers[side] = calloc (1,s->buff_tot[side]); 7500141cc406Sopenharmony_ci 7501141cc406Sopenharmony_ci if (!s->buffers[side]) { 7502141cc406Sopenharmony_ci DBG (5, "setup_buffers: Error, no buffer %d.\n",side); 7503141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 7504141cc406Sopenharmony_ci } 7505141cc406Sopenharmony_ci } 7506141cc406Sopenharmony_ci } 7507141cc406Sopenharmony_ci 7508141cc406Sopenharmony_ci DBG (10, "setup_buffers: finish\n"); 7509141cc406Sopenharmony_ci 7510141cc406Sopenharmony_ci return ret; 7511141cc406Sopenharmony_ci} 7512141cc406Sopenharmony_ci 7513141cc406Sopenharmony_ci/* 7514141cc406Sopenharmony_ci * This routine issues a SCSI SET WINDOW command to the scanner, using the 7515141cc406Sopenharmony_ci * values currently in the scanner data structure. 7516141cc406Sopenharmony_ci */ 7517141cc406Sopenharmony_cistatic SANE_Status 7518141cc406Sopenharmony_ciset_window (struct fujitsu *s) 7519141cc406Sopenharmony_ci{ 7520141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 7521141cc406Sopenharmony_ci 7522141cc406Sopenharmony_ci /* The command specifies the number of bytes in the data phase 7523141cc406Sopenharmony_ci * the data phase has a header, followed by 1 or 2 window desc blocks 7524141cc406Sopenharmony_ci * the header specifies the number of bytes in 1 window desc block 7525141cc406Sopenharmony_ci */ 7526141cc406Sopenharmony_ci 7527141cc406Sopenharmony_ci unsigned char cmd[SET_WINDOW_len]; 7528141cc406Sopenharmony_ci size_t cmdLen = SET_WINDOW_len; 7529141cc406Sopenharmony_ci 7530141cc406Sopenharmony_ci /*this is max size, we might send less below*/ 7531141cc406Sopenharmony_ci unsigned char out[SW_header_len + SW_desc_len + SW_desc_len]; 7532141cc406Sopenharmony_ci size_t outLen = SW_header_len + SW_desc_len + SW_desc_len; 7533141cc406Sopenharmony_ci 7534141cc406Sopenharmony_ci unsigned char * header = out; /*header*/ 7535141cc406Sopenharmony_ci unsigned char * desc1 = out + SW_header_len; /*1st desc*/ 7536141cc406Sopenharmony_ci unsigned char * desc2 = out + SW_header_len + SW_desc_len; /*2nd desc*/ 7537141cc406Sopenharmony_ci 7538141cc406Sopenharmony_ci int length = 0; 7539141cc406Sopenharmony_ci 7540141cc406Sopenharmony_ci DBG (10, "set_window: start\n"); 7541141cc406Sopenharmony_ci 7542141cc406Sopenharmony_ci /*build the payload*/ 7543141cc406Sopenharmony_ci memset(out,0,outLen); 7544141cc406Sopenharmony_ci 7545141cc406Sopenharmony_ci /* set window desc size in header */ 7546141cc406Sopenharmony_ci set_WPDB_wdblen(header, SW_desc_len); 7547141cc406Sopenharmony_ci 7548141cc406Sopenharmony_ci /* init the window block */ 7549141cc406Sopenharmony_ci if (s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) { 7550141cc406Sopenharmony_ci set_WD_wid (desc1, WD_wid_back); 7551141cc406Sopenharmony_ci } 7552141cc406Sopenharmony_ci else{ 7553141cc406Sopenharmony_ci set_WD_wid (desc1, WD_wid_front); 7554141cc406Sopenharmony_ci } 7555141cc406Sopenharmony_ci 7556141cc406Sopenharmony_ci set_WD_Xres (desc1, s->resolution_x); 7557141cc406Sopenharmony_ci set_WD_Yres (desc1, s->resolution_y); 7558141cc406Sopenharmony_ci 7559141cc406Sopenharmony_ci set_WD_ULX (desc1, s->tl_x); 7560141cc406Sopenharmony_ci /* low-end scanners ignore paper-size, 7561141cc406Sopenharmony_ci * so we have to center the window ourselves */ 7562141cc406Sopenharmony_ci if(s->cropping_mode == CROP_ABSOLUTE){ 7563141cc406Sopenharmony_ci set_WD_ULX (desc1, s->tl_x + (s->max_x - s->page_width) / 2); 7564141cc406Sopenharmony_ci } 7565141cc406Sopenharmony_ci 7566141cc406Sopenharmony_ci set_WD_ULY (desc1, s->tl_y); 7567141cc406Sopenharmony_ci set_WD_width (desc1, s->s_params.pixels_per_line * 1200/s->resolution_x); 7568141cc406Sopenharmony_ci 7569141cc406Sopenharmony_ci length = s->s_params.lines * 1200/s->resolution_y; 7570141cc406Sopenharmony_ci 7571141cc406Sopenharmony_ci /* stupid trick. 3091/2 require reading extra lines, 7572141cc406Sopenharmony_ci * because they have a gap between R G and B */ 7573141cc406Sopenharmony_ci if(s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ 7574141cc406Sopenharmony_ci length += (s->color_raster_offset+s->green_offset) * 1200/300 * 2; 7575141cc406Sopenharmony_ci DBG(5,"set_window: Increasing length to %d\n",length); 7576141cc406Sopenharmony_ci } 7577141cc406Sopenharmony_ci set_WD_length (desc1, length); 7578141cc406Sopenharmony_ci 7579141cc406Sopenharmony_ci set_WD_brightness (desc1, 0); 7580141cc406Sopenharmony_ci if(s->brightness_steps){ 7581141cc406Sopenharmony_ci /*convert our common -127 to +127 range into HW's range 7582141cc406Sopenharmony_ci *FIXME: this code assumes hardware range of 0-255 */ 7583141cc406Sopenharmony_ci set_WD_brightness (desc1, s->brightness+128); 7584141cc406Sopenharmony_ci } 7585141cc406Sopenharmony_ci 7586141cc406Sopenharmony_ci set_WD_threshold (desc1, s->threshold); 7587141cc406Sopenharmony_ci 7588141cc406Sopenharmony_ci set_WD_contrast (desc1, 0); 7589141cc406Sopenharmony_ci if(s->contrast_steps){ 7590141cc406Sopenharmony_ci /*convert our common -127 to +127 range into HW's range 7591141cc406Sopenharmony_ci *FIXME: this code assumes hardware range of 0-255 */ 7592141cc406Sopenharmony_ci set_WD_contrast (desc1, s->contrast+128); 7593141cc406Sopenharmony_ci } 7594141cc406Sopenharmony_ci 7595141cc406Sopenharmony_ci set_WD_composition (desc1, s->s_mode); 7596141cc406Sopenharmony_ci 7597141cc406Sopenharmony_ci set_WD_bitsperpixel (desc1, s->s_params.depth); 7598141cc406Sopenharmony_ci 7599141cc406Sopenharmony_ci if(s->s_mode == MODE_HALFTONE){ 7600141cc406Sopenharmony_ci set_WD_ht_type(desc1, s->ht_type); 7601141cc406Sopenharmony_ci set_WD_ht_pattern(desc1, s->ht_pattern); 7602141cc406Sopenharmony_ci } 7603141cc406Sopenharmony_ci 7604141cc406Sopenharmony_ci set_WD_rif (desc1, s->rif); 7605141cc406Sopenharmony_ci 7606141cc406Sopenharmony_ci set_WD_compress_type(desc1, COMP_NONE); 7607141cc406Sopenharmony_ci set_WD_compress_arg(desc1, 0); 7608141cc406Sopenharmony_ci 7609141cc406Sopenharmony_ci /* some scanners support jpeg image compression, for color/gs only */ 7610141cc406Sopenharmony_ci if(s->s_params.format == SANE_FRAME_JPEG){ 7611141cc406Sopenharmony_ci set_WD_compress_type(desc1, COMP_JPEG); 7612141cc406Sopenharmony_ci set_WD_compress_arg(desc1, s->compress_arg); 7613141cc406Sopenharmony_ci } 7614141cc406Sopenharmony_ci 7615141cc406Sopenharmony_ci /* the remainder of the block varies based on model and mode, 7616141cc406Sopenharmony_ci * except for gamma and paper size, those are in the same place */ 7617141cc406Sopenharmony_ci 7618141cc406Sopenharmony_ci /* determine if we need to send gamma LUT. 7619141cc406Sopenharmony_ci * send lut if scanner supports it and any of: 7620141cc406Sopenharmony_ci * has no hardware brightness but user changed it 7621141cc406Sopenharmony_ci * has no hardware contrast but user changed it 7622141cc406Sopenharmony_ci * has no internal gamma table */ 7623141cc406Sopenharmony_ci if ( s->num_download_gamma && ( 7624141cc406Sopenharmony_ci (!s->brightness_steps && s->brightness != 0) 7625141cc406Sopenharmony_ci || (!s->contrast_steps && s->contrast != 0 ) 7626141cc406Sopenharmony_ci || !s->num_internal_gamma 7627141cc406Sopenharmony_ci ) ){ 7628141cc406Sopenharmony_ci s->window_gamma = 0x80; 7629141cc406Sopenharmony_ci } 7630141cc406Sopenharmony_ci /* otherwise, use the internal table */ 7631141cc406Sopenharmony_ci else{ 7632141cc406Sopenharmony_ci s->window_gamma = 0; 7633141cc406Sopenharmony_ci } 7634141cc406Sopenharmony_ci 7635141cc406Sopenharmony_ci /*vuid c0*/ 7636141cc406Sopenharmony_ci if(s->has_vuid_3091){ 7637141cc406Sopenharmony_ci set_WD_vendor_id_code (desc1, WD_VUID_3091); 7638141cc406Sopenharmony_ci set_WD_gamma (desc1, s->window_gamma); 7639141cc406Sopenharmony_ci 7640141cc406Sopenharmony_ci if (s->s_mode != MODE_COLOR){ 7641141cc406Sopenharmony_ci switch (s->dropout_color) { 7642141cc406Sopenharmony_ci case COLOR_RED: 7643141cc406Sopenharmony_ci set_WD_lamp_color (desc1, WD_LAMP_RED); 7644141cc406Sopenharmony_ci break; 7645141cc406Sopenharmony_ci case COLOR_GREEN: 7646141cc406Sopenharmony_ci set_WD_lamp_color (desc1, WD_LAMP_GREEN); 7647141cc406Sopenharmony_ci break; 7648141cc406Sopenharmony_ci case COLOR_BLUE: 7649141cc406Sopenharmony_ci set_WD_lamp_color (desc1, WD_LAMP_BLUE); 7650141cc406Sopenharmony_ci break; 7651141cc406Sopenharmony_ci default: 7652141cc406Sopenharmony_ci set_WD_lamp_color (desc1, WD_LAMP_DEFAULT); 7653141cc406Sopenharmony_ci break; 7654141cc406Sopenharmony_ci } 7655141cc406Sopenharmony_ci } 7656141cc406Sopenharmony_ci /*set_WD_quality(desc1,s->quality);*/ 7657141cc406Sopenharmony_ci } 7658141cc406Sopenharmony_ci 7659141cc406Sopenharmony_ci /*vuid c1*/ 7660141cc406Sopenharmony_ci else if(s->s_mode == MODE_COLOR && s->has_vuid_color){ 7661141cc406Sopenharmony_ci set_WD_vendor_id_code (desc1, WD_VUID_COLOR); 7662141cc406Sopenharmony_ci set_WD_gamma (desc1, s->window_gamma); 7663141cc406Sopenharmony_ci 7664141cc406Sopenharmony_ci if(s->color_interlace == COLOR_INTERLACE_RGB){ 7665141cc406Sopenharmony_ci set_WD_scanning_order (desc1, WD_SCAN_ORDER_DOT); 7666141cc406Sopenharmony_ci set_WD_scanning_order_arg (desc1, WD_SCAN_ARG_RGB); 7667141cc406Sopenharmony_ci } 7668141cc406Sopenharmony_ci else if(s->color_interlace == COLOR_INTERLACE_BGR){ 7669141cc406Sopenharmony_ci set_WD_scanning_order (desc1, WD_SCAN_ORDER_DOT); 7670141cc406Sopenharmony_ci set_WD_scanning_order_arg (desc1, WD_SCAN_ARG_BGR); 7671141cc406Sopenharmony_ci } 7672141cc406Sopenharmony_ci else if(s->color_interlace == COLOR_INTERLACE_RRGGBB){ 7673141cc406Sopenharmony_ci set_WD_scanning_order (desc1, WD_SCAN_ORDER_LINE); 7674141cc406Sopenharmony_ci set_WD_scanning_order_arg (desc1, WD_SCAN_ARG_RGB); 7675141cc406Sopenharmony_ci } 7676141cc406Sopenharmony_ci else{ 7677141cc406Sopenharmony_ci DBG (5,"set_window: unknown color interlacing\n"); 7678141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 7679141cc406Sopenharmony_ci } 7680141cc406Sopenharmony_ci 7681141cc406Sopenharmony_ci /*scanner emphasis ranges from 0 to 7f and smoothing from 80 to ff*/ 7682141cc406Sopenharmony_ci /* but we expose them to user as a single linear range smooth->emphasis */ 7683141cc406Sopenharmony_ci /* flip the smooth part over, and tack it onto the upper end of emphasis */ 7684141cc406Sopenharmony_ci if(s->emphasis < 0) 7685141cc406Sopenharmony_ci set_WD_c1_emphasis(desc1,127-s->emphasis); 7686141cc406Sopenharmony_ci else 7687141cc406Sopenharmony_ci set_WD_c1_emphasis(desc1,s->emphasis); 7688141cc406Sopenharmony_ci 7689141cc406Sopenharmony_ci set_WD_c1_mirroring(desc1,s->mirroring); 7690141cc406Sopenharmony_ci 7691141cc406Sopenharmony_ci set_WD_wl_follow(desc1,s->wl_follow); 7692141cc406Sopenharmony_ci } 7693141cc406Sopenharmony_ci 7694141cc406Sopenharmony_ci /*vuid 00*/ 7695141cc406Sopenharmony_ci else if(s->has_vuid_mono){ 7696141cc406Sopenharmony_ci set_WD_vendor_id_code (desc1, WD_VUID_MONO); 7697141cc406Sopenharmony_ci set_WD_gamma (desc1, s->window_gamma); 7698141cc406Sopenharmony_ci 7699141cc406Sopenharmony_ci set_WD_outline(desc1,s->outline); 7700141cc406Sopenharmony_ci 7701141cc406Sopenharmony_ci /*scanner emphasis ranges from 0 to 7f and smoothing from 80 to ff*/ 7702141cc406Sopenharmony_ci /* but we expose them to user as a single linear range smooth->emphasis */ 7703141cc406Sopenharmony_ci /* flip the smooth part over, and tack it onto the upper end of emphasis */ 7704141cc406Sopenharmony_ci if(s->emphasis < 0) 7705141cc406Sopenharmony_ci set_WD_emphasis(desc1,127-s->emphasis); 7706141cc406Sopenharmony_ci else 7707141cc406Sopenharmony_ci set_WD_emphasis(desc1,s->emphasis); 7708141cc406Sopenharmony_ci 7709141cc406Sopenharmony_ci set_WD_separation(desc1,s->separation); 7710141cc406Sopenharmony_ci set_WD_mirroring(desc1,s->mirroring); 7711141cc406Sopenharmony_ci 7712141cc406Sopenharmony_ci if (get_ipc_mode(s) == WD_ipc_SDTC) 7713141cc406Sopenharmony_ci set_WD_variance(desc1,s->variance); 7714141cc406Sopenharmony_ci 7715141cc406Sopenharmony_ci else if (get_ipc_mode(s) == WD_ipc_DTC){ 7716141cc406Sopenharmony_ci set_WD_filtering(desc1,s->bp_filter); 7717141cc406Sopenharmony_ci set_WD_smoothing(desc1,s->smoothing); 7718141cc406Sopenharmony_ci set_WD_gamma_curve(desc1,s->gamma_curve); 7719141cc406Sopenharmony_ci set_WD_threshold_curve(desc1,s->threshold_curve); 7720141cc406Sopenharmony_ci set_WD_noise_removal(desc1,s->noise_removal); 7721141cc406Sopenharmony_ci if(s->noise_removal){ 7722141cc406Sopenharmony_ci set_WD_matrix5x5(desc1,s->matrix_5); 7723141cc406Sopenharmony_ci set_WD_matrix4x4(desc1,s->matrix_4); 7724141cc406Sopenharmony_ci set_WD_matrix3x3(desc1,s->matrix_3); 7725141cc406Sopenharmony_ci set_WD_matrix2x2(desc1,s->matrix_2); 7726141cc406Sopenharmony_ci } 7727141cc406Sopenharmony_ci set_WD_background(desc1,s->threshold_white); 7728141cc406Sopenharmony_ci } 7729141cc406Sopenharmony_ci 7730141cc406Sopenharmony_ci set_WD_wl_follow(desc1,s->wl_follow); 7731141cc406Sopenharmony_ci set_WD_subwindow_list(desc1,0); 7732141cc406Sopenharmony_ci set_WD_ipc_mode(desc1,get_ipc_mode(s)); 7733141cc406Sopenharmony_ci } 7734141cc406Sopenharmony_ci 7735141cc406Sopenharmony_ci else{ 7736141cc406Sopenharmony_ci DBG (5,"set_window: no vuid to send?\n"); 7737141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 7738141cc406Sopenharmony_ci } 7739141cc406Sopenharmony_ci 7740141cc406Sopenharmony_ci /* common to all vuids */ 7741141cc406Sopenharmony_ci if(s->source == SOURCE_FLATBED){ 7742141cc406Sopenharmony_ci set_WD_paper_selection(desc1,WD_paper_SEL_UNDEFINED); 7743141cc406Sopenharmony_ci } 7744141cc406Sopenharmony_ci else{ 7745141cc406Sopenharmony_ci set_WD_paper_selection (desc1, WD_paper_SEL_NON_STANDARD); 7746141cc406Sopenharmony_ci 7747141cc406Sopenharmony_ci /* call helper function, scanner wants lies about paper width */ 7748141cc406Sopenharmony_ci set_WD_paper_width_X (desc1, get_page_width(s)); 7749141cc406Sopenharmony_ci 7750141cc406Sopenharmony_ci /* don't call helper function, scanner wants actual length? */ 7751141cc406Sopenharmony_ci set_WD_paper_length_Y (desc1, s->page_height); 7752141cc406Sopenharmony_ci } 7753141cc406Sopenharmony_ci 7754141cc406Sopenharmony_ci /* when in duplex mode, copy first desc block into second */ 7755141cc406Sopenharmony_ci if (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) { 7756141cc406Sopenharmony_ci memcpy (desc2, desc1, SW_desc_len); 7757141cc406Sopenharmony_ci 7758141cc406Sopenharmony_ci set_WD_wid (desc2, WD_wid_back); 7759141cc406Sopenharmony_ci 7760141cc406Sopenharmony_ci /* FIXME: do we really need these on back of page? */ 7761141cc406Sopenharmony_ci set_WD_paper_selection (desc2, WD_paper_SEL_UNDEFINED); 7762141cc406Sopenharmony_ci set_WD_paper_width_X (desc2, 0); 7763141cc406Sopenharmony_ci set_WD_paper_length_Y (desc2, 0); 7764141cc406Sopenharmony_ci } 7765141cc406Sopenharmony_ci /* output shorter if not using duplex */ 7766141cc406Sopenharmony_ci else{ 7767141cc406Sopenharmony_ci outLen -= SW_desc_len; 7768141cc406Sopenharmony_ci } 7769141cc406Sopenharmony_ci 7770141cc406Sopenharmony_ci /*build the command*/ 7771141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 7772141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SET_WINDOW_code); 7773141cc406Sopenharmony_ci set_SW_xferlen(cmd, outLen); 7774141cc406Sopenharmony_ci 7775141cc406Sopenharmony_ci ret = do_cmd ( 7776141cc406Sopenharmony_ci s, 1, 0, 7777141cc406Sopenharmony_ci cmd, cmdLen, 7778141cc406Sopenharmony_ci out, outLen, 7779141cc406Sopenharmony_ci NULL, NULL 7780141cc406Sopenharmony_ci ); 7781141cc406Sopenharmony_ci 7782141cc406Sopenharmony_ci DBG (10, "set_window: finish\n"); 7783141cc406Sopenharmony_ci 7784141cc406Sopenharmony_ci return ret; 7785141cc406Sopenharmony_ci} 7786141cc406Sopenharmony_ci 7787141cc406Sopenharmony_ci/* update s_params with actual data size scanner reports */ 7788141cc406Sopenharmony_ci/* then copy as required to the u_params to send to user */ 7789141cc406Sopenharmony_cistatic SANE_Status 7790141cc406Sopenharmony_ciget_pixelsize(struct fujitsu *s, int actual) 7791141cc406Sopenharmony_ci{ 7792141cc406Sopenharmony_ci SANE_Status ret; 7793141cc406Sopenharmony_ci 7794141cc406Sopenharmony_ci unsigned char cmd[READ_len]; 7795141cc406Sopenharmony_ci size_t cmdLen = READ_len; 7796141cc406Sopenharmony_ci 7797141cc406Sopenharmony_ci unsigned char in[R_PSIZE_len]; 7798141cc406Sopenharmony_ci size_t inLen = R_PSIZE_len; 7799141cc406Sopenharmony_ci 7800141cc406Sopenharmony_ci DBG (10, "get_pixelsize: start %d\n",actual); 7801141cc406Sopenharmony_ci 7802141cc406Sopenharmony_ci if (!s->has_pixelsize){ 7803141cc406Sopenharmony_ci DBG (10, "get_pixelsize: unsupported\n"); 7804141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7805141cc406Sopenharmony_ci } 7806141cc406Sopenharmony_ci 7807141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 7808141cc406Sopenharmony_ci set_SCSI_opcode(cmd, READ_code); 7809141cc406Sopenharmony_ci set_R_datatype_code (cmd, R_datatype_pixelsize); 7810141cc406Sopenharmony_ci 7811141cc406Sopenharmony_ci if(s->side == SIDE_BACK){ 7812141cc406Sopenharmony_ci set_R_window_id (cmd, WD_wid_back); 7813141cc406Sopenharmony_ci } 7814141cc406Sopenharmony_ci else{ 7815141cc406Sopenharmony_ci set_R_window_id (cmd, WD_wid_front); 7816141cc406Sopenharmony_ci } 7817141cc406Sopenharmony_ci set_R_xfer_length (cmd, inLen); 7818141cc406Sopenharmony_ci 7819141cc406Sopenharmony_ci ret = do_cmd ( 7820141cc406Sopenharmony_ci s, 1, 0, 7821141cc406Sopenharmony_ci cmd, cmdLen, 7822141cc406Sopenharmony_ci NULL, 0, 7823141cc406Sopenharmony_ci in, &inLen 7824141cc406Sopenharmony_ci ); 7825141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD){ 7826141cc406Sopenharmony_ci 7827141cc406Sopenharmony_ci /* when we are called post-scan, the scanner may give 7828141cc406Sopenharmony_ci * more accurate data in other fields */ 7829141cc406Sopenharmony_ci if(actual && !s->has_short_pixelsize && get_PSIZE_paper_w(in)){ 7830141cc406Sopenharmony_ci DBG(5,"get_pixelsize: Actual width %d -> %d\n", s->s_params.pixels_per_line, get_PSIZE_paper_w(in)); 7831141cc406Sopenharmony_ci s->s_params.pixels_per_line = get_PSIZE_paper_w(in); 7832141cc406Sopenharmony_ci } 7833141cc406Sopenharmony_ci else{ 7834141cc406Sopenharmony_ci s->s_params.pixels_per_line = get_PSIZE_num_x(in); 7835141cc406Sopenharmony_ci } 7836141cc406Sopenharmony_ci 7837141cc406Sopenharmony_ci /* stupid trick. 3091/2 require reading extra lines, 7838141cc406Sopenharmony_ci * because they have a gap between R G and B 7839141cc406Sopenharmony_ci * we only want to report the shorter value to the frontend */ 7840141cc406Sopenharmony_ci if(s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ 7841141cc406Sopenharmony_ci DBG(5,"get_pixelsize: Ignoring length %d\n",get_PSIZE_num_y(in)); 7842141cc406Sopenharmony_ci } 7843141cc406Sopenharmony_ci /* when we are called post-scan, the scanner may give 7844141cc406Sopenharmony_ci * more accurate data in other fields */ 7845141cc406Sopenharmony_ci else if(actual && !s->has_short_pixelsize && get_PSIZE_paper_l(in)){ 7846141cc406Sopenharmony_ci DBG(5,"get_pixelsize: Actual length %d -> %d\n", s->s_params.lines, get_PSIZE_paper_l(in)); 7847141cc406Sopenharmony_ci s->s_params.lines = get_PSIZE_paper_l(in); 7848141cc406Sopenharmony_ci } 7849141cc406Sopenharmony_ci else{ 7850141cc406Sopenharmony_ci s->s_params.lines = get_PSIZE_num_y(in); 7851141cc406Sopenharmony_ci } 7852141cc406Sopenharmony_ci 7853141cc406Sopenharmony_ci /* bytes per line differs by mode */ 7854141cc406Sopenharmony_ci if (s->s_mode == MODE_COLOR) { 7855141cc406Sopenharmony_ci s->s_params.bytes_per_line = s->s_params.pixels_per_line * 3; 7856141cc406Sopenharmony_ci } 7857141cc406Sopenharmony_ci else if (s->s_mode == MODE_GRAYSCALE) { 7858141cc406Sopenharmony_ci s->s_params.bytes_per_line = s->s_params.pixels_per_line; 7859141cc406Sopenharmony_ci } 7860141cc406Sopenharmony_ci else { 7861141cc406Sopenharmony_ci s->s_params.bytes_per_line = s->s_params.pixels_per_line / 8; 7862141cc406Sopenharmony_ci } 7863141cc406Sopenharmony_ci 7864141cc406Sopenharmony_ci /* some scanners can request that the driver clean img */ 7865141cc406Sopenharmony_ci if(!s->has_short_pixelsize && get_PSIZE_req_driv_valid(in)){ 7866141cc406Sopenharmony_ci s->req_driv_crop = get_PSIZE_req_driv_crop(in); 7867141cc406Sopenharmony_ci s->req_driv_lut = get_PSIZE_req_driv_lut(in); 7868141cc406Sopenharmony_ci DBG(5,"get_pixelsize: scanner requests: crop=%d, lut=%d\n", 7869141cc406Sopenharmony_ci s->req_driv_crop,s->req_driv_lut); 7870141cc406Sopenharmony_ci } 7871141cc406Sopenharmony_ci 7872141cc406Sopenharmony_ci DBG (15, "get_pixelsize: scan_x=%d, Bpl=%d, scan_y=%d\n", 7873141cc406Sopenharmony_ci s->s_params.pixels_per_line, s->s_params.bytes_per_line, s->s_params.lines ); 7874141cc406Sopenharmony_ci 7875141cc406Sopenharmony_ci /* the user params are usually the same */ 7876141cc406Sopenharmony_ci s->u_params.pixels_per_line = s->s_params.pixels_per_line; 7877141cc406Sopenharmony_ci s->u_params.lines = s->s_params.lines; 7878141cc406Sopenharmony_ci 7879141cc406Sopenharmony_ci /* bytes per line differs by mode */ 7880141cc406Sopenharmony_ci if (s->u_mode == MODE_COLOR) { 7881141cc406Sopenharmony_ci s->u_params.bytes_per_line = s->u_params.pixels_per_line * 3; 7882141cc406Sopenharmony_ci } 7883141cc406Sopenharmony_ci else if (s->u_mode == MODE_GRAYSCALE) { 7884141cc406Sopenharmony_ci s->u_params.bytes_per_line = s->u_params.pixels_per_line; 7885141cc406Sopenharmony_ci } 7886141cc406Sopenharmony_ci else { 7887141cc406Sopenharmony_ci s->u_params.bytes_per_line = s->u_params.pixels_per_line / 8; 7888141cc406Sopenharmony_ci } 7889141cc406Sopenharmony_ci 7890141cc406Sopenharmony_ci } 7891141cc406Sopenharmony_ci else{ 7892141cc406Sopenharmony_ci DBG (10, "get_pixelsize: got bad status %d, ignoring\n", ret); 7893141cc406Sopenharmony_ci s->has_pixelsize = 0; 7894141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 7895141cc406Sopenharmony_ci } 7896141cc406Sopenharmony_ci 7897141cc406Sopenharmony_ci DBG (10, "get_pixelsize: finish\n"); 7898141cc406Sopenharmony_ci 7899141cc406Sopenharmony_ci return ret; 7900141cc406Sopenharmony_ci} 7901141cc406Sopenharmony_ci 7902141cc406Sopenharmony_ci/* 7903141cc406Sopenharmony_ci * Issues the SCSI OBJECT POSITION command if an ADF or card scanner is in use. 7904141cc406Sopenharmony_ci */ 7905141cc406Sopenharmony_cistatic SANE_Status 7906141cc406Sopenharmony_ciobject_position (struct fujitsu *s, int action) 7907141cc406Sopenharmony_ci{ 7908141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 7909141cc406Sopenharmony_ci 7910141cc406Sopenharmony_ci unsigned char cmd[OBJECT_POSITION_len]; 7911141cc406Sopenharmony_ci size_t cmdLen = OBJECT_POSITION_len; 7912141cc406Sopenharmony_ci 7913141cc406Sopenharmony_ci DBG (10, "object_position: start %d\n", action); 7914141cc406Sopenharmony_ci 7915141cc406Sopenharmony_ci if (s->source == SOURCE_FLATBED && action < OP_Halt) { 7916141cc406Sopenharmony_ci DBG (10, "object_position: flatbed no-op\n"); 7917141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7918141cc406Sopenharmony_ci } 7919141cc406Sopenharmony_ci 7920141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 7921141cc406Sopenharmony_ci set_SCSI_opcode(cmd, OBJECT_POSITION_code); 7922141cc406Sopenharmony_ci set_OP_action (cmd, action); 7923141cc406Sopenharmony_ci 7924141cc406Sopenharmony_ci ret = do_cmd ( 7925141cc406Sopenharmony_ci s, 1, 0, 7926141cc406Sopenharmony_ci cmd, cmdLen, 7927141cc406Sopenharmony_ci NULL, 0, 7928141cc406Sopenharmony_ci NULL, NULL 7929141cc406Sopenharmony_ci ); 7930141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 7931141cc406Sopenharmony_ci return ret; 7932141cc406Sopenharmony_ci 7933141cc406Sopenharmony_ci if(!s->no_wait_after_op) 7934141cc406Sopenharmony_ci wait_scanner (s); 7935141cc406Sopenharmony_ci 7936141cc406Sopenharmony_ci DBG (10, "object_position: finish\n"); 7937141cc406Sopenharmony_ci 7938141cc406Sopenharmony_ci return ret; 7939141cc406Sopenharmony_ci} 7940141cc406Sopenharmony_ci 7941141cc406Sopenharmony_ci/* 7942141cc406Sopenharmony_ci * Issues SCAN command. 7943141cc406Sopenharmony_ci * 7944141cc406Sopenharmony_ci * (This doesn't actually read anything, it just tells the scanner 7945141cc406Sopenharmony_ci * to start scanning.) 7946141cc406Sopenharmony_ci */ 7947141cc406Sopenharmony_cistatic SANE_Status 7948141cc406Sopenharmony_cistart_scan (struct fujitsu *s) 7949141cc406Sopenharmony_ci{ 7950141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 7951141cc406Sopenharmony_ci 7952141cc406Sopenharmony_ci unsigned char cmd[SCAN_len]; 7953141cc406Sopenharmony_ci size_t cmdLen = SCAN_len; 7954141cc406Sopenharmony_ci 7955141cc406Sopenharmony_ci unsigned char out[] = {WD_wid_front, WD_wid_back}; 7956141cc406Sopenharmony_ci size_t outLen = 2; 7957141cc406Sopenharmony_ci 7958141cc406Sopenharmony_ci DBG (10, "start_scan: start\n"); 7959141cc406Sopenharmony_ci 7960141cc406Sopenharmony_ci if (s->source != SOURCE_ADF_DUPLEX && s->source != SOURCE_CARD_DUPLEX) { 7961141cc406Sopenharmony_ci outLen--; 7962141cc406Sopenharmony_ci if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) { 7963141cc406Sopenharmony_ci out[0] = WD_wid_back; 7964141cc406Sopenharmony_ci } 7965141cc406Sopenharmony_ci } 7966141cc406Sopenharmony_ci 7967141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 7968141cc406Sopenharmony_ci set_SCSI_opcode(cmd, SCAN_code); 7969141cc406Sopenharmony_ci set_SC_xfer_length (cmd, outLen); 7970141cc406Sopenharmony_ci 7971141cc406Sopenharmony_ci ret = do_cmd ( 7972141cc406Sopenharmony_ci s, 1, 0, 7973141cc406Sopenharmony_ci cmd, cmdLen, 7974141cc406Sopenharmony_ci out, outLen, 7975141cc406Sopenharmony_ci NULL, NULL 7976141cc406Sopenharmony_ci ); 7977141cc406Sopenharmony_ci 7978141cc406Sopenharmony_ci DBG (10, "start_scan: finish\n"); 7979141cc406Sopenharmony_ci 7980141cc406Sopenharmony_ci return ret; 7981141cc406Sopenharmony_ci} 7982141cc406Sopenharmony_ci 7983141cc406Sopenharmony_ci/* checks started and cancelled flags in scanner struct, 7984141cc406Sopenharmony_ci * sends cancel command to scanner if required. don't call 7985141cc406Sopenharmony_ci * this function asynchronously, wait for pending operation */ 7986141cc406Sopenharmony_cistatic SANE_Status 7987141cc406Sopenharmony_cicheck_for_cancel(struct fujitsu *s) 7988141cc406Sopenharmony_ci{ 7989141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 7990141cc406Sopenharmony_ci 7991141cc406Sopenharmony_ci DBG (10, "check_for_cancel: start %d %d\n",s->started,s->cancelled); 7992141cc406Sopenharmony_ci 7993141cc406Sopenharmony_ci if(s->started && s->cancelled){ 7994141cc406Sopenharmony_ci 7995141cc406Sopenharmony_ci /* halt scan */ 7996141cc406Sopenharmony_ci if(s->halt_on_cancel){ 7997141cc406Sopenharmony_ci DBG (15, "check_for_cancel: halting\n"); 7998141cc406Sopenharmony_ci ret = object_position (s, OP_Halt); 7999141cc406Sopenharmony_ci } 8000141cc406Sopenharmony_ci /* cancel scan */ 8001141cc406Sopenharmony_ci else{ 8002141cc406Sopenharmony_ci DBG (15, "check_for_cancel: cancelling\n"); 8003141cc406Sopenharmony_ci ret = scanner_control(s, SC_function_cancel); 8004141cc406Sopenharmony_ci } 8005141cc406Sopenharmony_ci 8006141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_CANCELLED) { 8007141cc406Sopenharmony_ci ret = SANE_STATUS_CANCELLED; 8008141cc406Sopenharmony_ci } 8009141cc406Sopenharmony_ci else{ 8010141cc406Sopenharmony_ci DBG (5, "check_for_cancel: ERROR: cannot cancel\n"); 8011141cc406Sopenharmony_ci } 8012141cc406Sopenharmony_ci 8013141cc406Sopenharmony_ci s->started = 0; 8014141cc406Sopenharmony_ci s->cancelled = 0; 8015141cc406Sopenharmony_ci } 8016141cc406Sopenharmony_ci else if(s->cancelled){ 8017141cc406Sopenharmony_ci DBG (15, "check_for_cancel: already cancelled\n"); 8018141cc406Sopenharmony_ci ret = SANE_STATUS_CANCELLED; 8019141cc406Sopenharmony_ci s->cancelled = 0; 8020141cc406Sopenharmony_ci } 8021141cc406Sopenharmony_ci 8022141cc406Sopenharmony_ci DBG (10, "check_for_cancel: finish %d\n",ret); 8023141cc406Sopenharmony_ci return ret; 8024141cc406Sopenharmony_ci} 8025141cc406Sopenharmony_ci 8026141cc406Sopenharmony_ci/* 8027141cc406Sopenharmony_ci * Called by SANE to read data. 8028141cc406Sopenharmony_ci * 8029141cc406Sopenharmony_ci * From the SANE spec: 8030141cc406Sopenharmony_ci * This function is used to read image data from the device 8031141cc406Sopenharmony_ci * represented by handle h. Argument buf is a pointer to a memory 8032141cc406Sopenharmony_ci * area that is at least maxlen bytes long. The number of bytes 8033141cc406Sopenharmony_ci * returned is stored in *len. A backend must set this to zero when 8034141cc406Sopenharmony_ci * the call fails (i.e., when a status other than SANE_STATUS_GOOD is 8035141cc406Sopenharmony_ci * returned). 8036141cc406Sopenharmony_ci * 8037141cc406Sopenharmony_ci * When the call succeeds, the number of bytes returned can be 8038141cc406Sopenharmony_ci * anywhere in the range from 0 to maxlen bytes. 8039141cc406Sopenharmony_ci */ 8040141cc406Sopenharmony_ciSANE_Status 8041141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) 8042141cc406Sopenharmony_ci{ 8043141cc406Sopenharmony_ci struct fujitsu *s = (struct fujitsu *) handle; 8044141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8045141cc406Sopenharmony_ci 8046141cc406Sopenharmony_ci DBG (10, "sane_read: start\n"); 8047141cc406Sopenharmony_ci 8048141cc406Sopenharmony_ci *len=0; 8049141cc406Sopenharmony_ci 8050141cc406Sopenharmony_ci /* maybe cancelled? */ 8051141cc406Sopenharmony_ci if(!s->started){ 8052141cc406Sopenharmony_ci DBG (5, "sane_read: not started, call sane_start\n"); 8053141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 8054141cc406Sopenharmony_ci } 8055141cc406Sopenharmony_ci 8056141cc406Sopenharmony_ci /* sane_start required between sides */ 8057141cc406Sopenharmony_ci if(s->eof_rx[s->side] && s->bytes_tx[s->side] == s->bytes_rx[s->side]){ 8058141cc406Sopenharmony_ci DBG (15, "sane_read: returning eof\n"); 8059141cc406Sopenharmony_ci s->eof_tx[s->side] = 1; 8060141cc406Sopenharmony_ci 8061141cc406Sopenharmony_ci /* swap sides if user asked for low-mem mode, we are duplexing, 8062141cc406Sopenharmony_ci * and there is data waiting on the other side */ 8063141cc406Sopenharmony_ci if(s->low_mem 8064141cc406Sopenharmony_ci && (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) 8065141cc406Sopenharmony_ci && (s->bytes_rx[!s->side] > s->bytes_tx[!s->side] 8066141cc406Sopenharmony_ci || (s->eof_rx[!s->side] && !s->eof_tx[!s->side]) 8067141cc406Sopenharmony_ci ) 8068141cc406Sopenharmony_ci ){ 8069141cc406Sopenharmony_ci s->side = !s->side; 8070141cc406Sopenharmony_ci } 8071141cc406Sopenharmony_ci 8072141cc406Sopenharmony_ci return SANE_STATUS_EOF; 8073141cc406Sopenharmony_ci } 8074141cc406Sopenharmony_ci 8075141cc406Sopenharmony_ci /* protect this block from sane_cancel */ 8076141cc406Sopenharmony_ci s->reading = 1; 8077141cc406Sopenharmony_ci 8078141cc406Sopenharmony_ci /* ---------------------------------------------- 8079141cc406Sopenharmony_ci * try to read some data from scanner into buffer 8080141cc406Sopenharmony_ci * these functions are expected not to overrun */ 8081141cc406Sopenharmony_ci 8082141cc406Sopenharmony_ci /* 3091/2 are on crack, get their own duplex reader function */ 8083141cc406Sopenharmony_ci if(s->source == SOURCE_ADF_DUPLEX 8084141cc406Sopenharmony_ci && s->duplex_interlace == DUPLEX_INTERLACE_3091 8085141cc406Sopenharmony_ci ){ 8086141cc406Sopenharmony_ci ret = read_from_3091duplex(s); 8087141cc406Sopenharmony_ci if(ret){ 8088141cc406Sopenharmony_ci DBG(5,"sane_read: 3091 returning %d\n",ret); 8089141cc406Sopenharmony_ci return ret; 8090141cc406Sopenharmony_ci } 8091141cc406Sopenharmony_ci } /* end 3091 */ 8092141cc406Sopenharmony_ci 8093141cc406Sopenharmony_ci /* alternating jpeg duplex interlacing */ 8094141cc406Sopenharmony_ci else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) 8095141cc406Sopenharmony_ci && s->s_params.format == SANE_FRAME_JPEG 8096141cc406Sopenharmony_ci && s->jpeg_interlace == JPEG_INTERLACE_ALT 8097141cc406Sopenharmony_ci ){ 8098141cc406Sopenharmony_ci ret = read_from_JPEGduplex(s); 8099141cc406Sopenharmony_ci if(ret){ 8100141cc406Sopenharmony_ci DBG(5,"sane_read: jpeg duplex returning %d\n",ret); 8101141cc406Sopenharmony_ci return ret; 8102141cc406Sopenharmony_ci } 8103141cc406Sopenharmony_ci } /* end alt jpeg */ 8104141cc406Sopenharmony_ci 8105141cc406Sopenharmony_ci /* alternating pnm duplex interlacing */ 8106141cc406Sopenharmony_ci else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) 8107141cc406Sopenharmony_ci && s->s_params.format != SANE_FRAME_JPEG 8108141cc406Sopenharmony_ci && s->duplex_interlace == DUPLEX_INTERLACE_ALT 8109141cc406Sopenharmony_ci ){ 8110141cc406Sopenharmony_ci 8111141cc406Sopenharmony_ci /* buffer front side */ 8112141cc406Sopenharmony_ci ret = read_from_scanner(s, SIDE_FRONT); 8113141cc406Sopenharmony_ci if(ret){ 8114141cc406Sopenharmony_ci DBG(5,"sane_read: front returning %d\n",ret); 8115141cc406Sopenharmony_ci return ret; 8116141cc406Sopenharmony_ci } 8117141cc406Sopenharmony_ci 8118141cc406Sopenharmony_ci /* buffer back side, but don't get too far ahead of the front! */ 8119141cc406Sopenharmony_ci if(s->bytes_rx[SIDE_BACK] < s->bytes_rx[SIDE_FRONT] + s->buffer_size){ 8120141cc406Sopenharmony_ci ret = read_from_scanner(s, SIDE_BACK); 8121141cc406Sopenharmony_ci if(ret){ 8122141cc406Sopenharmony_ci DBG(5,"sane_read: back returning %d\n",ret); 8123141cc406Sopenharmony_ci return ret; 8124141cc406Sopenharmony_ci } 8125141cc406Sopenharmony_ci } 8126141cc406Sopenharmony_ci } /* end alt pnm */ 8127141cc406Sopenharmony_ci 8128141cc406Sopenharmony_ci /* simplex or non-alternating duplex */ 8129141cc406Sopenharmony_ci else{ 8130141cc406Sopenharmony_ci ret = read_from_scanner(s, s->side); 8131141cc406Sopenharmony_ci if(ret){ 8132141cc406Sopenharmony_ci DBG(5,"sane_read: side %d returning %d\n",s->side,ret); 8133141cc406Sopenharmony_ci return ret; 8134141cc406Sopenharmony_ci } 8135141cc406Sopenharmony_ci } /*end simplex*/ 8136141cc406Sopenharmony_ci 8137141cc406Sopenharmony_ci /* uncommon case, downsample and copy a block from buffer to frontend */ 8138141cc406Sopenharmony_ci if(must_downsample(s)){ 8139141cc406Sopenharmony_ci ret = downsample_from_buffer(s,buf,max_len,len,s->side); 8140141cc406Sopenharmony_ci } 8141141cc406Sopenharmony_ci 8142141cc406Sopenharmony_ci /* common case, memcpy a block from buffer to frontend */ 8143141cc406Sopenharmony_ci else{ 8144141cc406Sopenharmony_ci ret = read_from_buffer(s,buf,max_len,len,s->side); 8145141cc406Sopenharmony_ci } 8146141cc406Sopenharmony_ci 8147141cc406Sopenharmony_ci /*finished sending small buffer, reset it*/ 8148141cc406Sopenharmony_ci if(s->buff_tx[s->side] == s->buff_rx[s->side] 8149141cc406Sopenharmony_ci && s->buff_tot[s->side] < s->bytes_tot[s->side] 8150141cc406Sopenharmony_ci ){ 8151141cc406Sopenharmony_ci DBG (15, "sane_read: reset buffers\n"); 8152141cc406Sopenharmony_ci s->buff_rx[s->side] = 0; 8153141cc406Sopenharmony_ci s->buff_tx[s->side] = 0; 8154141cc406Sopenharmony_ci } 8155141cc406Sopenharmony_ci 8156141cc406Sopenharmony_ci /* check if user cancelled during this read */ 8157141cc406Sopenharmony_ci ret = check_for_cancel(s); 8158141cc406Sopenharmony_ci 8159141cc406Sopenharmony_ci /* swap sides if user asked for low-mem mode, we are duplexing, 8160141cc406Sopenharmony_ci * and there is data waiting on the other side */ 8161141cc406Sopenharmony_ci if(s->low_mem 8162141cc406Sopenharmony_ci && (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) 8163141cc406Sopenharmony_ci && (s->bytes_rx[!s->side] > s->bytes_tx[!s->side] 8164141cc406Sopenharmony_ci || (s->eof_rx[!s->side] && !s->eof_tx[!s->side]) 8165141cc406Sopenharmony_ci ) 8166141cc406Sopenharmony_ci ){ 8167141cc406Sopenharmony_ci s->side = !s->side; 8168141cc406Sopenharmony_ci } 8169141cc406Sopenharmony_ci 8170141cc406Sopenharmony_ci /* unprotect this block from sane_cancel */ 8171141cc406Sopenharmony_ci s->reading = 0; 8172141cc406Sopenharmony_ci 8173141cc406Sopenharmony_ci DBG (10, "sane_read: finish %d\n", ret); 8174141cc406Sopenharmony_ci return ret; 8175141cc406Sopenharmony_ci} 8176141cc406Sopenharmony_ci 8177141cc406Sopenharmony_ci/* bare jpeg images don't contain resolution, but JFIF APP0 does, so we add */ 8178141cc406Sopenharmony_cistatic SANE_Status 8179141cc406Sopenharmony_ciinject_jfif_header(struct fujitsu *s, int side) 8180141cc406Sopenharmony_ci{ 8181141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8182141cc406Sopenharmony_ci 8183141cc406Sopenharmony_ci unsigned char out[] = { 8184141cc406Sopenharmony_ci 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 8185141cc406Sopenharmony_ci 0x00, 0x01, 0x02, 0x01, 0x00, 0x48, 0x00, 0x48, 8186141cc406Sopenharmony_ci 0x00, 0x00 8187141cc406Sopenharmony_ci }; 8188141cc406Sopenharmony_ci size_t outLen=JFIF_APP0_LENGTH; 8189141cc406Sopenharmony_ci 8190141cc406Sopenharmony_ci DBG (10, "inject_jfif_header: start %d\n", side); 8191141cc406Sopenharmony_ci 8192141cc406Sopenharmony_ci putnbyte(out + 12, s->resolution_x, 2); 8193141cc406Sopenharmony_ci putnbyte(out + 14, s->resolution_y, 2); 8194141cc406Sopenharmony_ci 8195141cc406Sopenharmony_ci memcpy(s->buffers[side]+s->buff_rx[side], out, outLen); 8196141cc406Sopenharmony_ci s->buff_rx[side] += outLen; 8197141cc406Sopenharmony_ci s->bytes_rx[side] += outLen; 8198141cc406Sopenharmony_ci 8199141cc406Sopenharmony_ci DBG (10, "inject_jfif_header: finish %d\n", ret); 8200141cc406Sopenharmony_ci 8201141cc406Sopenharmony_ci return ret; 8202141cc406Sopenharmony_ci} 8203141cc406Sopenharmony_ci 8204141cc406Sopenharmony_cistatic SANE_Status 8205141cc406Sopenharmony_ciread_from_JPEGduplex(struct fujitsu *s) 8206141cc406Sopenharmony_ci{ 8207141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8208141cc406Sopenharmony_ci 8209141cc406Sopenharmony_ci unsigned char cmd[READ_len]; 8210141cc406Sopenharmony_ci size_t cmdLen = READ_len; 8211141cc406Sopenharmony_ci 8212141cc406Sopenharmony_ci unsigned char * in; 8213141cc406Sopenharmony_ci size_t inLen = 0; 8214141cc406Sopenharmony_ci 8215141cc406Sopenharmony_ci int bytes = s->buffer_size; 8216141cc406Sopenharmony_ci int i = 0; 8217141cc406Sopenharmony_ci 8218141cc406Sopenharmony_ci DBG (10, "read_from_JPEGduplex: start\n"); 8219141cc406Sopenharmony_ci 8220141cc406Sopenharmony_ci if(s->eof_rx[SIDE_FRONT] && s->eof_rx[SIDE_BACK]){ 8221141cc406Sopenharmony_ci DBG (10, "read_from_JPEGduplex: already have eofs, done\n"); 8222141cc406Sopenharmony_ci return ret; 8223141cc406Sopenharmony_ci } 8224141cc406Sopenharmony_ci 8225141cc406Sopenharmony_ci /* we don't know if the following read will give us front or back data 8226141cc406Sopenharmony_ci * so we only get enough to fill whichever is smaller (and not yet done) */ 8227141cc406Sopenharmony_ci if(!s->eof_rx[SIDE_FRONT]){ 8228141cc406Sopenharmony_ci int avail = s->buff_tot[SIDE_FRONT] - s->buff_rx[SIDE_FRONT]; 8229141cc406Sopenharmony_ci if(bytes > avail){ 8230141cc406Sopenharmony_ci bytes = avail; 8231141cc406Sopenharmony_ci } 8232141cc406Sopenharmony_ci } 8233141cc406Sopenharmony_ci if(!s->eof_rx[SIDE_BACK]){ 8234141cc406Sopenharmony_ci int avail = s->buff_tot[SIDE_BACK] - s->buff_rx[SIDE_BACK]; 8235141cc406Sopenharmony_ci if(bytes > avail){ 8236141cc406Sopenharmony_ci bytes = avail; 8237141cc406Sopenharmony_ci } 8238141cc406Sopenharmony_ci } 8239141cc406Sopenharmony_ci 8240141cc406Sopenharmony_ci /* leave space for JFIF header in the small front side buffer, 8241141cc406Sopenharmony_ci * if we are at the beginning of the image */ 8242141cc406Sopenharmony_ci if(s->bytes_rx[SIDE_FRONT] < 3){ 8243141cc406Sopenharmony_ci bytes -= JFIF_APP0_LENGTH; 8244141cc406Sopenharmony_ci } 8245141cc406Sopenharmony_ci 8246141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: fto:%d frx:%d bto:%d brx:%d pa:%d\n", 8247141cc406Sopenharmony_ci s->bytes_tot[SIDE_FRONT], s->bytes_rx[SIDE_FRONT], 8248141cc406Sopenharmony_ci s->bytes_tot[SIDE_BACK], s->bytes_rx[SIDE_BACK], 8249141cc406Sopenharmony_ci bytes); 8250141cc406Sopenharmony_ci 8251141cc406Sopenharmony_ci /* this will happen if buffer is not drained yet */ 8252141cc406Sopenharmony_ci if(bytes < 1){ 8253141cc406Sopenharmony_ci DBG(5, "read_from_JPEGduplex: Warning: no bytes this pass\n"); 8254141cc406Sopenharmony_ci return ret; 8255141cc406Sopenharmony_ci } 8256141cc406Sopenharmony_ci 8257141cc406Sopenharmony_ci /* fi-6770A gets mad if you 'read' too soon on usb, see if it is ready */ 8258141cc406Sopenharmony_ci if(!s->bytes_rx[SIDE_FRONT] && s->connection == CONNECTION_USB){ 8259141cc406Sopenharmony_ci DBG (15, "read: start of usb page, checking RIC\n"); 8260141cc406Sopenharmony_ci ret = scanner_control_ric(s,bytes,SIDE_FRONT); 8261141cc406Sopenharmony_ci if(ret){ 8262141cc406Sopenharmony_ci DBG(5,"read: ric returning %d\n",ret); 8263141cc406Sopenharmony_ci return ret; 8264141cc406Sopenharmony_ci } 8265141cc406Sopenharmony_ci } 8266141cc406Sopenharmony_ci 8267141cc406Sopenharmony_ci inLen = bytes; 8268141cc406Sopenharmony_ci in = malloc(inLen); 8269141cc406Sopenharmony_ci if(!in){ 8270141cc406Sopenharmony_ci DBG(5, "read_from_JPEGduplex: not enough mem for buffer: %d\n",(int)inLen); 8271141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 8272141cc406Sopenharmony_ci } 8273141cc406Sopenharmony_ci 8274141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 8275141cc406Sopenharmony_ci set_SCSI_opcode(cmd, READ_code); 8276141cc406Sopenharmony_ci set_R_datatype_code (cmd, R_datatype_imagedata); 8277141cc406Sopenharmony_ci /* interlaced jpeg duplex always reads from front */ 8278141cc406Sopenharmony_ci set_R_window_id (cmd, WD_wid_front); 8279141cc406Sopenharmony_ci set_R_xfer_length (cmd, inLen); 8280141cc406Sopenharmony_ci 8281141cc406Sopenharmony_ci ret = do_cmd ( 8282141cc406Sopenharmony_ci s, 1, 0, 8283141cc406Sopenharmony_ci cmd, cmdLen, 8284141cc406Sopenharmony_ci NULL, 0, 8285141cc406Sopenharmony_ci in, &inLen 8286141cc406Sopenharmony_ci ); 8287141cc406Sopenharmony_ci 8288141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { 8289141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: got GOOD/EOF, returning GOOD\n"); 8290141cc406Sopenharmony_ci } 8291141cc406Sopenharmony_ci else if (ret == SANE_STATUS_DEVICE_BUSY) { 8292141cc406Sopenharmony_ci DBG(5, "read_from_JPEGduplex: got BUSY, returning GOOD\n"); 8293141cc406Sopenharmony_ci inLen = 0; 8294141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 8295141cc406Sopenharmony_ci } 8296141cc406Sopenharmony_ci else { 8297141cc406Sopenharmony_ci DBG(5, "read_from_JPEGduplex: error reading data status = %d\n", ret); 8298141cc406Sopenharmony_ci inLen = 0; 8299141cc406Sopenharmony_ci } 8300141cc406Sopenharmony_ci 8301141cc406Sopenharmony_ci for(i=0;i<(int)inLen;i++){ 8302141cc406Sopenharmony_ci 8303141cc406Sopenharmony_ci /* about to change stage */ 8304141cc406Sopenharmony_ci if(in[i] == 0xff && s->jpeg_ff_offset != 0){ 8305141cc406Sopenharmony_ci s->jpeg_ff_offset=0; 8306141cc406Sopenharmony_ci continue; 8307141cc406Sopenharmony_ci } 8308141cc406Sopenharmony_ci 8309141cc406Sopenharmony_ci /* last byte was an ff, this byte will change stage */ 8310141cc406Sopenharmony_ci if(s->jpeg_ff_offset == 0){ 8311141cc406Sopenharmony_ci 8312141cc406Sopenharmony_ci /* first marker after SOI is not APP0, add one */ 8313141cc406Sopenharmony_ci if(s->jpeg_stage == JPEG_STAGE_SOI && in[i] != 0xe0){ 8314141cc406Sopenharmony_ci inject_jfif_header(s,SIDE_FRONT); 8315141cc406Sopenharmony_ci inject_jfif_header(s,SIDE_BACK); 8316141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_HEAD; 8317141cc406Sopenharmony_ci } 8318141cc406Sopenharmony_ci 8319141cc406Sopenharmony_ci /* SOI header, in both sides */ 8320141cc406Sopenharmony_ci if(in[i] == 0xd8){ 8321141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_SOI; 8322141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: stage SOI\n"); 8323141cc406Sopenharmony_ci } 8324141cc406Sopenharmony_ci 8325141cc406Sopenharmony_ci /* headers (HuffTab/QTab/DRI), in both sides */ 8326141cc406Sopenharmony_ci else if(in[i] == 0xc4 || in[i] == 0xdb || in[i] == 0xdd){ 8327141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_HEAD; 8328141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: stage head\n"); 8329141cc406Sopenharmony_ci } 8330141cc406Sopenharmony_ci 8331141cc406Sopenharmony_ci /* start of frame, in both sides, update x first */ 8332141cc406Sopenharmony_ci else if(in[i]==0xc0){ 8333141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_SOF; 8334141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: stage sof\n"); 8335141cc406Sopenharmony_ci } 8336141cc406Sopenharmony_ci 8337141cc406Sopenharmony_ci /* start of scan, first few bytes of marker in both sides 8338141cc406Sopenharmony_ci * but rest in front */ 8339141cc406Sopenharmony_ci else if(in[i]==0xda){ 8340141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_SOS; 8341141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: stage sos\n"); 8342141cc406Sopenharmony_ci } 8343141cc406Sopenharmony_ci 8344141cc406Sopenharmony_ci /* found image block. images are not interlaced */ 8345141cc406Sopenharmony_ci /* copy to front, don't change RST */ 8346141cc406Sopenharmony_ci else if(in[i] >= 0xd0 && in[i] <= 0xd7 8347141cc406Sopenharmony_ci && s->jpeg_interlace == JPEG_INTERLACE_NONE){ 8348141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_FRONT; 8349141cc406Sopenharmony_ci DBG(35, "read_from_JPEGduplex: stage front (all)\n"); 8350141cc406Sopenharmony_ci } 8351141cc406Sopenharmony_ci 8352141cc406Sopenharmony_ci /* found even numbered image block. */ 8353141cc406Sopenharmony_ci /* images are interlaced, so switch to back. */ 8354141cc406Sopenharmony_ci /* also change from even RST to proper one */ 8355141cc406Sopenharmony_ci else if(in[i] == 0xd0 || in[i] == 0xd2 8356141cc406Sopenharmony_ci || in[i] == 0xd4 || in[i] == 0xd6){ 8357141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_BACK; 8358141cc406Sopenharmony_ci DBG(35, "read_from_JPEGduplex: stage back\n"); 8359141cc406Sopenharmony_ci 8360141cc406Sopenharmony_ci /* skip first RST for back side*/ 8361141cc406Sopenharmony_ci if(!s->jpeg_back_rst){ 8362141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: stage back jump\n"); 8363141cc406Sopenharmony_ci s->jpeg_ff_offset++; 8364141cc406Sopenharmony_ci s->jpeg_back_rst++; 8365141cc406Sopenharmony_ci continue; 8366141cc406Sopenharmony_ci } 8367141cc406Sopenharmony_ci 8368141cc406Sopenharmony_ci in[i] = 0xd0 + (s->jpeg_back_rst-1) % 8; 8369141cc406Sopenharmony_ci s->jpeg_back_rst++; 8370141cc406Sopenharmony_ci } 8371141cc406Sopenharmony_ci 8372141cc406Sopenharmony_ci /* finished back image block, switch to front */ 8373141cc406Sopenharmony_ci /* also change from odd RST to proper one */ 8374141cc406Sopenharmony_ci else if(in[i] == 0xd1 || in[i] == 0xd3 8375141cc406Sopenharmony_ci || in[i] == 0xd5 || in[i] == 0xd7){ 8376141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_FRONT; 8377141cc406Sopenharmony_ci DBG(35, "read_from_JPEGduplex: stage front\n"); 8378141cc406Sopenharmony_ci in[i] = 0xd0 + (s->jpeg_front_rst % 8); 8379141cc406Sopenharmony_ci s->jpeg_front_rst++; 8380141cc406Sopenharmony_ci } 8381141cc406Sopenharmony_ci 8382141cc406Sopenharmony_ci /* finished image, update totals */ 8383141cc406Sopenharmony_ci else if(in[i]==0xd9){ 8384141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_EOI; 8385141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: stage eoi %d %d\n",(int)inLen,i); 8386141cc406Sopenharmony_ci } 8387141cc406Sopenharmony_ci 8388141cc406Sopenharmony_ci /* unknown, warn */ 8389141cc406Sopenharmony_ci else if(in[i] != 0x00){ 8390141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: unknown %02x\n", in[i]); 8391141cc406Sopenharmony_ci } 8392141cc406Sopenharmony_ci } 8393141cc406Sopenharmony_ci s->jpeg_ff_offset++; 8394141cc406Sopenharmony_ci 8395141cc406Sopenharmony_ci /* first x byte in start of frame, buffer it */ 8396141cc406Sopenharmony_ci if(s->jpeg_stage == JPEG_STAGE_SOF && s->jpeg_ff_offset == 7){ 8397141cc406Sopenharmony_ci s->jpeg_x_byte = in[i]; 8398141cc406Sopenharmony_ci continue; 8399141cc406Sopenharmony_ci } 8400141cc406Sopenharmony_ci 8401141cc406Sopenharmony_ci /* second x byte in start of frame */ 8402141cc406Sopenharmony_ci if(s->jpeg_stage == JPEG_STAGE_SOF && s->jpeg_ff_offset == 8){ 8403141cc406Sopenharmony_ci 8404141cc406Sopenharmony_ci int width = (s->jpeg_x_byte << 8) | in[i]; 8405141cc406Sopenharmony_ci 8406141cc406Sopenharmony_ci /* if image width equals what we asked for, then 8407141cc406Sopenharmony_ci * the image is not interlaced, clean up the mess */ 8408141cc406Sopenharmony_ci if(width == s->s_params.pixels_per_line){ 8409141cc406Sopenharmony_ci 8410141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: right width, req:%d got:%d\n", 8411141cc406Sopenharmony_ci s->s_params.pixels_per_line,width); 8412141cc406Sopenharmony_ci 8413141cc406Sopenharmony_ci /* stop copying to the back */ 8414141cc406Sopenharmony_ci s->jpeg_interlace = JPEG_INTERLACE_NONE; 8415141cc406Sopenharmony_ci 8416141cc406Sopenharmony_ci /* clear what is already in the back */ 8417141cc406Sopenharmony_ci s->bytes_rx[SIDE_BACK]=0; 8418141cc406Sopenharmony_ci s->lines_rx[SIDE_BACK]=0; 8419141cc406Sopenharmony_ci s->buff_rx[SIDE_BACK]=0; 8420141cc406Sopenharmony_ci 8421141cc406Sopenharmony_ci /* and put the high-order width byte into front unchanged */ 8422141cc406Sopenharmony_ci s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = s->jpeg_x_byte; 8423141cc406Sopenharmony_ci s->bytes_rx[SIDE_FRONT]++; 8424141cc406Sopenharmony_ci } 8425141cc406Sopenharmony_ci 8426141cc406Sopenharmony_ci /* image is interlaced after all, continue */ 8427141cc406Sopenharmony_ci else{ 8428141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: wrong width, req:%d got:%d\n", 8429141cc406Sopenharmony_ci s->s_params.pixels_per_line,width); 8430141cc406Sopenharmony_ci 8431141cc406Sopenharmony_ci /* put the high-order width byte into front side, shifted down */ 8432141cc406Sopenharmony_ci s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = width >> 9; 8433141cc406Sopenharmony_ci s->bytes_rx[SIDE_FRONT]++; 8434141cc406Sopenharmony_ci 8435141cc406Sopenharmony_ci /* put the high-order width byte into back side, shifted down */ 8436141cc406Sopenharmony_ci s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = width >> 9; 8437141cc406Sopenharmony_ci s->bytes_rx[SIDE_BACK]++; 8438141cc406Sopenharmony_ci 8439141cc406Sopenharmony_ci /* shift down low order byte */ 8440141cc406Sopenharmony_ci in[i] = (width >> 1) & 0xff; 8441141cc406Sopenharmony_ci } 8442141cc406Sopenharmony_ci } 8443141cc406Sopenharmony_ci 8444141cc406Sopenharmony_ci /* copy these stages to front */ 8445141cc406Sopenharmony_ci if(s->jpeg_stage == JPEG_STAGE_SOI 8446141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_HEAD 8447141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_SOF 8448141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_SOS 8449141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_EOI 8450141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_FRONT 8451141cc406Sopenharmony_ci ){ 8452141cc406Sopenharmony_ci /* first byte after ff, send the ff first */ 8453141cc406Sopenharmony_ci if(s->jpeg_ff_offset == 1){ 8454141cc406Sopenharmony_ci s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = 0xff; 8455141cc406Sopenharmony_ci s->bytes_rx[SIDE_FRONT]++; 8456141cc406Sopenharmony_ci } 8457141cc406Sopenharmony_ci s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = in[i]; 8458141cc406Sopenharmony_ci s->bytes_rx[SIDE_FRONT]++; 8459141cc406Sopenharmony_ci } 8460141cc406Sopenharmony_ci 8461141cc406Sopenharmony_ci /* copy these stages to back */ 8462141cc406Sopenharmony_ci if( s->jpeg_interlace == JPEG_INTERLACE_ALT 8463141cc406Sopenharmony_ci && 8464141cc406Sopenharmony_ci ( s->jpeg_stage == JPEG_STAGE_SOI 8465141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_HEAD 8466141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_SOF 8467141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_SOS 8468141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_EOI 8469141cc406Sopenharmony_ci || s->jpeg_stage == JPEG_STAGE_BACK ) 8470141cc406Sopenharmony_ci ){ 8471141cc406Sopenharmony_ci /* first byte after ff, send the ff first */ 8472141cc406Sopenharmony_ci if(s->jpeg_ff_offset == 1){ 8473141cc406Sopenharmony_ci s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = 0xff; 8474141cc406Sopenharmony_ci s->bytes_rx[SIDE_BACK]++; 8475141cc406Sopenharmony_ci } 8476141cc406Sopenharmony_ci s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = in[i]; 8477141cc406Sopenharmony_ci s->bytes_rx[SIDE_BACK]++; 8478141cc406Sopenharmony_ci } 8479141cc406Sopenharmony_ci 8480141cc406Sopenharmony_ci /* reached last byte of SOS section, next byte front */ 8481141cc406Sopenharmony_ci if(s->jpeg_stage == JPEG_STAGE_SOS && s->jpeg_ff_offset == 0x0d){ 8482141cc406Sopenharmony_ci s->jpeg_stage = JPEG_STAGE_FRONT; 8483141cc406Sopenharmony_ci } 8484141cc406Sopenharmony_ci 8485141cc406Sopenharmony_ci /* last byte of file, update totals, bail out */ 8486141cc406Sopenharmony_ci if(s->jpeg_stage == JPEG_STAGE_EOI){ 8487141cc406Sopenharmony_ci s->eof_rx[SIDE_FRONT] = 1; 8488141cc406Sopenharmony_ci if(s->jpeg_interlace == JPEG_INTERLACE_ALT) 8489141cc406Sopenharmony_ci s->eof_rx[SIDE_BACK] = 1; 8490141cc406Sopenharmony_ci } 8491141cc406Sopenharmony_ci } 8492141cc406Sopenharmony_ci 8493141cc406Sopenharmony_ci free(in); 8494141cc406Sopenharmony_ci 8495141cc406Sopenharmony_ci /* jpeg uses in-band EOI marker, so this is usually redundant */ 8496141cc406Sopenharmony_ci if(ret == SANE_STATUS_EOF){ 8497141cc406Sopenharmony_ci DBG(15, "read_from_JPEGduplex: got EOF, finishing\n"); 8498141cc406Sopenharmony_ci s->eof_rx[SIDE_FRONT] = 1; 8499141cc406Sopenharmony_ci if(s->jpeg_interlace == JPEG_INTERLACE_ALT) 8500141cc406Sopenharmony_ci s->eof_rx[SIDE_BACK] = 1; 8501141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 8502141cc406Sopenharmony_ci } 8503141cc406Sopenharmony_ci 8504141cc406Sopenharmony_ci DBG (10, "read_from_JPEGduplex: finish\n"); 8505141cc406Sopenharmony_ci 8506141cc406Sopenharmony_ci return ret; 8507141cc406Sopenharmony_ci} 8508141cc406Sopenharmony_ci 8509141cc406Sopenharmony_cistatic SANE_Status 8510141cc406Sopenharmony_ciread_from_3091duplex(struct fujitsu *s) 8511141cc406Sopenharmony_ci{ 8512141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8513141cc406Sopenharmony_ci 8514141cc406Sopenharmony_ci unsigned char cmd[READ_len]; 8515141cc406Sopenharmony_ci size_t cmdLen = READ_len; 8516141cc406Sopenharmony_ci 8517141cc406Sopenharmony_ci unsigned char * in; 8518141cc406Sopenharmony_ci size_t inLen = 0; 8519141cc406Sopenharmony_ci 8520141cc406Sopenharmony_ci int side = SIDE_FRONT; 8521141cc406Sopenharmony_ci int bytes = s->buffer_size; 8522141cc406Sopenharmony_ci int off = (s->duplex_raster_offset+s->duplex_offset) * s->resolution_y/300; 8523141cc406Sopenharmony_ci unsigned int i; 8524141cc406Sopenharmony_ci 8525141cc406Sopenharmony_ci DBG (10, "read_from_3091duplex: start\n"); 8526141cc406Sopenharmony_ci 8527141cc406Sopenharmony_ci if(s->eof_rx[SIDE_FRONT] && s->eof_rx[SIDE_BACK]){ 8528141cc406Sopenharmony_ci DBG (10, "read_from_3091duplex: already have eofs, done\n"); 8529141cc406Sopenharmony_ci return ret; 8530141cc406Sopenharmony_ci } 8531141cc406Sopenharmony_ci 8532141cc406Sopenharmony_ci /* we don't know if the following read will give us front,back or both data 8533141cc406Sopenharmony_ci * so we only get enough to fill whichever is smaller (and not yet done) */ 8534141cc406Sopenharmony_ci if(!s->eof_rx[SIDE_FRONT]){ 8535141cc406Sopenharmony_ci int avail = s->buff_tot[SIDE_FRONT] - s->buff_rx[SIDE_FRONT]; 8536141cc406Sopenharmony_ci if(bytes > avail) 8537141cc406Sopenharmony_ci bytes = avail; 8538141cc406Sopenharmony_ci } 8539141cc406Sopenharmony_ci if(!s->eof_rx[SIDE_BACK]){ 8540141cc406Sopenharmony_ci int avail = s->buff_tot[SIDE_BACK] - s->buff_rx[SIDE_BACK]; 8541141cc406Sopenharmony_ci if(bytes > avail) 8542141cc406Sopenharmony_ci bytes = avail; 8543141cc406Sopenharmony_ci } 8544141cc406Sopenharmony_ci 8545141cc406Sopenharmony_ci /* all requests must end on a line boundary */ 8546141cc406Sopenharmony_ci bytes -= (bytes % s->s_params.bytes_per_line); 8547141cc406Sopenharmony_ci 8548141cc406Sopenharmony_ci DBG(15, "read_from_3091duplex: front img: to:%d rx:%d tx:%d li:%d\n", 8549141cc406Sopenharmony_ci s->bytes_tot[SIDE_FRONT], s->bytes_rx[SIDE_FRONT], 8550141cc406Sopenharmony_ci s->bytes_tx[SIDE_FRONT], s->lines_rx[SIDE_FRONT]); 8551141cc406Sopenharmony_ci 8552141cc406Sopenharmony_ci DBG(15, "read_from_3091duplex: front buf: to:%d rx:%d tx:%d\n", 8553141cc406Sopenharmony_ci s->buff_tot[SIDE_FRONT], s->buff_rx[SIDE_FRONT], 8554141cc406Sopenharmony_ci s->buff_tx[SIDE_FRONT]); 8555141cc406Sopenharmony_ci 8556141cc406Sopenharmony_ci DBG(15, "read_from_3091duplex: back img: to:%d rx:%d tx:%d li:%d\n", 8557141cc406Sopenharmony_ci s->bytes_tot[SIDE_BACK], s->bytes_rx[SIDE_BACK], 8558141cc406Sopenharmony_ci s->bytes_tx[SIDE_BACK], s->lines_rx[SIDE_BACK]); 8559141cc406Sopenharmony_ci 8560141cc406Sopenharmony_ci DBG(15, "read_from_3091duplex: back buf: to:%d rx:%d tx:%d\n", 8561141cc406Sopenharmony_ci s->buff_tot[SIDE_BACK], s->buff_rx[SIDE_BACK], 8562141cc406Sopenharmony_ci s->buff_tx[SIDE_BACK]); 8563141cc406Sopenharmony_ci 8564141cc406Sopenharmony_ci DBG(15, "read_from_3091duplex: bu:%d pa:%d of:%d\n", 8565141cc406Sopenharmony_ci s->buffer_size, bytes, off); 8566141cc406Sopenharmony_ci 8567141cc406Sopenharmony_ci /* this could happen if the front buffer is not drained fast enough */ 8568141cc406Sopenharmony_ci if(bytes < 1){ 8569141cc406Sopenharmony_ci DBG(10, "read_from_3091duplex: Warning: no bytes this pass\n"); 8570141cc406Sopenharmony_ci return ret; 8571141cc406Sopenharmony_ci } 8572141cc406Sopenharmony_ci 8573141cc406Sopenharmony_ci inLen = bytes; 8574141cc406Sopenharmony_ci 8575141cc406Sopenharmony_ci in = malloc(inLen); 8576141cc406Sopenharmony_ci if(!in){ 8577141cc406Sopenharmony_ci DBG(5, "read_from_3091duplex: not enough mem for buffer: %d\n",(int)inLen); 8578141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 8579141cc406Sopenharmony_ci } 8580141cc406Sopenharmony_ci 8581141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 8582141cc406Sopenharmony_ci set_SCSI_opcode(cmd, READ_code); 8583141cc406Sopenharmony_ci set_R_datatype_code (cmd, R_datatype_imagedata); 8584141cc406Sopenharmony_ci /* 3091 duplex always reads from front */ 8585141cc406Sopenharmony_ci set_R_window_id (cmd, WD_wid_front); 8586141cc406Sopenharmony_ci set_R_xfer_length (cmd, inLen); 8587141cc406Sopenharmony_ci 8588141cc406Sopenharmony_ci ret = do_cmd ( 8589141cc406Sopenharmony_ci s, 1, 0, 8590141cc406Sopenharmony_ci cmd, cmdLen, 8591141cc406Sopenharmony_ci NULL, 0, 8592141cc406Sopenharmony_ci in, &inLen 8593141cc406Sopenharmony_ci ); 8594141cc406Sopenharmony_ci 8595141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { 8596141cc406Sopenharmony_ci DBG(15, "read_from_3091duplex: got GOOD/EOF, returning GOOD\n"); 8597141cc406Sopenharmony_ci } 8598141cc406Sopenharmony_ci else if (ret == SANE_STATUS_DEVICE_BUSY) { 8599141cc406Sopenharmony_ci DBG(5, "read_from_3091duplex: got BUSY, returning GOOD\n"); 8600141cc406Sopenharmony_ci inLen = 0; 8601141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 8602141cc406Sopenharmony_ci } 8603141cc406Sopenharmony_ci else { 8604141cc406Sopenharmony_ci DBG(5, "read_from_3091duplex: error reading data block status = %d\n", ret); 8605141cc406Sopenharmony_ci inLen = 0; 8606141cc406Sopenharmony_ci } 8607141cc406Sopenharmony_ci 8608141cc406Sopenharmony_ci /* loop thru all lines in read buffer */ 8609141cc406Sopenharmony_ci for(i=0;i<inLen/s->s_params.bytes_per_line;i++){ 8610141cc406Sopenharmony_ci 8611141cc406Sopenharmony_ci /* start is front */ 8612141cc406Sopenharmony_ci if(s->lines_rx[SIDE_FRONT] < off){ 8613141cc406Sopenharmony_ci side=SIDE_FRONT; 8614141cc406Sopenharmony_ci } 8615141cc406Sopenharmony_ci 8616141cc406Sopenharmony_ci /* end is back */ 8617141cc406Sopenharmony_ci else if(s->eof_rx[SIDE_FRONT]){ 8618141cc406Sopenharmony_ci side=SIDE_BACK; 8619141cc406Sopenharmony_ci } 8620141cc406Sopenharmony_ci 8621141cc406Sopenharmony_ci /* odd are back */ 8622141cc406Sopenharmony_ci else if( ((s->lines_rx[SIDE_FRONT] + s->lines_rx[SIDE_BACK] - off) % 2) ){ 8623141cc406Sopenharmony_ci side=SIDE_BACK; 8624141cc406Sopenharmony_ci } 8625141cc406Sopenharmony_ci 8626141cc406Sopenharmony_ci /* even are front */ 8627141cc406Sopenharmony_ci else{ 8628141cc406Sopenharmony_ci side=SIDE_FRONT; 8629141cc406Sopenharmony_ci } 8630141cc406Sopenharmony_ci 8631141cc406Sopenharmony_ci if(s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ 8632141cc406Sopenharmony_ci copy_3091 (s, in + i*s->s_params.bytes_per_line, s->s_params.bytes_per_line, side); 8633141cc406Sopenharmony_ci } 8634141cc406Sopenharmony_ci else{ 8635141cc406Sopenharmony_ci copy_buffer (s, in + i*s->s_params.bytes_per_line, s->s_params.bytes_per_line, side); 8636141cc406Sopenharmony_ci } 8637141cc406Sopenharmony_ci } 8638141cc406Sopenharmony_ci 8639141cc406Sopenharmony_ci if(ret == SANE_STATUS_EOF){ 8640141cc406Sopenharmony_ci DBG(15, "read_from_3091duplex: got EOF, finishing both sides\n"); 8641141cc406Sopenharmony_ci s->eof_rx[SIDE_FRONT] = 1; 8642141cc406Sopenharmony_ci s->eof_rx[SIDE_BACK] = 1; 8643141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 8644141cc406Sopenharmony_ci } 8645141cc406Sopenharmony_ci 8646141cc406Sopenharmony_ci free(in); 8647141cc406Sopenharmony_ci 8648141cc406Sopenharmony_ci DBG (10, "read_from_3091duplex: finish\n"); 8649141cc406Sopenharmony_ci 8650141cc406Sopenharmony_ci return ret; 8651141cc406Sopenharmony_ci} 8652141cc406Sopenharmony_ci 8653141cc406Sopenharmony_cistatic SANE_Status 8654141cc406Sopenharmony_ciread_from_scanner(struct fujitsu *s, int side) 8655141cc406Sopenharmony_ci{ 8656141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8657141cc406Sopenharmony_ci 8658141cc406Sopenharmony_ci unsigned char cmd[READ_len]; 8659141cc406Sopenharmony_ci size_t cmdLen = READ_len; 8660141cc406Sopenharmony_ci 8661141cc406Sopenharmony_ci unsigned char * in; 8662141cc406Sopenharmony_ci size_t inLen = 0; 8663141cc406Sopenharmony_ci 8664141cc406Sopenharmony_ci int bytes = s->buffer_size; 8665141cc406Sopenharmony_ci int avail = s->buff_tot[side] - s->buff_rx[side]; 8666141cc406Sopenharmony_ci int remain = s->bytes_tot[side] - s->bytes_rx[side]; 8667141cc406Sopenharmony_ci 8668141cc406Sopenharmony_ci DBG (10, "read_from_scanner: start %d\n", side); 8669141cc406Sopenharmony_ci 8670141cc406Sopenharmony_ci if(s->eof_rx[side]){ 8671141cc406Sopenharmony_ci DBG (10, "read_from_scanner: already have eof, done\n"); 8672141cc406Sopenharmony_ci return ret; 8673141cc406Sopenharmony_ci } 8674141cc406Sopenharmony_ci 8675141cc406Sopenharmony_ci /* figure out the max amount to transfer */ 8676141cc406Sopenharmony_ci if(bytes > avail) 8677141cc406Sopenharmony_ci bytes = avail; 8678141cc406Sopenharmony_ci 8679141cc406Sopenharmony_ci /* all requests must end on line boundary */ 8680141cc406Sopenharmony_ci bytes -= (bytes % s->s_params.bytes_per_line); 8681141cc406Sopenharmony_ci 8682141cc406Sopenharmony_ci /* some larger scanners require even bytes per block */ 8683141cc406Sopenharmony_ci /* so we get even lines, but not on the last block */ 8684141cc406Sopenharmony_ci /* cause odd number of lines would never finish */ 8685141cc406Sopenharmony_ci if(bytes % 2 && bytes < remain){ 8686141cc406Sopenharmony_ci bytes -= s->s_params.bytes_per_line; 8687141cc406Sopenharmony_ci } 8688141cc406Sopenharmony_ci 8689141cc406Sopenharmony_ci /* jpeg scans leave space for JFIF header at start of image */ 8690141cc406Sopenharmony_ci if(s->s_params.format == SANE_FRAME_JPEG && s->bytes_rx[side] < 2) 8691141cc406Sopenharmony_ci bytes -= JFIF_APP0_LENGTH; 8692141cc406Sopenharmony_ci 8693141cc406Sopenharmony_ci DBG(15, "read_from_scanner: si:%d re:%d bs:%d by:%d av:%d\n", 8694141cc406Sopenharmony_ci side, remain, s->buffer_size, bytes, avail); 8695141cc406Sopenharmony_ci 8696141cc406Sopenharmony_ci DBG(15, "read_from_scanner: img to:%d rx:%d tx:%d li:%d\n", 8697141cc406Sopenharmony_ci s->bytes_tot[side], s->bytes_rx[side], s->bytes_tx[side], 8698141cc406Sopenharmony_ci s->lines_rx[side]); 8699141cc406Sopenharmony_ci 8700141cc406Sopenharmony_ci DBG(15, "read_from_scanner: buf to:%d rx:%d tx:%d\n", 8701141cc406Sopenharmony_ci s->buff_tot[side], s->buff_rx[side], s->buff_tx[side]); 8702141cc406Sopenharmony_ci 8703141cc406Sopenharmony_ci /* this will happen if buffer is not drained yet */ 8704141cc406Sopenharmony_ci if(bytes < 1){ 8705141cc406Sopenharmony_ci DBG(5, "read_from_scanner: no bytes this pass\n"); 8706141cc406Sopenharmony_ci return ret; 8707141cc406Sopenharmony_ci } 8708141cc406Sopenharmony_ci 8709141cc406Sopenharmony_ci /* fi-6770A gets mad if you 'read' too soon on usb, see if it is ready */ 8710141cc406Sopenharmony_ci if(!s->bytes_rx[side] && s->connection == CONNECTION_USB){ 8711141cc406Sopenharmony_ci DBG (15, "read_from_scanner: start of usb page, checking RIC\n"); 8712141cc406Sopenharmony_ci ret = scanner_control_ric(s,bytes,side); 8713141cc406Sopenharmony_ci if(ret){ 8714141cc406Sopenharmony_ci DBG(5,"read_from_scanner: ric returning %d\n",ret); 8715141cc406Sopenharmony_ci return ret; 8716141cc406Sopenharmony_ci } 8717141cc406Sopenharmony_ci } 8718141cc406Sopenharmony_ci 8719141cc406Sopenharmony_ci inLen = bytes; 8720141cc406Sopenharmony_ci in = malloc(inLen); 8721141cc406Sopenharmony_ci if(!in){ 8722141cc406Sopenharmony_ci DBG(5, "read_from_scanner: not enough mem for buffer: %d\n",(int)inLen); 8723141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 8724141cc406Sopenharmony_ci } 8725141cc406Sopenharmony_ci 8726141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 8727141cc406Sopenharmony_ci set_SCSI_opcode(cmd, READ_code); 8728141cc406Sopenharmony_ci set_R_datatype_code (cmd, R_datatype_imagedata); 8729141cc406Sopenharmony_ci 8730141cc406Sopenharmony_ci if (side == SIDE_BACK) { 8731141cc406Sopenharmony_ci set_R_window_id (cmd, WD_wid_back); 8732141cc406Sopenharmony_ci } 8733141cc406Sopenharmony_ci else{ 8734141cc406Sopenharmony_ci set_R_window_id (cmd, WD_wid_front); 8735141cc406Sopenharmony_ci } 8736141cc406Sopenharmony_ci 8737141cc406Sopenharmony_ci set_R_xfer_length (cmd, inLen); 8738141cc406Sopenharmony_ci 8739141cc406Sopenharmony_ci ret = do_cmd ( 8740141cc406Sopenharmony_ci s, 1, 0, 8741141cc406Sopenharmony_ci cmd, cmdLen, 8742141cc406Sopenharmony_ci NULL, 0, 8743141cc406Sopenharmony_ci in, &inLen 8744141cc406Sopenharmony_ci ); 8745141cc406Sopenharmony_ci 8746141cc406Sopenharmony_ci if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { 8747141cc406Sopenharmony_ci DBG(15, "read_from_scanner: got GOOD/EOF, returning GOOD\n"); 8748141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 8749141cc406Sopenharmony_ci } 8750141cc406Sopenharmony_ci else if (ret == SANE_STATUS_DEVICE_BUSY) { 8751141cc406Sopenharmony_ci DBG(5, "read_from_scanner: got BUSY, returning GOOD\n"); 8752141cc406Sopenharmony_ci inLen = 0; 8753141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 8754141cc406Sopenharmony_ci } 8755141cc406Sopenharmony_ci else { 8756141cc406Sopenharmony_ci DBG(5, "read_from_scanner: error reading data block status = %d\n",ret); 8757141cc406Sopenharmony_ci inLen = 0; 8758141cc406Sopenharmony_ci } 8759141cc406Sopenharmony_ci 8760141cc406Sopenharmony_ci DBG(15, "read_from_scanner: read %lu bytes\n",(unsigned long)inLen); 8761141cc406Sopenharmony_ci 8762141cc406Sopenharmony_ci if(inLen){ 8763141cc406Sopenharmony_ci if(s->s_mode==MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ 8764141cc406Sopenharmony_ci copy_3091 (s, in, inLen, side); 8765141cc406Sopenharmony_ci } 8766141cc406Sopenharmony_ci else if(s->s_params.format == SANE_FRAME_JPEG){ 8767141cc406Sopenharmony_ci copy_JPEG (s, in, inLen, side); 8768141cc406Sopenharmony_ci } 8769141cc406Sopenharmony_ci else{ 8770141cc406Sopenharmony_ci copy_buffer (s, in, inLen, side); 8771141cc406Sopenharmony_ci } 8772141cc406Sopenharmony_ci } 8773141cc406Sopenharmony_ci 8774141cc406Sopenharmony_ci free(in); 8775141cc406Sopenharmony_ci 8776141cc406Sopenharmony_ci /* if this was a short read or not, log it */ 8777141cc406Sopenharmony_ci s->ili_rx[side] = s->rs_ili; 8778141cc406Sopenharmony_ci if(s->ili_rx[side]){ 8779141cc406Sopenharmony_ci DBG(15, "read_from_scanner: got ILI\n"); 8780141cc406Sopenharmony_ci } 8781141cc406Sopenharmony_ci 8782141cc406Sopenharmony_ci /* if this was an end of medium, log it */ 8783141cc406Sopenharmony_ci if(s->rs_eom){ 8784141cc406Sopenharmony_ci DBG(15, "read_from_scanner: got EOM\n"); 8785141cc406Sopenharmony_ci s->eom_rx = 1; 8786141cc406Sopenharmony_ci } 8787141cc406Sopenharmony_ci 8788141cc406Sopenharmony_ci /* paper ran out. lets try to set the eof flag on both sides, 8789141cc406Sopenharmony_ci * but only if that side had a short read last time */ 8790141cc406Sopenharmony_ci if(s->eom_rx){ 8791141cc406Sopenharmony_ci int i; 8792141cc406Sopenharmony_ci for(i=0;i<2;i++){ 8793141cc406Sopenharmony_ci if(s->ili_rx[i]){ 8794141cc406Sopenharmony_ci DBG(15, "read_from_scanner: finishing side %d\n",i); 8795141cc406Sopenharmony_ci s->eof_rx[i] = 1; 8796141cc406Sopenharmony_ci } 8797141cc406Sopenharmony_ci } 8798141cc406Sopenharmony_ci } 8799141cc406Sopenharmony_ci 8800141cc406Sopenharmony_ci DBG (10, "read_from_scanner: finish\n"); 8801141cc406Sopenharmony_ci 8802141cc406Sopenharmony_ci return ret; 8803141cc406Sopenharmony_ci} 8804141cc406Sopenharmony_ci 8805141cc406Sopenharmony_cistatic SANE_Status 8806141cc406Sopenharmony_cicopy_3091(struct fujitsu *s, unsigned char * buf, int len, int side) 8807141cc406Sopenharmony_ci{ 8808141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8809141cc406Sopenharmony_ci int i, j, dest, boff, goff; 8810141cc406Sopenharmony_ci 8811141cc406Sopenharmony_ci DBG (10, "copy_3091: start\n"); 8812141cc406Sopenharmony_ci 8813141cc406Sopenharmony_ci /* Data is RR...GG...BB... on each line, 8814141cc406Sopenharmony_ci * green is back 8 lines from red at 300 dpi 8815141cc406Sopenharmony_ci * blue is back 4 lines from red at 300 dpi. 8816141cc406Sopenharmony_ci * 8817141cc406Sopenharmony_ci * Here, we get things on correct line, and 8818141cc406Sopenharmony_ci * interlace to make RGBRGB. 8819141cc406Sopenharmony_ci * 8820141cc406Sopenharmony_ci * We add the user-supplied offsets before we scale 8821141cc406Sopenharmony_ci * so that they are independent of scanning resolution. 8822141cc406Sopenharmony_ci */ 8823141cc406Sopenharmony_ci goff = (s->color_raster_offset+s->green_offset) * s->resolution_y/150; 8824141cc406Sopenharmony_ci boff = (s->color_raster_offset+s->blue_offset) * s->resolution_y/300; 8825141cc406Sopenharmony_ci 8826141cc406Sopenharmony_ci /* loop thru all lines in read buffer */ 8827141cc406Sopenharmony_ci for(i=0;i<len;i+=s->s_params.bytes_per_line){ 8828141cc406Sopenharmony_ci 8829141cc406Sopenharmony_ci /* red at start of line */ 8830141cc406Sopenharmony_ci dest = s->lines_rx[side] * s->s_params.bytes_per_line; 8831141cc406Sopenharmony_ci 8832141cc406Sopenharmony_ci if(dest >= 0 && dest < s->bytes_tot[side]){ 8833141cc406Sopenharmony_ci for (j=0; j<s->s_params.pixels_per_line; j++){ 8834141cc406Sopenharmony_ci s->buffers[side][dest+j*3] = buf[i+j]; 8835141cc406Sopenharmony_ci } 8836141cc406Sopenharmony_ci } 8837141cc406Sopenharmony_ci 8838141cc406Sopenharmony_ci /* green is in middle of line */ 8839141cc406Sopenharmony_ci dest = (s->lines_rx[side] - goff) * s->s_params.bytes_per_line; 8840141cc406Sopenharmony_ci 8841141cc406Sopenharmony_ci if(dest >= 0 && dest < s->bytes_tot[side]){ 8842141cc406Sopenharmony_ci for (j=0; j<s->s_params.pixels_per_line; j++){ 8843141cc406Sopenharmony_ci s->buffers[side][dest+j*3+1] = buf[i+s->s_params.pixels_per_line+j]; 8844141cc406Sopenharmony_ci } 8845141cc406Sopenharmony_ci } 8846141cc406Sopenharmony_ci 8847141cc406Sopenharmony_ci /* blue is at end of line */ 8848141cc406Sopenharmony_ci dest = (s->lines_rx[side] - boff) * s->s_params.bytes_per_line; 8849141cc406Sopenharmony_ci 8850141cc406Sopenharmony_ci if(dest >= 0 && dest < s->bytes_tot[side]){ 8851141cc406Sopenharmony_ci for (j=0; j<s->s_params.pixels_per_line; j++){ 8852141cc406Sopenharmony_ci s->buffers[side][dest+j*3+2] = buf[i+2*s->s_params.pixels_per_line+j]; 8853141cc406Sopenharmony_ci } 8854141cc406Sopenharmony_ci } 8855141cc406Sopenharmony_ci 8856141cc406Sopenharmony_ci s->lines_rx[side]++; 8857141cc406Sopenharmony_ci } 8858141cc406Sopenharmony_ci 8859141cc406Sopenharmony_ci /* even if we have read data, we may not have any 8860141cc406Sopenharmony_ci * full lines loaded yet, so we may have to lie */ 8861141cc406Sopenharmony_ci i = (s->lines_rx[side]-goff) * s->s_params.bytes_per_line; 8862141cc406Sopenharmony_ci if(i < 0){ 8863141cc406Sopenharmony_ci i = 0; 8864141cc406Sopenharmony_ci } 8865141cc406Sopenharmony_ci s->bytes_rx[side] = i; 8866141cc406Sopenharmony_ci s->buff_rx[side] = i; 8867141cc406Sopenharmony_ci 8868141cc406Sopenharmony_ci if(s->bytes_rx[side] == s->bytes_tot[side]){ 8869141cc406Sopenharmony_ci s->eof_rx[side] = 1; 8870141cc406Sopenharmony_ci } 8871141cc406Sopenharmony_ci 8872141cc406Sopenharmony_ci DBG(15, "copy_3091: si:%d imgrx:%d bufrx:%d li:%d eof:%d\n", 8873141cc406Sopenharmony_ci side, s->bytes_rx[side], s->buff_rx[side], s->lines_rx[side], 8874141cc406Sopenharmony_ci s->eof_rx[side]); 8875141cc406Sopenharmony_ci 8876141cc406Sopenharmony_ci DBG (10, "copy_3091: finish\n"); 8877141cc406Sopenharmony_ci 8878141cc406Sopenharmony_ci return ret; 8879141cc406Sopenharmony_ci} 8880141cc406Sopenharmony_ci 8881141cc406Sopenharmony_cistatic SANE_Status 8882141cc406Sopenharmony_cicopy_JPEG(struct fujitsu *s, unsigned char * buf, int len, int side) 8883141cc406Sopenharmony_ci{ 8884141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8885141cc406Sopenharmony_ci int i, seen = 0; 8886141cc406Sopenharmony_ci 8887141cc406Sopenharmony_ci DBG (10, "copy_JPEG: start\n"); 8888141cc406Sopenharmony_ci 8889141cc406Sopenharmony_ci /* A jpeg image starts with the SOI marker, FF D8. 8890141cc406Sopenharmony_ci * This is optionally followed by the JFIF APP0 8891141cc406Sopenharmony_ci * marker, FF E0. If that marker is not present, 8892141cc406Sopenharmony_ci * we add it, so we can insert the resolution */ 8893141cc406Sopenharmony_ci 8894141cc406Sopenharmony_ci if(!s->bytes_rx[side] && len >= 4 8895141cc406Sopenharmony_ci && buf[0] == 0xFF && buf[1] == 0xD8 8896141cc406Sopenharmony_ci && buf[2] == 0xFF && buf[3] != 0xE0 8897141cc406Sopenharmony_ci ){ 8898141cc406Sopenharmony_ci /* SOI marker */ 8899141cc406Sopenharmony_ci for (i=0; i<2; i++){ 8900141cc406Sopenharmony_ci s->buffers[side][s->buff_rx[side]++] = buf[i]; 8901141cc406Sopenharmony_ci s->bytes_rx[side]++; 8902141cc406Sopenharmony_ci seen++; 8903141cc406Sopenharmony_ci } 8904141cc406Sopenharmony_ci 8905141cc406Sopenharmony_ci /* JFIF header after SOI */ 8906141cc406Sopenharmony_ci inject_jfif_header(s,side); 8907141cc406Sopenharmony_ci } 8908141cc406Sopenharmony_ci 8909141cc406Sopenharmony_ci memcpy(s->buffers[side]+s->buff_rx[side],buf+seen,len-seen); 8910141cc406Sopenharmony_ci s->buff_rx[side] += len-seen; 8911141cc406Sopenharmony_ci s->bytes_rx[side] += len-seen; 8912141cc406Sopenharmony_ci 8913141cc406Sopenharmony_ci /* should never happen with jpeg */ 8914141cc406Sopenharmony_ci if(s->bytes_rx[side] == s->bytes_tot[side]){ 8915141cc406Sopenharmony_ci s->eof_rx[side] = 1; 8916141cc406Sopenharmony_ci } 8917141cc406Sopenharmony_ci 8918141cc406Sopenharmony_ci DBG (10, "copy_JPEG: finish\n"); 8919141cc406Sopenharmony_ci 8920141cc406Sopenharmony_ci return ret; 8921141cc406Sopenharmony_ci} 8922141cc406Sopenharmony_ci 8923141cc406Sopenharmony_cistatic SANE_Status 8924141cc406Sopenharmony_cicopy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side) 8925141cc406Sopenharmony_ci{ 8926141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8927141cc406Sopenharmony_ci int i, j; 8928141cc406Sopenharmony_ci int bwidth = s->s_params.bytes_per_line; 8929141cc406Sopenharmony_ci int pwidth = s->s_params.pixels_per_line; 8930141cc406Sopenharmony_ci 8931141cc406Sopenharmony_ci DBG (10, "copy_buffer: start\n"); 8932141cc406Sopenharmony_ci 8933141cc406Sopenharmony_ci /* invert image if scanner needs it for this mode */ 8934141cc406Sopenharmony_ci /* jpeg data does not use inverting */ 8935141cc406Sopenharmony_ci if(s->s_params.format != SANE_FRAME_JPEG && s->reverse_by_mode[s->s_mode]){ 8936141cc406Sopenharmony_ci for(i=0; i<len; i++){ 8937141cc406Sopenharmony_ci buf[i] ^= 0xff; 8938141cc406Sopenharmony_ci } 8939141cc406Sopenharmony_ci } 8940141cc406Sopenharmony_ci 8941141cc406Sopenharmony_ci /* scanners interlace colors in many different ways */ 8942141cc406Sopenharmony_ci if(s->s_params.format == SANE_FRAME_RGB){ 8943141cc406Sopenharmony_ci 8944141cc406Sopenharmony_ci switch (s->color_interlace) { 8945141cc406Sopenharmony_ci 8946141cc406Sopenharmony_ci /* scanner returns pixel data as bgrbgr... */ 8947141cc406Sopenharmony_ci case COLOR_INTERLACE_BGR: 8948141cc406Sopenharmony_ci for(i=0; i<len; i+=bwidth){ 8949141cc406Sopenharmony_ci for (j=0; j<pwidth; j++){ 8950141cc406Sopenharmony_ci s->buffers[side][s->buff_rx[side]++] = buf[i+j*3+2]; 8951141cc406Sopenharmony_ci s->buffers[side][s->buff_rx[side]++] = buf[i+j*3+1]; 8952141cc406Sopenharmony_ci s->buffers[side][s->buff_rx[side]++] = buf[i+j*3]; 8953141cc406Sopenharmony_ci } 8954141cc406Sopenharmony_ci } 8955141cc406Sopenharmony_ci break; 8956141cc406Sopenharmony_ci 8957141cc406Sopenharmony_ci /* one line has the following format: rrr...rrrggg...gggbbb...bbb */ 8958141cc406Sopenharmony_ci case COLOR_INTERLACE_RRGGBB: 8959141cc406Sopenharmony_ci for(i=0; i<len; i+=bwidth){ 8960141cc406Sopenharmony_ci for (j=0; j<pwidth; j++){ 8961141cc406Sopenharmony_ci s->buffers[side][s->buff_rx[side]++] = buf[i+j]; 8962141cc406Sopenharmony_ci s->buffers[side][s->buff_rx[side]++] = buf[i+pwidth+j]; 8963141cc406Sopenharmony_ci s->buffers[side][s->buff_rx[side]++] = buf[i+2*pwidth+j]; 8964141cc406Sopenharmony_ci } 8965141cc406Sopenharmony_ci } 8966141cc406Sopenharmony_ci break; 8967141cc406Sopenharmony_ci 8968141cc406Sopenharmony_ci default: 8969141cc406Sopenharmony_ci memcpy(s->buffers[side]+s->buff_rx[side],buf,len); 8970141cc406Sopenharmony_ci s->buff_rx[side] += len; 8971141cc406Sopenharmony_ci break; 8972141cc406Sopenharmony_ci } 8973141cc406Sopenharmony_ci } 8974141cc406Sopenharmony_ci 8975141cc406Sopenharmony_ci /* jpeg/gray/ht/binary */ 8976141cc406Sopenharmony_ci else{ 8977141cc406Sopenharmony_ci memcpy(s->buffers[side]+s->buff_rx[side],buf,len); 8978141cc406Sopenharmony_ci s->buff_rx[side] += len; 8979141cc406Sopenharmony_ci } 8980141cc406Sopenharmony_ci 8981141cc406Sopenharmony_ci s->bytes_rx[side] += len; 8982141cc406Sopenharmony_ci s->lines_rx[side] += len/s->s_params.bytes_per_line; 8983141cc406Sopenharmony_ci 8984141cc406Sopenharmony_ci if(s->bytes_rx[side] == s->bytes_tot[side]){ 8985141cc406Sopenharmony_ci s->eof_rx[side] = 1; 8986141cc406Sopenharmony_ci } 8987141cc406Sopenharmony_ci 8988141cc406Sopenharmony_ci DBG (10, "copy_buffer: finish\n"); 8989141cc406Sopenharmony_ci 8990141cc406Sopenharmony_ci return ret; 8991141cc406Sopenharmony_ci} 8992141cc406Sopenharmony_ci 8993141cc406Sopenharmony_cistatic SANE_Status 8994141cc406Sopenharmony_ciread_from_buffer(struct fujitsu *s, SANE_Byte * buf, 8995141cc406Sopenharmony_ci SANE_Int max_len, SANE_Int * len, int side) 8996141cc406Sopenharmony_ci{ 8997141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 8998141cc406Sopenharmony_ci int bytes = max_len; 8999141cc406Sopenharmony_ci int remain = s->buff_rx[side] - s->buff_tx[side]; 9000141cc406Sopenharmony_ci 9001141cc406Sopenharmony_ci DBG (10, "read_from_buffer: start\n"); 9002141cc406Sopenharmony_ci 9003141cc406Sopenharmony_ci /* figure out the max amount to transfer */ 9004141cc406Sopenharmony_ci if(bytes > remain){ 9005141cc406Sopenharmony_ci bytes = remain; 9006141cc406Sopenharmony_ci } 9007141cc406Sopenharmony_ci 9008141cc406Sopenharmony_ci *len = bytes; 9009141cc406Sopenharmony_ci 9010141cc406Sopenharmony_ci DBG(15, "read_from_buffer: si:%d re:%d ml:%d by:%d\n", 9011141cc406Sopenharmony_ci side, remain, max_len, bytes); 9012141cc406Sopenharmony_ci 9013141cc406Sopenharmony_ci DBG(15, "read_from_buffer: img to:%d rx:%d tx:%d\n", 9014141cc406Sopenharmony_ci s->bytes_tot[side], s->bytes_rx[side], s->bytes_tx[side]); 9015141cc406Sopenharmony_ci 9016141cc406Sopenharmony_ci DBG(15, "read_from_buffer: buf to:%d rx:%d tx:%d\n", 9017141cc406Sopenharmony_ci s->buff_tot[side], s->buff_rx[side], s->buff_tx[side]); 9018141cc406Sopenharmony_ci 9019141cc406Sopenharmony_ci /*FIXME this needs to timeout eventually */ 9020141cc406Sopenharmony_ci if(!bytes){ 9021141cc406Sopenharmony_ci DBG(5,"read_from_buffer: nothing to do\n"); 9022141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 9023141cc406Sopenharmony_ci } 9024141cc406Sopenharmony_ci 9025141cc406Sopenharmony_ci memcpy(buf,s->buffers[side]+s->buff_tx[side],bytes); 9026141cc406Sopenharmony_ci s->buff_tx[side] += bytes; 9027141cc406Sopenharmony_ci s->bytes_tx[side] += bytes; 9028141cc406Sopenharmony_ci 9029141cc406Sopenharmony_ci DBG (10, "read_from_buffer: finish\n"); 9030141cc406Sopenharmony_ci 9031141cc406Sopenharmony_ci return ret; 9032141cc406Sopenharmony_ci} 9033141cc406Sopenharmony_ci 9034141cc406Sopenharmony_ci/* we have bytes of higher mode image data in s->buffers */ 9035141cc406Sopenharmony_ci/* user asked for lower mode image. downsample and copy to buf */ 9036141cc406Sopenharmony_ci 9037141cc406Sopenharmony_cistatic SANE_Status 9038141cc406Sopenharmony_cidownsample_from_buffer(struct fujitsu *s, SANE_Byte * buf, 9039141cc406Sopenharmony_ci SANE_Int max_len, SANE_Int * len, int side) 9040141cc406Sopenharmony_ci{ 9041141cc406Sopenharmony_ci SANE_Status ret=SANE_STATUS_GOOD; 9042141cc406Sopenharmony_ci 9043141cc406Sopenharmony_ci DBG (10, "downsample_from_buffer: start %d %d %d %d\n", s->bytes_rx[side], s->bytes_tx[side], s->buff_rx[side], s->buff_tx[side]); 9044141cc406Sopenharmony_ci 9045141cc406Sopenharmony_ci if(s->s_mode == MODE_COLOR && s->u_mode == MODE_GRAYSCALE){ 9046141cc406Sopenharmony_ci 9047141cc406Sopenharmony_ci while(*len < max_len && s->buff_rx[side] - s->buff_tx[side] >= 3){ 9048141cc406Sopenharmony_ci 9049141cc406Sopenharmony_ci int gray = 0; 9050141cc406Sopenharmony_ci 9051141cc406Sopenharmony_ci switch (s->dropout_color) { 9052141cc406Sopenharmony_ci case COLOR_RED: 9053141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]) * 3; 9054141cc406Sopenharmony_ci break; 9055141cc406Sopenharmony_ci case COLOR_GREEN: 9056141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]+1) * 3; 9057141cc406Sopenharmony_ci break; 9058141cc406Sopenharmony_ci case COLOR_BLUE: 9059141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]+2) * 3; 9060141cc406Sopenharmony_ci break; 9061141cc406Sopenharmony_ci default: 9062141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]) 9063141cc406Sopenharmony_ci + *(s->buffers[side]+s->buff_tx[side]+1) 9064141cc406Sopenharmony_ci + *(s->buffers[side]+s->buff_tx[side]+2); 9065141cc406Sopenharmony_ci break; 9066141cc406Sopenharmony_ci } 9067141cc406Sopenharmony_ci 9068141cc406Sopenharmony_ci /* bookkeeping for input */ 9069141cc406Sopenharmony_ci s->buff_tx[side] += 3; 9070141cc406Sopenharmony_ci s->bytes_tx[side] += 3; 9071141cc406Sopenharmony_ci 9072141cc406Sopenharmony_ci /* add byte to output */ 9073141cc406Sopenharmony_ci *(buf + *len) = gray/3; 9074141cc406Sopenharmony_ci (*len)++; 9075141cc406Sopenharmony_ci } 9076141cc406Sopenharmony_ci } 9077141cc406Sopenharmony_ci 9078141cc406Sopenharmony_ci else if(s->s_mode == MODE_COLOR && s->u_mode == MODE_LINEART){ 9079141cc406Sopenharmony_ci 9080141cc406Sopenharmony_ci /* threshold of 0 is actually middle of range */ 9081141cc406Sopenharmony_ci /*FIXME: add dynamic threshold? */ 9082141cc406Sopenharmony_ci unsigned char thresh = (s->threshold ? s->threshold : 127); 9083141cc406Sopenharmony_ci 9084141cc406Sopenharmony_ci while(*len < max_len && s->buff_rx[side] - s->buff_tx[side] >= 24){ 9085141cc406Sopenharmony_ci 9086141cc406Sopenharmony_ci int i; 9087141cc406Sopenharmony_ci unsigned char out = 0; 9088141cc406Sopenharmony_ci 9089141cc406Sopenharmony_ci for(i=0; i<8; i++){ 9090141cc406Sopenharmony_ci 9091141cc406Sopenharmony_ci int gray = 0; 9092141cc406Sopenharmony_ci 9093141cc406Sopenharmony_ci switch (s->dropout_color) { 9094141cc406Sopenharmony_ci case COLOR_RED: 9095141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]) * 3; 9096141cc406Sopenharmony_ci break; 9097141cc406Sopenharmony_ci case COLOR_GREEN: 9098141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]+1) * 3; 9099141cc406Sopenharmony_ci break; 9100141cc406Sopenharmony_ci case COLOR_BLUE: 9101141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]+2) * 3; 9102141cc406Sopenharmony_ci break; 9103141cc406Sopenharmony_ci default: 9104141cc406Sopenharmony_ci gray = *(s->buffers[side]+s->buff_tx[side]) 9105141cc406Sopenharmony_ci + *(s->buffers[side]+s->buff_tx[side]+1) 9106141cc406Sopenharmony_ci + *(s->buffers[side]+s->buff_tx[side]+2); 9107141cc406Sopenharmony_ci break; 9108141cc406Sopenharmony_ci } 9109141cc406Sopenharmony_ci 9110141cc406Sopenharmony_ci /* black if input gray is lower than threshold */ 9111141cc406Sopenharmony_ci if(gray/3 < thresh){ 9112141cc406Sopenharmony_ci out |= (0x80 >> i); 9113141cc406Sopenharmony_ci } 9114141cc406Sopenharmony_ci 9115141cc406Sopenharmony_ci /* bookkeeping for input */ 9116141cc406Sopenharmony_ci s->buff_tx[side] += 3; 9117141cc406Sopenharmony_ci s->bytes_tx[side] += 3; 9118141cc406Sopenharmony_ci } 9119141cc406Sopenharmony_ci 9120141cc406Sopenharmony_ci /* add byte to output */ 9121141cc406Sopenharmony_ci *(buf + *len) = out; 9122141cc406Sopenharmony_ci (*len)++; 9123141cc406Sopenharmony_ci } 9124141cc406Sopenharmony_ci } 9125141cc406Sopenharmony_ci 9126141cc406Sopenharmony_ci else{ 9127141cc406Sopenharmony_ci DBG (5, "downsample_from_buffer: invalid mode combination\n"); 9128141cc406Sopenharmony_ci ret = SANE_STATUS_INVAL; 9129141cc406Sopenharmony_ci } 9130141cc406Sopenharmony_ci 9131141cc406Sopenharmony_ci DBG (10, "downsample_from_buffer: finish %d %d %d %d\n", s->bytes_rx[side], s->bytes_tx[side], s->buff_rx[side], s->buff_tx[side]); 9132141cc406Sopenharmony_ci 9133141cc406Sopenharmony_ci return ret; 9134141cc406Sopenharmony_ci} 9135141cc406Sopenharmony_ci 9136141cc406Sopenharmony_ci 9137141cc406Sopenharmony_ci/* 9138141cc406Sopenharmony_ci * @@ Section 5 - SANE cleanup functions 9139141cc406Sopenharmony_ci */ 9140141cc406Sopenharmony_ci/* 9141141cc406Sopenharmony_ci * Cancels a scan. 9142141cc406Sopenharmony_ci * 9143141cc406Sopenharmony_ci * It has been said on the mailing list that sane_cancel is a bit of a 9144141cc406Sopenharmony_ci * misnomer because it is routinely called to signal the end of a 9145141cc406Sopenharmony_ci * batch - quoting David Mosberger-Tang: 9146141cc406Sopenharmony_ci * 9147141cc406Sopenharmony_ci * > In other words, the idea is to have sane_start() be called, and 9148141cc406Sopenharmony_ci * > collect as many images as the frontend wants (which could in turn 9149141cc406Sopenharmony_ci * > consist of multiple frames each as indicated by frame-type) and 9150141cc406Sopenharmony_ci * > when the frontend is done, it should call sane_cancel(). 9151141cc406Sopenharmony_ci * > Sometimes it's better to think of sane_cancel() as "sane_stop()" 9152141cc406Sopenharmony_ci * > but that name would have had some misleading connotations as 9153141cc406Sopenharmony_ci * > well, that's why we stuck with "cancel". 9154141cc406Sopenharmony_ci * 9155141cc406Sopenharmony_ci * The current consensus regarding duplex and ADF scans seems to be 9156141cc406Sopenharmony_ci * the following call sequence: sane_start; sane_read (repeat until 9157141cc406Sopenharmony_ci * EOF); sane_start; sane_read... and then call sane_cancel if the 9158141cc406Sopenharmony_ci * batch is at an end. I.e. do not call sane_cancel during the run but 9159141cc406Sopenharmony_ci * as soon as you get a SANE_STATUS_NO_DOCS. 9160141cc406Sopenharmony_ci * 9161141cc406Sopenharmony_ci * From the SANE spec: 9162141cc406Sopenharmony_ci * This function is used to immediately or as quickly as possible 9163141cc406Sopenharmony_ci * cancel the currently pending operation of the device represented by 9164141cc406Sopenharmony_ci * handle h. This function can be called at any time (as long as 9165141cc406Sopenharmony_ci * handle h is a valid handle) but usually affects long-running 9166141cc406Sopenharmony_ci * operations only (such as image is acquisition). It is safe to call 9167141cc406Sopenharmony_ci * this function asynchronously (e.g., from within a signal handler). 9168141cc406Sopenharmony_ci * It is important to note that completion of this operation does not 9169141cc406Sopenharmony_ci * imply that the currently pending operation has been cancelled. It 9170141cc406Sopenharmony_ci * only guarantees that cancellation has been initiated. Cancellation 9171141cc406Sopenharmony_ci * completes only when the cancelled call returns (typically with a 9172141cc406Sopenharmony_ci * status value of SANE_STATUS_CANCELLED). Since the SANE API does 9173141cc406Sopenharmony_ci * not require any other operations to be re-entrant, this implies 9174141cc406Sopenharmony_ci * that a frontend must not call any other operation until the 9175141cc406Sopenharmony_ci * cancelled operation has returned. 9176141cc406Sopenharmony_ci */ 9177141cc406Sopenharmony_civoid 9178141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 9179141cc406Sopenharmony_ci{ 9180141cc406Sopenharmony_ci struct fujitsu * s = (struct fujitsu *) handle; 9181141cc406Sopenharmony_ci 9182141cc406Sopenharmony_ci DBG (10, "sane_cancel: start\n"); 9183141cc406Sopenharmony_ci s->cancelled = 1; 9184141cc406Sopenharmony_ci 9185141cc406Sopenharmony_ci /* if there is no other running function to check, we do it */ 9186141cc406Sopenharmony_ci if(!s->reading) 9187141cc406Sopenharmony_ci check_for_cancel(s); 9188141cc406Sopenharmony_ci 9189141cc406Sopenharmony_ci DBG (10, "sane_cancel: finish\n"); 9190141cc406Sopenharmony_ci} 9191141cc406Sopenharmony_ci 9192141cc406Sopenharmony_ci/* 9193141cc406Sopenharmony_ci * Ends use of the scanner. 9194141cc406Sopenharmony_ci * 9195141cc406Sopenharmony_ci * From the SANE spec: 9196141cc406Sopenharmony_ci * This function terminates the association between the device handle 9197141cc406Sopenharmony_ci * passed in argument h and the device it represents. If the device is 9198141cc406Sopenharmony_ci * presently active, a call to sane_cancel() is performed first. After 9199141cc406Sopenharmony_ci * this function returns, handle h must not be used anymore. 9200141cc406Sopenharmony_ci */ 9201141cc406Sopenharmony_civoid 9202141cc406Sopenharmony_cisane_close (SANE_Handle handle) 9203141cc406Sopenharmony_ci{ 9204141cc406Sopenharmony_ci struct fujitsu * s = (struct fujitsu *) handle; 9205141cc406Sopenharmony_ci 9206141cc406Sopenharmony_ci DBG (10, "sane_close: start\n"); 9207141cc406Sopenharmony_ci /*clears any held scans*/ 9208141cc406Sopenharmony_ci mode_select_buff(s); 9209141cc406Sopenharmony_ci disconnect_fd(s); 9210141cc406Sopenharmony_ci DBG (10, "sane_close: finish\n"); 9211141cc406Sopenharmony_ci} 9212141cc406Sopenharmony_ci 9213141cc406Sopenharmony_cistatic SANE_Status 9214141cc406Sopenharmony_cidisconnect_fd (struct fujitsu *s) 9215141cc406Sopenharmony_ci{ 9216141cc406Sopenharmony_ci DBG (10, "disconnect_fd: start\n"); 9217141cc406Sopenharmony_ci 9218141cc406Sopenharmony_ci if(s->fd > -1){ 9219141cc406Sopenharmony_ci if (s->connection == CONNECTION_USB) { 9220141cc406Sopenharmony_ci DBG (15, "disconnecting usb device\n"); 9221141cc406Sopenharmony_ci sanei_usb_close (s->fd); 9222141cc406Sopenharmony_ci } 9223141cc406Sopenharmony_ci else if (s->connection == CONNECTION_SCSI) { 9224141cc406Sopenharmony_ci DBG (15, "disconnecting scsi device\n"); 9225141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 9226141cc406Sopenharmony_ci } 9227141cc406Sopenharmony_ci s->fd = -1; 9228141cc406Sopenharmony_ci } 9229141cc406Sopenharmony_ci 9230141cc406Sopenharmony_ci DBG (10, "disconnect_fd: finish\n"); 9231141cc406Sopenharmony_ci 9232141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 9233141cc406Sopenharmony_ci} 9234141cc406Sopenharmony_ci 9235141cc406Sopenharmony_ci/* 9236141cc406Sopenharmony_ci * Terminates the backend. 9237141cc406Sopenharmony_ci * 9238141cc406Sopenharmony_ci * From the SANE spec: 9239141cc406Sopenharmony_ci * This function must be called to terminate use of a backend. The 9240141cc406Sopenharmony_ci * function will first close all device handles that still might be 9241141cc406Sopenharmony_ci * open (it is recommended to close device handles explicitly through 9242141cc406Sopenharmony_ci * a call to sane_close(), but backends are required to release all 9243141cc406Sopenharmony_ci * resources upon a call to this function). After this function 9244141cc406Sopenharmony_ci * returns, no function other than sane_init() may be called 9245141cc406Sopenharmony_ci * (regardless of the status value returned by sane_exit(). Neglecting 9246141cc406Sopenharmony_ci * to call this function may result in some resources not being 9247141cc406Sopenharmony_ci * released properly. 9248141cc406Sopenharmony_ci */ 9249141cc406Sopenharmony_civoid 9250141cc406Sopenharmony_cisane_exit (void) 9251141cc406Sopenharmony_ci{ 9252141cc406Sopenharmony_ci struct fujitsu *dev, *next; 9253141cc406Sopenharmony_ci 9254141cc406Sopenharmony_ci DBG (10, "sane_exit: start\n"); 9255141cc406Sopenharmony_ci 9256141cc406Sopenharmony_ci for (dev = fujitsu_devList; dev; dev = next) { 9257141cc406Sopenharmony_ci disconnect_fd(dev); 9258141cc406Sopenharmony_ci next = dev->next; 9259141cc406Sopenharmony_ci free (dev); 9260141cc406Sopenharmony_ci } 9261141cc406Sopenharmony_ci 9262141cc406Sopenharmony_ci if (sane_devArray) 9263141cc406Sopenharmony_ci free (sane_devArray); 9264141cc406Sopenharmony_ci 9265141cc406Sopenharmony_ci fujitsu_devList = NULL; 9266141cc406Sopenharmony_ci sane_devArray = NULL; 9267141cc406Sopenharmony_ci 9268141cc406Sopenharmony_ci DBG (10, "sane_exit: finish\n"); 9269141cc406Sopenharmony_ci} 9270141cc406Sopenharmony_ci 9271141cc406Sopenharmony_ci/* 9272141cc406Sopenharmony_ci * @@ Section 6 - misc helper functions 9273141cc406Sopenharmony_ci */ 9274141cc406Sopenharmony_ci/* 9275141cc406Sopenharmony_ci * Called by the SANE SCSI core and our usb code on device errors 9276141cc406Sopenharmony_ci * parses the request sense return data buffer, 9277141cc406Sopenharmony_ci * decides the best SANE_Status for the problem, produces debug msgs, 9278141cc406Sopenharmony_ci * and copies the sense buffer into the scanner struct 9279141cc406Sopenharmony_ci */ 9280141cc406Sopenharmony_cistatic SANE_Status 9281141cc406Sopenharmony_cisense_handler (int fd, unsigned char * sensed_data, void *arg) 9282141cc406Sopenharmony_ci{ 9283141cc406Sopenharmony_ci struct fujitsu *s = arg; 9284141cc406Sopenharmony_ci unsigned int sense = get_RS_sense_key (sensed_data); 9285141cc406Sopenharmony_ci unsigned int asc = get_RS_ASC (sensed_data); 9286141cc406Sopenharmony_ci unsigned int ascq = get_RS_ASCQ (sensed_data); 9287141cc406Sopenharmony_ci 9288141cc406Sopenharmony_ci DBG (5, "sense_handler: start\n"); 9289141cc406Sopenharmony_ci 9290141cc406Sopenharmony_ci /* kill compiler warning */ 9291141cc406Sopenharmony_ci (void) fd; 9292141cc406Sopenharmony_ci 9293141cc406Sopenharmony_ci /* copy the rs return data into the scanner struct 9294141cc406Sopenharmony_ci so that the caller can use it if he wants */ 9295141cc406Sopenharmony_ci s->rs_info = get_RS_information (sensed_data); 9296141cc406Sopenharmony_ci s->rs_eom = get_RS_EOM (sensed_data); 9297141cc406Sopenharmony_ci s->rs_ili = get_RS_ILI (sensed_data); 9298141cc406Sopenharmony_ci 9299141cc406Sopenharmony_ci DBG (5, "Sense=%#02x, ASC=%#02x, ASCQ=%#02x, EOM=%d, ILI=%d, info=%#08lx\n", sense, asc, ascq, s->rs_eom, s->rs_ili, (unsigned long)s->rs_info); 9300141cc406Sopenharmony_ci 9301141cc406Sopenharmony_ci switch (sense) { 9302141cc406Sopenharmony_ci case 0x0: 9303141cc406Sopenharmony_ci if (0x80 == asc) { 9304141cc406Sopenharmony_ci DBG (5, "No sense: hardware status bits?\n"); 9305141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 9306141cc406Sopenharmony_ci } 9307141cc406Sopenharmony_ci if (0x00 != asc) { 9308141cc406Sopenharmony_ci DBG (5, "No sense: unknown asc\n"); 9309141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9310141cc406Sopenharmony_ci } 9311141cc406Sopenharmony_ci if (0x00 != ascq) { 9312141cc406Sopenharmony_ci DBG (5, "No sense: unknown ascq\n"); 9313141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9314141cc406Sopenharmony_ci } 9315141cc406Sopenharmony_ci /* ready, but short read */ 9316141cc406Sopenharmony_ci if (s->rs_ili) { 9317141cc406Sopenharmony_ci DBG (5, "No sense: ILI remainder:%lu\n",(unsigned long)s->rs_info); 9318141cc406Sopenharmony_ci } 9319141cc406Sopenharmony_ci /* ready, but end of paper */ 9320141cc406Sopenharmony_ci if (s->rs_eom) { 9321141cc406Sopenharmony_ci DBG (5, "No sense: EOM\n"); 9322141cc406Sopenharmony_ci return SANE_STATUS_EOF; 9323141cc406Sopenharmony_ci } 9324141cc406Sopenharmony_ci DBG (5, "No sense: ready\n"); 9325141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 9326141cc406Sopenharmony_ci 9327141cc406Sopenharmony_ci case 0x2: 9328141cc406Sopenharmony_ci if (0x00 != asc) { 9329141cc406Sopenharmony_ci DBG (5, "Not ready: unknown asc\n"); 9330141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9331141cc406Sopenharmony_ci } 9332141cc406Sopenharmony_ci if (0x00 != ascq) { 9333141cc406Sopenharmony_ci DBG (5, "Not ready: unknown ascq\n"); 9334141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9335141cc406Sopenharmony_ci } 9336141cc406Sopenharmony_ci DBG (5, "Not ready: busy\n"); 9337141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 9338141cc406Sopenharmony_ci break; 9339141cc406Sopenharmony_ci 9340141cc406Sopenharmony_ci case 0x3: 9341141cc406Sopenharmony_ci if (0x80 != asc) { 9342141cc406Sopenharmony_ci DBG (5, "Medium error: unknown asc\n"); 9343141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9344141cc406Sopenharmony_ci } 9345141cc406Sopenharmony_ci if (0x01 == ascq) { 9346141cc406Sopenharmony_ci DBG (5, "Medium error: paper jam\n"); 9347141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 9348141cc406Sopenharmony_ci } 9349141cc406Sopenharmony_ci if (0x02 == ascq) { 9350141cc406Sopenharmony_ci DBG (5, "Medium error: cover open\n"); 9351141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 9352141cc406Sopenharmony_ci } 9353141cc406Sopenharmony_ci if (0x03 == ascq) { 9354141cc406Sopenharmony_ci DBG (5, "Medium error: hopper empty\n"); 9355141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 9356141cc406Sopenharmony_ci } 9357141cc406Sopenharmony_ci if (0x04 == ascq) { 9358141cc406Sopenharmony_ci DBG (5, "Medium error: unusual paper\n"); 9359141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 9360141cc406Sopenharmony_ci } 9361141cc406Sopenharmony_ci if (0x07 == ascq) { 9362141cc406Sopenharmony_ci DBG (5, "Medium error: double feed\n"); 9363141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 9364141cc406Sopenharmony_ci } 9365141cc406Sopenharmony_ci if (0x08 == ascq) { 9366141cc406Sopenharmony_ci DBG (5, "Medium error: ADF setup error\n"); 9367141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 9368141cc406Sopenharmony_ci } 9369141cc406Sopenharmony_ci if (0x09 == ascq) { 9370141cc406Sopenharmony_ci DBG (5, "Medium error: Carrier sheet\n"); 9371141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 9372141cc406Sopenharmony_ci } 9373141cc406Sopenharmony_ci if (0x0c == ascq) { 9374141cc406Sopenharmony_ci DBG (5, "Medium error: ADF blocked by card\n"); 9375141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 9376141cc406Sopenharmony_ci } 9377141cc406Sopenharmony_ci if (0x10 == ascq) { 9378141cc406Sopenharmony_ci DBG (5, "Medium error: no ink cartridge\n"); 9379141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9380141cc406Sopenharmony_ci } 9381141cc406Sopenharmony_ci if (0x13 == ascq) { 9382141cc406Sopenharmony_ci DBG (5, "Medium error: temporary no data\n"); 9383141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 9384141cc406Sopenharmony_ci } 9385141cc406Sopenharmony_ci if (0x14 == ascq) { 9386141cc406Sopenharmony_ci DBG (5, "Medium error: endorser error\n"); 9387141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9388141cc406Sopenharmony_ci } 9389141cc406Sopenharmony_ci if (0x20 == ascq) { 9390141cc406Sopenharmony_ci DBG (5, "Medium error: Stop button\n"); 9391141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 9392141cc406Sopenharmony_ci } 9393141cc406Sopenharmony_ci if (0x22 == ascq) { 9394141cc406Sopenharmony_ci DBG (5, "Medium error: scanning halted\n"); 9395141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 9396141cc406Sopenharmony_ci } 9397141cc406Sopenharmony_ci if (0x30 == ascq) { 9398141cc406Sopenharmony_ci DBG (5, "Medium error: Not enough paper\n"); 9399141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 9400141cc406Sopenharmony_ci } 9401141cc406Sopenharmony_ci if (0x31 == ascq) { 9402141cc406Sopenharmony_ci DBG (5, "Medium error: scanning disabled\n"); 9403141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9404141cc406Sopenharmony_ci } 9405141cc406Sopenharmony_ci if (0x32 == ascq) { 9406141cc406Sopenharmony_ci DBG (5, "Medium error: scanning paused\n"); 9407141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 9408141cc406Sopenharmony_ci } 9409141cc406Sopenharmony_ci if (0x33 == ascq) { 9410141cc406Sopenharmony_ci DBG (5, "Medium error: WiFi control error\n"); 9411141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9412141cc406Sopenharmony_ci } 9413141cc406Sopenharmony_ci DBG (5, "Medium error: unknown ascq\n"); 9414141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9415141cc406Sopenharmony_ci break; 9416141cc406Sopenharmony_ci 9417141cc406Sopenharmony_ci case 0x4: 9418141cc406Sopenharmony_ci if (0x80 != asc && 0x44 != asc) { 9419141cc406Sopenharmony_ci DBG (5, "Hardware error: unknown asc\n"); 9420141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9421141cc406Sopenharmony_ci } 9422141cc406Sopenharmony_ci if ((0x44 == asc) && (0x00 == ascq)) { 9423141cc406Sopenharmony_ci DBG (5, "Hardware error: EEPROM error\n"); 9424141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9425141cc406Sopenharmony_ci } 9426141cc406Sopenharmony_ci if ((0x80 == asc) && (0x01 == ascq)) { 9427141cc406Sopenharmony_ci DBG (5, "Hardware error: FB motor fuse\n"); 9428141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9429141cc406Sopenharmony_ci } 9430141cc406Sopenharmony_ci if ((0x80 == asc) && (0x02 == ascq)) { 9431141cc406Sopenharmony_ci DBG (5, "Hardware error: heater fuse\n"); 9432141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9433141cc406Sopenharmony_ci } 9434141cc406Sopenharmony_ci if ((0x80 == asc) && (0x03 == ascq)) { 9435141cc406Sopenharmony_ci DBG (5, "Hardware error: lamp fuse\n"); 9436141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9437141cc406Sopenharmony_ci } 9438141cc406Sopenharmony_ci if ((0x80 == asc) && (0x04 == ascq)) { 9439141cc406Sopenharmony_ci DBG (5, "Hardware error: ADF motor fuse\n"); 9440141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9441141cc406Sopenharmony_ci } 9442141cc406Sopenharmony_ci if ((0x80 == asc) && (0x05 == ascq)) { 9443141cc406Sopenharmony_ci DBG (5, "Hardware error: mechanical error\n"); 9444141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9445141cc406Sopenharmony_ci } 9446141cc406Sopenharmony_ci if ((0x80 == asc) && (0x06 == ascq)) { 9447141cc406Sopenharmony_ci DBG (5, "Hardware error: optical error\n"); 9448141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9449141cc406Sopenharmony_ci } 9450141cc406Sopenharmony_ci if ((0x80 == asc) && (0x07 == ascq)) { 9451141cc406Sopenharmony_ci DBG (5, "Hardware error: Fan error\n"); 9452141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9453141cc406Sopenharmony_ci } 9454141cc406Sopenharmony_ci if ((0x80 == asc) && (0x08 == ascq)) { 9455141cc406Sopenharmony_ci DBG (5, "Hardware error: IPC option error\n"); 9456141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9457141cc406Sopenharmony_ci } 9458141cc406Sopenharmony_ci if ((0x80 == asc) && (0x10 == ascq)) { 9459141cc406Sopenharmony_ci DBG (5, "Hardware error: endorser error\n"); 9460141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9461141cc406Sopenharmony_ci } 9462141cc406Sopenharmony_ci if ((0x80 == asc) && (0x11 == ascq)) { 9463141cc406Sopenharmony_ci DBG (5, "Hardware error: endorser fuse\n"); 9464141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9465141cc406Sopenharmony_ci } 9466141cc406Sopenharmony_ci if ((0x80 == asc) && (0x80 == ascq)) { 9467141cc406Sopenharmony_ci DBG (5, "Hardware error: interface board timeout\n"); 9468141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9469141cc406Sopenharmony_ci } 9470141cc406Sopenharmony_ci if ((0x80 == asc) && (0x81 == ascq)) { 9471141cc406Sopenharmony_ci DBG (5, "Hardware error: interface board error 1\n"); 9472141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9473141cc406Sopenharmony_ci } 9474141cc406Sopenharmony_ci if ((0x80 == asc) && (0x82 == ascq)) { 9475141cc406Sopenharmony_ci DBG (5, "Hardware error: interface board error 2\n"); 9476141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9477141cc406Sopenharmony_ci } 9478141cc406Sopenharmony_ci DBG (5, "Hardware error: unknown asc/ascq\n"); 9479141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9480141cc406Sopenharmony_ci break; 9481141cc406Sopenharmony_ci 9482141cc406Sopenharmony_ci case 0x5: 9483141cc406Sopenharmony_ci if ((0x00 == asc) && (0x00 == ascq)) { 9484141cc406Sopenharmony_ci DBG (5, "Illegal request: paper edge detected too soon\n"); 9485141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9486141cc406Sopenharmony_ci } 9487141cc406Sopenharmony_ci if ((0x1a == asc) && (0x00 == ascq)) { 9488141cc406Sopenharmony_ci DBG (5, "Illegal request: Parameter list error\n"); 9489141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9490141cc406Sopenharmony_ci } 9491141cc406Sopenharmony_ci if ((0x20 == asc) && (0x00 == ascq)) { 9492141cc406Sopenharmony_ci DBG (5, "Illegal request: invalid command\n"); 9493141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9494141cc406Sopenharmony_ci } 9495141cc406Sopenharmony_ci if ((0x24 == asc) && (0x00 == ascq)) { 9496141cc406Sopenharmony_ci DBG (5, "Illegal request: invalid CDB field\n"); 9497141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9498141cc406Sopenharmony_ci } 9499141cc406Sopenharmony_ci if ((0x25 == asc) && (0x00 == ascq)) { 9500141cc406Sopenharmony_ci DBG (5, "Illegal request: unsupported logical unit\n"); 9501141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 9502141cc406Sopenharmony_ci } 9503141cc406Sopenharmony_ci if ((0x26 == asc) && (0x00 == ascq)) { 9504141cc406Sopenharmony_ci DBG (5, "Illegal request: invalid field in parm list\n"); 9505141cc406Sopenharmony_ci if (get_RS_additional_length(sensed_data) >= 0x0a) { 9506141cc406Sopenharmony_ci DBG (5, "Offending byte is %#02x\n", get_RS_offending_byte(sensed_data)); 9507141cc406Sopenharmony_ci 9508141cc406Sopenharmony_ci /* move this to set_window() ? */ 9509141cc406Sopenharmony_ci if (get_RS_offending_byte(sensed_data) >= 8) { 9510141cc406Sopenharmony_ci DBG (5, "Window desc block? byte %#02x\n",get_RS_offending_byte(sensed_data)-8); 9511141cc406Sopenharmony_ci } 9512141cc406Sopenharmony_ci } 9513141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9514141cc406Sopenharmony_ci } 9515141cc406Sopenharmony_ci if ((0x2C == asc) && (0x00 == ascq)) { 9516141cc406Sopenharmony_ci DBG (5, "Illegal request: command sequence error\n"); 9517141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9518141cc406Sopenharmony_ci } 9519141cc406Sopenharmony_ci if ((0x2C == asc) && (0x02 == ascq)) { 9520141cc406Sopenharmony_ci DBG (5, "Illegal request: wrong window combination \n"); 9521141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9522141cc406Sopenharmony_ci } 9523141cc406Sopenharmony_ci DBG (5, "Illegal request: unknown asc/ascq\n"); 9524141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9525141cc406Sopenharmony_ci break; 9526141cc406Sopenharmony_ci 9527141cc406Sopenharmony_ci case 0x6: 9528141cc406Sopenharmony_ci if ((0x00 == asc) && (0x00 == ascq)) { 9529141cc406Sopenharmony_ci DBG (5, "Unit attention: device reset\n"); 9530141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 9531141cc406Sopenharmony_ci } 9532141cc406Sopenharmony_ci if ((0x80 == asc) && (0x01 == ascq)) { 9533141cc406Sopenharmony_ci DBG (5, "Unit attention: power saving\n"); 9534141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 9535141cc406Sopenharmony_ci } 9536141cc406Sopenharmony_ci DBG (5, "Unit attention: unknown asc/ascq\n"); 9537141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9538141cc406Sopenharmony_ci break; 9539141cc406Sopenharmony_ci 9540141cc406Sopenharmony_ci case 0xb: 9541141cc406Sopenharmony_ci if ((0x43 == asc) && (0x00 == ascq)) { 9542141cc406Sopenharmony_ci DBG (5, "Aborted command: message error\n"); 9543141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9544141cc406Sopenharmony_ci } 9545141cc406Sopenharmony_ci if ((0x45 == asc) && (0x00 == ascq)) { 9546141cc406Sopenharmony_ci DBG (5, "Aborted command: select failure\n"); 9547141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9548141cc406Sopenharmony_ci } 9549141cc406Sopenharmony_ci if ((0x47 == asc) && (0x00 == ascq)) { 9550141cc406Sopenharmony_ci DBG (5, "Aborted command: SCSI parity error\n"); 9551141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9552141cc406Sopenharmony_ci } 9553141cc406Sopenharmony_ci if ((0x48 == asc) && (0x00 == ascq)) { 9554141cc406Sopenharmony_ci DBG (5, "Aborted command: initiator error message\n"); 9555141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9556141cc406Sopenharmony_ci } 9557141cc406Sopenharmony_ci if ((0x4e == asc) && (0x00 == ascq)) { 9558141cc406Sopenharmony_ci DBG (5, "Aborted command: overlapped commands\n"); 9559141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9560141cc406Sopenharmony_ci } 9561141cc406Sopenharmony_ci if ((0x80 == asc) && (0x01 == ascq)) { 9562141cc406Sopenharmony_ci DBG (5, "Aborted command: image transfer error\n"); 9563141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9564141cc406Sopenharmony_ci } 9565141cc406Sopenharmony_ci if ((0x80 == asc) && (0x03 == ascq)) { 9566141cc406Sopenharmony_ci DBG (5, "Aborted command: JPEG overflow error\n"); 9567141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 9568141cc406Sopenharmony_ci } 9569141cc406Sopenharmony_ci DBG (5, "Aborted command: unknown asc/ascq\n"); 9570141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9571141cc406Sopenharmony_ci break; 9572141cc406Sopenharmony_ci 9573141cc406Sopenharmony_ci default: 9574141cc406Sopenharmony_ci DBG (5, "Unknown Sense Code\n"); 9575141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9576141cc406Sopenharmony_ci } 9577141cc406Sopenharmony_ci 9578141cc406Sopenharmony_ci DBG (5, "sense_handler: should never happen!\n"); 9579141cc406Sopenharmony_ci 9580141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9581141cc406Sopenharmony_ci} 9582141cc406Sopenharmony_ci 9583141cc406Sopenharmony_ci/* 9584141cc406Sopenharmony_ci * take a bunch of pointers, send commands to scanner 9585141cc406Sopenharmony_ci */ 9586141cc406Sopenharmony_cistatic SANE_Status 9587141cc406Sopenharmony_cido_cmd(struct fujitsu *s, int runRS, int shortTime, 9588141cc406Sopenharmony_ci unsigned char * cmdBuff, size_t cmdLen, 9589141cc406Sopenharmony_ci unsigned char * outBuff, size_t outLen, 9590141cc406Sopenharmony_ci unsigned char * inBuff, size_t * inLen 9591141cc406Sopenharmony_ci) 9592141cc406Sopenharmony_ci{ 9593141cc406Sopenharmony_ci 9594141cc406Sopenharmony_ci /* unset the request sense vars first */ 9595141cc406Sopenharmony_ci s->rs_info = 0; 9596141cc406Sopenharmony_ci s->rs_ili = 0; 9597141cc406Sopenharmony_ci s->rs_eom = 0; 9598141cc406Sopenharmony_ci 9599141cc406Sopenharmony_ci if (s->connection == CONNECTION_SCSI) { 9600141cc406Sopenharmony_ci return do_scsi_cmd(s, runRS, shortTime, 9601141cc406Sopenharmony_ci cmdBuff, cmdLen, 9602141cc406Sopenharmony_ci outBuff, outLen, 9603141cc406Sopenharmony_ci inBuff, inLen 9604141cc406Sopenharmony_ci ); 9605141cc406Sopenharmony_ci } 9606141cc406Sopenharmony_ci if (s->connection == CONNECTION_USB) { 9607141cc406Sopenharmony_ci return do_usb_cmd(s, runRS, shortTime, 9608141cc406Sopenharmony_ci cmdBuff, cmdLen, 9609141cc406Sopenharmony_ci outBuff, outLen, 9610141cc406Sopenharmony_ci inBuff, inLen 9611141cc406Sopenharmony_ci ); 9612141cc406Sopenharmony_ci } 9613141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 9614141cc406Sopenharmony_ci} 9615141cc406Sopenharmony_ci 9616141cc406Sopenharmony_ciSANE_Status 9617141cc406Sopenharmony_cido_scsi_cmd(struct fujitsu *s, int runRS, int shortTime, 9618141cc406Sopenharmony_ci unsigned char * cmdBuff, size_t cmdLen, 9619141cc406Sopenharmony_ci unsigned char * outBuff, size_t outLen, 9620141cc406Sopenharmony_ci unsigned char * inBuff, size_t * inLen 9621141cc406Sopenharmony_ci) 9622141cc406Sopenharmony_ci{ 9623141cc406Sopenharmony_ci int ret; 9624141cc406Sopenharmony_ci 9625141cc406Sopenharmony_ci /*shut up compiler*/ 9626141cc406Sopenharmony_ci (void) runRS; 9627141cc406Sopenharmony_ci (void) shortTime; 9628141cc406Sopenharmony_ci 9629141cc406Sopenharmony_ci DBG(10, "do_scsi_cmd: start\n"); 9630141cc406Sopenharmony_ci 9631141cc406Sopenharmony_ci DBG(25, "cmd: writing %d bytes\n", (int)cmdLen); 9632141cc406Sopenharmony_ci hexdump(30, "cmd: >>", cmdBuff, cmdLen); 9633141cc406Sopenharmony_ci 9634141cc406Sopenharmony_ci if(outBuff && outLen){ 9635141cc406Sopenharmony_ci DBG(25, "out: writing %d bytes\n", (int)outLen); 9636141cc406Sopenharmony_ci hexdump(30, "out: >>", outBuff, outLen); 9637141cc406Sopenharmony_ci } 9638141cc406Sopenharmony_ci if (inBuff && inLen){ 9639141cc406Sopenharmony_ci DBG(25, "in: reading %d bytes\n", (int)*inLen); 9640141cc406Sopenharmony_ci memset(inBuff,0,*inLen); 9641141cc406Sopenharmony_ci } 9642141cc406Sopenharmony_ci 9643141cc406Sopenharmony_ci ret = sanei_scsi_cmd2(s->fd, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen); 9644141cc406Sopenharmony_ci 9645141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD && ret != SANE_STATUS_EOF){ 9646141cc406Sopenharmony_ci DBG(5,"do_scsi_cmd: return '%s'\n",sane_strstatus(ret)); 9647141cc406Sopenharmony_ci return ret; 9648141cc406Sopenharmony_ci } 9649141cc406Sopenharmony_ci 9650141cc406Sopenharmony_ci /* FIXME: should we look at s->rs_info here? */ 9651141cc406Sopenharmony_ci if (inBuff && inLen){ 9652141cc406Sopenharmony_ci hexdump(30, "in: <<", inBuff, *inLen); 9653141cc406Sopenharmony_ci DBG(25, "in: read %d bytes\n", (int)*inLen); 9654141cc406Sopenharmony_ci } 9655141cc406Sopenharmony_ci 9656141cc406Sopenharmony_ci DBG(10, "do_scsi_cmd: finish\n"); 9657141cc406Sopenharmony_ci 9658141cc406Sopenharmony_ci return ret; 9659141cc406Sopenharmony_ci} 9660141cc406Sopenharmony_ci 9661141cc406Sopenharmony_ciSANE_Status 9662141cc406Sopenharmony_cido_usb_cmd(struct fujitsu *s, int runRS, int shortTime, 9663141cc406Sopenharmony_ci unsigned char * cmdBuff, size_t cmdLen, 9664141cc406Sopenharmony_ci unsigned char * outBuff, size_t outLen, 9665141cc406Sopenharmony_ci unsigned char * inBuff, size_t * inLen 9666141cc406Sopenharmony_ci) 9667141cc406Sopenharmony_ci{ 9668141cc406Sopenharmony_ci /*sanei_usb overwrites the transfer size, 9669141cc406Sopenharmony_ci * so make some local copies */ 9670141cc406Sopenharmony_ci size_t usb_cmdLen = USB_COMMAND_LEN; 9671141cc406Sopenharmony_ci size_t usb_outLen = outLen; 9672141cc406Sopenharmony_ci size_t usb_statLen = USB_STATUS_LEN; 9673141cc406Sopenharmony_ci size_t askLen = 0; 9674141cc406Sopenharmony_ci 9675141cc406Sopenharmony_ci /*copy the callers buffs into larger, padded ones*/ 9676141cc406Sopenharmony_ci unsigned char usb_cmdBuff[USB_COMMAND_LEN]; 9677141cc406Sopenharmony_ci unsigned char usb_statBuff[USB_STATUS_LEN]; 9678141cc406Sopenharmony_ci 9679141cc406Sopenharmony_ci int cmdTime = USB_COMMAND_TIME; 9680141cc406Sopenharmony_ci int outTime = USB_DATA_TIME; 9681141cc406Sopenharmony_ci int inTime = USB_DATA_TIME; 9682141cc406Sopenharmony_ci int statTime = USB_STATUS_TIME; 9683141cc406Sopenharmony_ci 9684141cc406Sopenharmony_ci int ret = 0; 9685141cc406Sopenharmony_ci int ret2 = 0; 9686141cc406Sopenharmony_ci 9687141cc406Sopenharmony_ci DBG (10, "do_usb_cmd: start\n"); 9688141cc406Sopenharmony_ci 9689141cc406Sopenharmony_ci if(shortTime){ 9690141cc406Sopenharmony_ci cmdTime = USB_COMMAND_TIME/60; 9691141cc406Sopenharmony_ci outTime = USB_DATA_TIME/60; 9692141cc406Sopenharmony_ci inTime = USB_DATA_TIME/60; 9693141cc406Sopenharmony_ci statTime = USB_STATUS_TIME/60; 9694141cc406Sopenharmony_ci } 9695141cc406Sopenharmony_ci 9696141cc406Sopenharmony_ci /* build a USB packet around the SCSI command */ 9697141cc406Sopenharmony_ci memset(&usb_cmdBuff,0,USB_COMMAND_LEN); 9698141cc406Sopenharmony_ci usb_cmdBuff[0] = USB_COMMAND_CODE; 9699141cc406Sopenharmony_ci memcpy(&usb_cmdBuff[USB_COMMAND_OFFSET],cmdBuff,cmdLen); 9700141cc406Sopenharmony_ci 9701141cc406Sopenharmony_ci /* change timeout */ 9702141cc406Sopenharmony_ci sanei_usb_set_timeout(cmdTime); 9703141cc406Sopenharmony_ci 9704141cc406Sopenharmony_ci /* write the command out */ 9705141cc406Sopenharmony_ci DBG(25, "cmd: writing %d bytes, timeout %d\n", USB_COMMAND_LEN, cmdTime); 9706141cc406Sopenharmony_ci hexdump(30, "cmd: >>", usb_cmdBuff, USB_COMMAND_LEN); 9707141cc406Sopenharmony_ci ret = sanei_usb_write_bulk(s->fd, usb_cmdBuff, &usb_cmdLen); 9708141cc406Sopenharmony_ci DBG(25, "cmd: wrote %d bytes, retVal %d\n", (int)usb_cmdLen, ret); 9709141cc406Sopenharmony_ci 9710141cc406Sopenharmony_ci if(ret == SANE_STATUS_EOF){ 9711141cc406Sopenharmony_ci DBG(5,"cmd: got EOF, returning IO_ERROR\n"); 9712141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9713141cc406Sopenharmony_ci } 9714141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 9715141cc406Sopenharmony_ci DBG(5,"cmd: return error '%s'\n",sane_strstatus(ret)); 9716141cc406Sopenharmony_ci return ret; 9717141cc406Sopenharmony_ci } 9718141cc406Sopenharmony_ci if(usb_cmdLen != USB_COMMAND_LEN){ 9719141cc406Sopenharmony_ci DBG(5,"cmd: wrong size %d/%d\n", USB_COMMAND_LEN, (int)usb_cmdLen); 9720141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9721141cc406Sopenharmony_ci } 9722141cc406Sopenharmony_ci 9723141cc406Sopenharmony_ci /* this command has a write component, and a place to get it */ 9724141cc406Sopenharmony_ci if(outBuff && outLen && outTime){ 9725141cc406Sopenharmony_ci 9726141cc406Sopenharmony_ci /* change timeout */ 9727141cc406Sopenharmony_ci sanei_usb_set_timeout(outTime); 9728141cc406Sopenharmony_ci 9729141cc406Sopenharmony_ci DBG(25, "out: writing %d bytes, timeout %d\n", (int)outLen, outTime); 9730141cc406Sopenharmony_ci hexdump(30, "out: >>", outBuff, outLen); 9731141cc406Sopenharmony_ci ret = sanei_usb_write_bulk(s->fd, outBuff, &usb_outLen); 9732141cc406Sopenharmony_ci DBG(25, "out: wrote %d bytes, retVal %d\n", (int)usb_outLen, ret); 9733141cc406Sopenharmony_ci 9734141cc406Sopenharmony_ci if(ret == SANE_STATUS_EOF){ 9735141cc406Sopenharmony_ci DBG(5,"out: got EOF, returning IO_ERROR\n"); 9736141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9737141cc406Sopenharmony_ci } 9738141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 9739141cc406Sopenharmony_ci DBG(5,"out: return error '%s'\n",sane_strstatus(ret)); 9740141cc406Sopenharmony_ci return ret; 9741141cc406Sopenharmony_ci } 9742141cc406Sopenharmony_ci if(usb_outLen != outLen){ 9743141cc406Sopenharmony_ci DBG(5,"out: wrong size %d/%d\n", (int)outLen, (int)usb_outLen); 9744141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9745141cc406Sopenharmony_ci } 9746141cc406Sopenharmony_ci } 9747141cc406Sopenharmony_ci 9748141cc406Sopenharmony_ci /* this command has a read component, and a place to put it */ 9749141cc406Sopenharmony_ci if(inBuff && inLen && inTime){ 9750141cc406Sopenharmony_ci 9751141cc406Sopenharmony_ci askLen = *inLen; 9752141cc406Sopenharmony_ci memset(inBuff,0,askLen); 9753141cc406Sopenharmony_ci 9754141cc406Sopenharmony_ci /* change timeout */ 9755141cc406Sopenharmony_ci sanei_usb_set_timeout(inTime); 9756141cc406Sopenharmony_ci 9757141cc406Sopenharmony_ci DBG(25, "in: reading %lu bytes, timeout %d\n", 9758141cc406Sopenharmony_ci (unsigned long)askLen, inTime); 9759141cc406Sopenharmony_ci 9760141cc406Sopenharmony_ci ret = sanei_usb_read_bulk(s->fd, inBuff, inLen); 9761141cc406Sopenharmony_ci DBG(25, "in: retVal %d\n", ret); 9762141cc406Sopenharmony_ci 9763141cc406Sopenharmony_ci if(ret == SANE_STATUS_EOF){ 9764141cc406Sopenharmony_ci DBG(5,"in: got EOF, continuing\n"); 9765141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 9766141cc406Sopenharmony_ci } 9767141cc406Sopenharmony_ci 9768141cc406Sopenharmony_ci if(ret != SANE_STATUS_GOOD){ 9769141cc406Sopenharmony_ci DBG(5,"in: return error '%s'\n",sane_strstatus(ret)); 9770141cc406Sopenharmony_ci return ret; 9771141cc406Sopenharmony_ci } 9772141cc406Sopenharmony_ci 9773141cc406Sopenharmony_ci DBG(25, "in: read %lu bytes\n", (unsigned long)*inLen); 9774141cc406Sopenharmony_ci if(*inLen){ 9775141cc406Sopenharmony_ci hexdump(31, "in: <<", inBuff, *inLen); 9776141cc406Sopenharmony_ci } 9777141cc406Sopenharmony_ci 9778141cc406Sopenharmony_ci if(*inLen && *inLen != askLen){ 9779141cc406Sopenharmony_ci ret = SANE_STATUS_EOF; 9780141cc406Sopenharmony_ci DBG(5,"in: short read, %lu/%lu\n", 9781141cc406Sopenharmony_ci (unsigned long)*inLen,(unsigned long)askLen); 9782141cc406Sopenharmony_ci } 9783141cc406Sopenharmony_ci } 9784141cc406Sopenharmony_ci 9785141cc406Sopenharmony_ci /*gather the scsi status byte. use ret2 instead of ret for status*/ 9786141cc406Sopenharmony_ci 9787141cc406Sopenharmony_ci memset(&usb_statBuff,0,USB_STATUS_LEN); 9788141cc406Sopenharmony_ci 9789141cc406Sopenharmony_ci /* change timeout */ 9790141cc406Sopenharmony_ci sanei_usb_set_timeout(statTime); 9791141cc406Sopenharmony_ci 9792141cc406Sopenharmony_ci DBG(25, "stat: reading %d bytes, timeout %d\n", USB_STATUS_LEN, statTime); 9793141cc406Sopenharmony_ci ret2 = sanei_usb_read_bulk(s->fd, usb_statBuff, &usb_statLen); 9794141cc406Sopenharmony_ci hexdump(30, "stat: <<", usb_statBuff, usb_statLen); 9795141cc406Sopenharmony_ci DBG(25, "stat: read %d bytes, retVal %d\n", (int)usb_statLen, ret2); 9796141cc406Sopenharmony_ci 9797141cc406Sopenharmony_ci if(ret2 == SANE_STATUS_EOF){ 9798141cc406Sopenharmony_ci DBG(5,"stat: got EOF, returning IO_ERROR\n"); 9799141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9800141cc406Sopenharmony_ci } 9801141cc406Sopenharmony_ci if(ret2 != SANE_STATUS_GOOD){ 9802141cc406Sopenharmony_ci DBG(5,"stat: return error '%s'\n",sane_strstatus(ret2)); 9803141cc406Sopenharmony_ci return ret2; 9804141cc406Sopenharmony_ci } 9805141cc406Sopenharmony_ci if(usb_statLen != USB_STATUS_LEN){ 9806141cc406Sopenharmony_ci DBG(5,"stat: wrong size %d/%d\n", USB_STATUS_LEN, (int)usb_statLen); 9807141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9808141cc406Sopenharmony_ci } 9809141cc406Sopenharmony_ci 9810141cc406Sopenharmony_ci /* busy status */ 9811141cc406Sopenharmony_ci if(usb_statBuff[USB_STATUS_OFFSET] == 8){ 9812141cc406Sopenharmony_ci DBG(25,"stat: busy\n"); 9813141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 9814141cc406Sopenharmony_ci } 9815141cc406Sopenharmony_ci 9816141cc406Sopenharmony_ci /* if there is a non-busy status >0, try to figure out why */ 9817141cc406Sopenharmony_ci if(usb_statBuff[USB_STATUS_OFFSET] > 0){ 9818141cc406Sopenharmony_ci DBG(25,"stat: value %d\n", usb_statBuff[USB_STATUS_OFFSET]); 9819141cc406Sopenharmony_ci 9820141cc406Sopenharmony_ci /* caller is interested in having RS run on errors */ 9821141cc406Sopenharmony_ci if(runRS){ 9822141cc406Sopenharmony_ci unsigned char rs_cmd[REQUEST_SENSE_len]; 9823141cc406Sopenharmony_ci size_t rs_cmdLen = REQUEST_SENSE_len; 9824141cc406Sopenharmony_ci 9825141cc406Sopenharmony_ci unsigned char rs_in[RS_return_size]; 9826141cc406Sopenharmony_ci size_t rs_inLen = RS_return_size; 9827141cc406Sopenharmony_ci 9828141cc406Sopenharmony_ci memset(rs_cmd,0,rs_cmdLen); 9829141cc406Sopenharmony_ci set_SCSI_opcode(rs_cmd, REQUEST_SENSE_code); 9830141cc406Sopenharmony_ci set_RS_return_size(rs_cmd, rs_inLen); 9831141cc406Sopenharmony_ci 9832141cc406Sopenharmony_ci DBG(25,"rs sub call >>\n"); 9833141cc406Sopenharmony_ci ret2 = do_cmd( 9834141cc406Sopenharmony_ci s,0,0, 9835141cc406Sopenharmony_ci rs_cmd, rs_cmdLen, 9836141cc406Sopenharmony_ci NULL,0, 9837141cc406Sopenharmony_ci rs_in, &rs_inLen 9838141cc406Sopenharmony_ci ); 9839141cc406Sopenharmony_ci DBG(25,"rs sub call <<\n"); 9840141cc406Sopenharmony_ci 9841141cc406Sopenharmony_ci if(ret2 == SANE_STATUS_EOF){ 9842141cc406Sopenharmony_ci DBG(5,"rs: got EOF, returning IO_ERROR\n"); 9843141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9844141cc406Sopenharmony_ci } 9845141cc406Sopenharmony_ci if(ret2 != SANE_STATUS_GOOD){ 9846141cc406Sopenharmony_ci DBG(5,"rs: return error '%s'\n",sane_strstatus(ret2)); 9847141cc406Sopenharmony_ci return ret2; 9848141cc406Sopenharmony_ci } 9849141cc406Sopenharmony_ci 9850141cc406Sopenharmony_ci /* parse the rs data */ 9851141cc406Sopenharmony_ci ret2 = sense_handler( 0, rs_in, (void *)s ); 9852141cc406Sopenharmony_ci 9853141cc406Sopenharmony_ci /* this was a short read, but the usb layer did not know */ 9854141cc406Sopenharmony_ci if(s->rs_ili && inBuff && inLen && inTime){ 9855141cc406Sopenharmony_ci *inLen = askLen - s->rs_info; 9856141cc406Sopenharmony_ci DBG(5,"do_usb_cmd: short read via rs, %lu/%lu\n", 9857141cc406Sopenharmony_ci (unsigned long)*inLen,(unsigned long)askLen); 9858141cc406Sopenharmony_ci } 9859141cc406Sopenharmony_ci return ret2; 9860141cc406Sopenharmony_ci } 9861141cc406Sopenharmony_ci else{ 9862141cc406Sopenharmony_ci DBG(5,"do_usb_cmd: Not calling rs!\n"); 9863141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 9864141cc406Sopenharmony_ci } 9865141cc406Sopenharmony_ci } 9866141cc406Sopenharmony_ci 9867141cc406Sopenharmony_ci DBG (10, "do_usb_cmd: finish\n"); 9868141cc406Sopenharmony_ci 9869141cc406Sopenharmony_ci return ret; 9870141cc406Sopenharmony_ci} 9871141cc406Sopenharmony_ci 9872141cc406Sopenharmony_cistatic SANE_Status 9873141cc406Sopenharmony_ciwait_scanner(struct fujitsu *s) 9874141cc406Sopenharmony_ci{ 9875141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 9876141cc406Sopenharmony_ci 9877141cc406Sopenharmony_ci unsigned char cmd[TEST_UNIT_READY_len]; 9878141cc406Sopenharmony_ci size_t cmdLen = TEST_UNIT_READY_len; 9879141cc406Sopenharmony_ci 9880141cc406Sopenharmony_ci DBG (10, "wait_scanner: start\n"); 9881141cc406Sopenharmony_ci 9882141cc406Sopenharmony_ci memset(cmd,0,cmdLen); 9883141cc406Sopenharmony_ci set_SCSI_opcode(cmd,TEST_UNIT_READY_code); 9884141cc406Sopenharmony_ci 9885141cc406Sopenharmony_ci ret = do_cmd ( 9886141cc406Sopenharmony_ci s, 0, 1, 9887141cc406Sopenharmony_ci cmd, cmdLen, 9888141cc406Sopenharmony_ci NULL, 0, 9889141cc406Sopenharmony_ci NULL, NULL 9890141cc406Sopenharmony_ci ); 9891141cc406Sopenharmony_ci 9892141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 9893141cc406Sopenharmony_ci DBG(5,"WARNING: Brain-dead scanner. Hitting with stick\n"); 9894141cc406Sopenharmony_ci ret = do_cmd ( 9895141cc406Sopenharmony_ci s, 0, 1, 9896141cc406Sopenharmony_ci cmd, cmdLen, 9897141cc406Sopenharmony_ci NULL, 0, 9898141cc406Sopenharmony_ci NULL, NULL 9899141cc406Sopenharmony_ci ); 9900141cc406Sopenharmony_ci } 9901141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 9902141cc406Sopenharmony_ci DBG(5,"WARNING: Brain-dead scanner. Hitting with stick again\n"); 9903141cc406Sopenharmony_ci ret = do_cmd ( 9904141cc406Sopenharmony_ci s, 0, 1, 9905141cc406Sopenharmony_ci cmd, cmdLen, 9906141cc406Sopenharmony_ci NULL, 0, 9907141cc406Sopenharmony_ci NULL, NULL 9908141cc406Sopenharmony_ci ); 9909141cc406Sopenharmony_ci } 9910141cc406Sopenharmony_ci 9911141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) { 9912141cc406Sopenharmony_ci DBG (5, "wait_scanner: error '%s'\n", sane_strstatus (ret)); 9913141cc406Sopenharmony_ci } 9914141cc406Sopenharmony_ci 9915141cc406Sopenharmony_ci DBG (10, "wait_scanner: finish\n"); 9916141cc406Sopenharmony_ci 9917141cc406Sopenharmony_ci return ret; 9918141cc406Sopenharmony_ci} 9919141cc406Sopenharmony_ci 9920141cc406Sopenharmony_ci/* certain options require the entire image to 9921141cc406Sopenharmony_ci * be collected from the scanner before we can 9922141cc406Sopenharmony_ci * tell the user the size of the image. */ 9923141cc406Sopenharmony_cistatic int 9924141cc406Sopenharmony_cimust_fully_buffer(struct fujitsu *s) 9925141cc406Sopenharmony_ci{ 9926141cc406Sopenharmony_ci if(s->hwdeskewcrop){ 9927141cc406Sopenharmony_ci return 1; 9928141cc406Sopenharmony_ci } 9929141cc406Sopenharmony_ci 9930141cc406Sopenharmony_ci if( 9931141cc406Sopenharmony_ci (s->swdeskew || s->swdespeck || s->swcrop || s->swskip) 9932141cc406Sopenharmony_ci && s->s_params.format != SANE_FRAME_JPEG 9933141cc406Sopenharmony_ci ){ 9934141cc406Sopenharmony_ci return 1; 9935141cc406Sopenharmony_ci } 9936141cc406Sopenharmony_ci 9937141cc406Sopenharmony_ci return 0; 9938141cc406Sopenharmony_ci} 9939141cc406Sopenharmony_ci 9940141cc406Sopenharmony_ci/* certain scanners require the mode of the 9941141cc406Sopenharmony_ci * image to be changed in software. */ 9942141cc406Sopenharmony_cistatic int 9943141cc406Sopenharmony_cimust_downsample(struct fujitsu *s) 9944141cc406Sopenharmony_ci{ 9945141cc406Sopenharmony_ci if(s->s_mode != s->u_mode 9946141cc406Sopenharmony_ci && s->compress != COMP_JPEG 9947141cc406Sopenharmony_ci ){ 9948141cc406Sopenharmony_ci return 1; 9949141cc406Sopenharmony_ci } 9950141cc406Sopenharmony_ci 9951141cc406Sopenharmony_ci return 0; 9952141cc406Sopenharmony_ci} 9953141cc406Sopenharmony_ci 9954141cc406Sopenharmony_ci/* s->page_width stores the user setting 9955141cc406Sopenharmony_ci * for the paper width in adf. sometimes, 9956141cc406Sopenharmony_ci * we need a value that differs from this 9957141cc406Sopenharmony_ci * due to using FB or overscan. 9958141cc406Sopenharmony_ci */ 9959141cc406Sopenharmony_cistatic int 9960141cc406Sopenharmony_ciget_page_width(struct fujitsu *s) 9961141cc406Sopenharmony_ci{ 9962141cc406Sopenharmony_ci int width = s->page_width + 2 * (s->os_x_basic*1200/s->basic_x_res); 9963141cc406Sopenharmony_ci 9964141cc406Sopenharmony_ci /* scanner max for fb */ 9965141cc406Sopenharmony_ci if(s->source == SOURCE_FLATBED){ 9966141cc406Sopenharmony_ci return s->max_x_fb; 9967141cc406Sopenharmony_ci } 9968141cc406Sopenharmony_ci 9969141cc406Sopenharmony_ci /* current paper size for adf not overscan */ 9970141cc406Sopenharmony_ci if(s->overscan != MSEL_ON){ 9971141cc406Sopenharmony_ci return s->page_width; 9972141cc406Sopenharmony_ci } 9973141cc406Sopenharmony_ci 9974141cc406Sopenharmony_ci /* can't overscan larger than scanner max */ 9975141cc406Sopenharmony_ci if(width > s->max_x){ 9976141cc406Sopenharmony_ci return s->max_x; 9977141cc406Sopenharmony_ci } 9978141cc406Sopenharmony_ci 9979141cc406Sopenharmony_ci /* overscan adds a margin to both sides */ 9980141cc406Sopenharmony_ci return width; 9981141cc406Sopenharmony_ci} 9982141cc406Sopenharmony_ci 9983141cc406Sopenharmony_ci/* s->page_height stores the user setting 9984141cc406Sopenharmony_ci * for the paper height in adf. sometimes, 9985141cc406Sopenharmony_ci * we need a value that differs from this 9986141cc406Sopenharmony_ci * due to using FB or overscan. 9987141cc406Sopenharmony_ci */ 9988141cc406Sopenharmony_cistatic int 9989141cc406Sopenharmony_ciget_page_height(struct fujitsu *s) 9990141cc406Sopenharmony_ci{ 9991141cc406Sopenharmony_ci int height = s->page_height + 2 * (s->os_y_basic*1200/s->basic_y_res); 9992141cc406Sopenharmony_ci 9993141cc406Sopenharmony_ci /* scanner max for fb */ 9994141cc406Sopenharmony_ci if(s->source == SOURCE_FLATBED){ 9995141cc406Sopenharmony_ci return s->max_y_fb; 9996141cc406Sopenharmony_ci } 9997141cc406Sopenharmony_ci 9998141cc406Sopenharmony_ci /* current paper size for adf not overscan */ 9999141cc406Sopenharmony_ci if(s->overscan != MSEL_ON){ 10000141cc406Sopenharmony_ci return s->page_height; 10001141cc406Sopenharmony_ci } 10002141cc406Sopenharmony_ci 10003141cc406Sopenharmony_ci /* can't overscan larger than scanner max */ 10004141cc406Sopenharmony_ci if(height > s->max_y){ 10005141cc406Sopenharmony_ci return s->max_y; 10006141cc406Sopenharmony_ci } 10007141cc406Sopenharmony_ci 10008141cc406Sopenharmony_ci /* overscan adds a margin to both sides */ 10009141cc406Sopenharmony_ci return height; 10010141cc406Sopenharmony_ci} 10011141cc406Sopenharmony_ci 10012141cc406Sopenharmony_ci/* scanners have two different possible IPC 10013141cc406Sopenharmony_ci * modes, which enable a different series of 10014141cc406Sopenharmony_ci * subordinate options. Rather than provide 10015141cc406Sopenharmony_ci * the user with an option to pick the IPC 10016141cc406Sopenharmony_ci * mode, we show them the subordinate ones, 10017141cc406Sopenharmony_ci * and pick the right mode to match. 10018141cc406Sopenharmony_ci */ 10019141cc406Sopenharmony_cistatic int 10020141cc406Sopenharmony_ciget_ipc_mode(struct fujitsu *s) 10021141cc406Sopenharmony_ci{ 10022141cc406Sopenharmony_ci if ( s->bp_filter 10023141cc406Sopenharmony_ci || s->smoothing 10024141cc406Sopenharmony_ci || s->gamma_curve 10025141cc406Sopenharmony_ci || s->threshold_curve 10026141cc406Sopenharmony_ci || s->threshold_white 10027141cc406Sopenharmony_ci || s->noise_removal 10028141cc406Sopenharmony_ci || s->matrix_5 10029141cc406Sopenharmony_ci || s->matrix_4 10030141cc406Sopenharmony_ci || s->matrix_3 10031141cc406Sopenharmony_ci || s->matrix_2 10032141cc406Sopenharmony_ci ) 10033141cc406Sopenharmony_ci return WD_ipc_DTC; 10034141cc406Sopenharmony_ci 10035141cc406Sopenharmony_ci if(s->variance) 10036141cc406Sopenharmony_ci return WD_ipc_SDTC; 10037141cc406Sopenharmony_ci 10038141cc406Sopenharmony_ci /* special case: 0 threshold should activate IPC */ 10039141cc406Sopenharmony_ci if(!s->threshold){ 10040141cc406Sopenharmony_ci if(s->has_sdtc) 10041141cc406Sopenharmony_ci return WD_ipc_SDTC; 10042141cc406Sopenharmony_ci if(s->has_dtc) 10043141cc406Sopenharmony_ci return WD_ipc_DTC; 10044141cc406Sopenharmony_ci } 10045141cc406Sopenharmony_ci 10046141cc406Sopenharmony_ci return WD_ipc_DEFAULT; 10047141cc406Sopenharmony_ci} 10048141cc406Sopenharmony_ci 10049141cc406Sopenharmony_ci/* s->max_y gives the maximum height of paper which can be scanned 10050141cc406Sopenharmony_ci * this actually varies by resolution, so a helper to change it */ 10051141cc406Sopenharmony_cistatic int 10052141cc406Sopenharmony_ciset_max_y(struct fujitsu *s) 10053141cc406Sopenharmony_ci{ 10054141cc406Sopenharmony_ci int i; 10055141cc406Sopenharmony_ci 10056141cc406Sopenharmony_ci for(i=0;i<4;i++){ 10057141cc406Sopenharmony_ci if(!s->max_y_by_res[i].res) 10058141cc406Sopenharmony_ci break; 10059141cc406Sopenharmony_ci if(s->resolution_x <= s->max_y_by_res[i].res){ 10060141cc406Sopenharmony_ci s->max_y = s->max_y_by_res[i].len; 10061141cc406Sopenharmony_ci } 10062141cc406Sopenharmony_ci } 10063141cc406Sopenharmony_ci 10064141cc406Sopenharmony_ci return s->max_y; 10065141cc406Sopenharmony_ci} 10066141cc406Sopenharmony_ci 10067141cc406Sopenharmony_ci/** 10068141cc406Sopenharmony_ci * Convenience method to determine longest string size in a list. 10069141cc406Sopenharmony_ci */ 10070141cc406Sopenharmony_cistatic size_t 10071141cc406Sopenharmony_cimaxStringSize (const SANE_String_Const strings[]) 10072141cc406Sopenharmony_ci{ 10073141cc406Sopenharmony_ci size_t size, max_size = 0; 10074141cc406Sopenharmony_ci int i; 10075141cc406Sopenharmony_ci 10076141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) { 10077141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 10078141cc406Sopenharmony_ci if (size > max_size) 10079141cc406Sopenharmony_ci max_size = size; 10080141cc406Sopenharmony_ci } 10081141cc406Sopenharmony_ci 10082141cc406Sopenharmony_ci return max_size; 10083141cc406Sopenharmony_ci} 10084141cc406Sopenharmony_ci 10085141cc406Sopenharmony_ci/* 10086141cc406Sopenharmony_ci * Prints a hex dump of the given buffer onto the debug output stream. 10087141cc406Sopenharmony_ci */ 10088141cc406Sopenharmony_cistatic void 10089141cc406Sopenharmony_cihexdump (int level, char *comment, unsigned char *p, int l) 10090141cc406Sopenharmony_ci{ 10091141cc406Sopenharmony_ci int i; 10092141cc406Sopenharmony_ci char line[70]; /* 'xxx: xx xx ... xx xx abc */ 10093141cc406Sopenharmony_ci char *hex = line+4; 10094141cc406Sopenharmony_ci char *bin = line+53; 10095141cc406Sopenharmony_ci 10096141cc406Sopenharmony_ci if(DBG_LEVEL < level) 10097141cc406Sopenharmony_ci return; 10098141cc406Sopenharmony_ci 10099141cc406Sopenharmony_ci DBG (level, "%s\n", comment); 10100141cc406Sopenharmony_ci 10101141cc406Sopenharmony_ci for (i = 0; i < l; i++, p++) { 10102141cc406Sopenharmony_ci 10103141cc406Sopenharmony_ci /* at start of line */ 10104141cc406Sopenharmony_ci if ((i % 16) == 0) { 10105141cc406Sopenharmony_ci 10106141cc406Sopenharmony_ci /* not at start of first line, print current, reset */ 10107141cc406Sopenharmony_ci if (i) { 10108141cc406Sopenharmony_ci DBG (level, "%s\n", line); 10109141cc406Sopenharmony_ci } 10110141cc406Sopenharmony_ci 10111141cc406Sopenharmony_ci memset(line,0x20,69); 10112141cc406Sopenharmony_ci line[69] = 0; 10113141cc406Sopenharmony_ci hex = line + 4; 10114141cc406Sopenharmony_ci bin = line + 53; 10115141cc406Sopenharmony_ci 10116141cc406Sopenharmony_ci sprintf (line, "%3.3x:", i); 10117141cc406Sopenharmony_ci } 10118141cc406Sopenharmony_ci 10119141cc406Sopenharmony_ci /* the hex section */ 10120141cc406Sopenharmony_ci sprintf (hex, " %2.2x", *p); 10121141cc406Sopenharmony_ci hex += 3; 10122141cc406Sopenharmony_ci *hex = ' '; 10123141cc406Sopenharmony_ci 10124141cc406Sopenharmony_ci /* the char section */ 10125141cc406Sopenharmony_ci if(*p >= 0x20 && *p <= 0x7e){ 10126141cc406Sopenharmony_ci *bin=*p; 10127141cc406Sopenharmony_ci } 10128141cc406Sopenharmony_ci else{ 10129141cc406Sopenharmony_ci *bin='.'; 10130141cc406Sopenharmony_ci } 10131141cc406Sopenharmony_ci bin++; 10132141cc406Sopenharmony_ci } 10133141cc406Sopenharmony_ci 10134141cc406Sopenharmony_ci /* print last (partial) line */ 10135141cc406Sopenharmony_ci if (i) 10136141cc406Sopenharmony_ci DBG (level, "%s\n", line); 10137141cc406Sopenharmony_ci} 10138141cc406Sopenharmony_ci 10139141cc406Sopenharmony_ci/** 10140141cc406Sopenharmony_ci * An advanced method we don't support but have to define. 10141141cc406Sopenharmony_ci */ 10142141cc406Sopenharmony_ciSANE_Status 10143141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) 10144141cc406Sopenharmony_ci{ 10145141cc406Sopenharmony_ci DBG (10, "sane_set_io_mode\n"); 10146141cc406Sopenharmony_ci DBG (15, "%d %p\n", non_blocking, h); 10147141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 10148141cc406Sopenharmony_ci} 10149141cc406Sopenharmony_ci 10150141cc406Sopenharmony_ci/** 10151141cc406Sopenharmony_ci * An advanced method we don't support but have to define. 10152141cc406Sopenharmony_ci */ 10153141cc406Sopenharmony_ciSANE_Status 10154141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle h, SANE_Int *fdp) 10155141cc406Sopenharmony_ci{ 10156141cc406Sopenharmony_ci DBG (10, "sane_get_select_fd\n"); 10157141cc406Sopenharmony_ci DBG (15, "%p %d\n", h, *fdp); 10158141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 10159141cc406Sopenharmony_ci} 10160141cc406Sopenharmony_ci 10161141cc406Sopenharmony_ci/* 10162141cc406Sopenharmony_ci * @@ Section 7 - Image processing functions 10163141cc406Sopenharmony_ci */ 10164141cc406Sopenharmony_ci 10165141cc406Sopenharmony_ci/* Look in image for likely upper and left paper edges, then rotate 10166141cc406Sopenharmony_ci * image so that upper left corner of paper is upper left of image. 10167141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 10168141cc406Sopenharmony_cistatic SANE_Status 10169141cc406Sopenharmony_cibuffer_deskew(struct fujitsu *s, int side) 10170141cc406Sopenharmony_ci{ 10171141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 10172141cc406Sopenharmony_ci 10173141cc406Sopenharmony_ci int bg_color = 0xd6; 10174141cc406Sopenharmony_ci 10175141cc406Sopenharmony_ci DBG (10, "buffer_deskew: start\n"); 10176141cc406Sopenharmony_ci 10177141cc406Sopenharmony_ci /*only find skew on first image from a page, or if first image had error */ 10178141cc406Sopenharmony_ci if(s->side == SIDE_FRONT 10179141cc406Sopenharmony_ci || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK 10180141cc406Sopenharmony_ci || s->deskew_stat){ 10181141cc406Sopenharmony_ci 10182141cc406Sopenharmony_ci s->deskew_stat = sanei_magic_findSkew( 10183141cc406Sopenharmony_ci &s->s_params,s->buffers[side],s->resolution_x,s->resolution_y, 10184141cc406Sopenharmony_ci &s->deskew_vals[0],&s->deskew_vals[1],&s->deskew_slope); 10185141cc406Sopenharmony_ci 10186141cc406Sopenharmony_ci if(s->deskew_stat){ 10187141cc406Sopenharmony_ci DBG (5, "buffer_deskew: bad findSkew, bailing\n"); 10188141cc406Sopenharmony_ci goto cleanup; 10189141cc406Sopenharmony_ci } 10190141cc406Sopenharmony_ci } 10191141cc406Sopenharmony_ci /* backside images can use a 'flipped' version of frontside data */ 10192141cc406Sopenharmony_ci else{ 10193141cc406Sopenharmony_ci s->deskew_slope *= -1; 10194141cc406Sopenharmony_ci s->deskew_vals[0] = s->s_params.pixels_per_line - s->deskew_vals[0]; 10195141cc406Sopenharmony_ci } 10196141cc406Sopenharmony_ci 10197141cc406Sopenharmony_ci /* tweak the bg color based on scanner settings */ 10198141cc406Sopenharmony_ci if(s->s_mode == MODE_HALFTONE || s->s_mode == MODE_LINEART){ 10199141cc406Sopenharmony_ci if(s->bg_color == COLOR_BLACK || s->hwdeskewcrop || s->overscan) 10200141cc406Sopenharmony_ci bg_color = 0xff; 10201141cc406Sopenharmony_ci else 10202141cc406Sopenharmony_ci bg_color = 0; 10203141cc406Sopenharmony_ci } 10204141cc406Sopenharmony_ci else if(s->bg_color == COLOR_BLACK || s->hwdeskewcrop || s->overscan) 10205141cc406Sopenharmony_ci bg_color = 0; 10206141cc406Sopenharmony_ci 10207141cc406Sopenharmony_ci ret = sanei_magic_rotate(&s->s_params,s->buffers[side], 10208141cc406Sopenharmony_ci s->deskew_vals[0],s->deskew_vals[1],s->deskew_slope,bg_color); 10209141cc406Sopenharmony_ci 10210141cc406Sopenharmony_ci if(ret){ 10211141cc406Sopenharmony_ci DBG(5,"buffer_deskew: rotate error: %d",ret); 10212141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 10213141cc406Sopenharmony_ci goto cleanup; 10214141cc406Sopenharmony_ci } 10215141cc406Sopenharmony_ci 10216141cc406Sopenharmony_ci cleanup: 10217141cc406Sopenharmony_ci DBG (10, "buffer_deskew: finish\n"); 10218141cc406Sopenharmony_ci return ret; 10219141cc406Sopenharmony_ci} 10220141cc406Sopenharmony_ci 10221141cc406Sopenharmony_ci/* Look in image for likely left/right/bottom paper edges, then crop image. 10222141cc406Sopenharmony_ci * Does not attempt to rotate the image, that should be done first. 10223141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 10224141cc406Sopenharmony_cistatic SANE_Status 10225141cc406Sopenharmony_cibuffer_crop(struct fujitsu *s, int side) 10226141cc406Sopenharmony_ci{ 10227141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 10228141cc406Sopenharmony_ci 10229141cc406Sopenharmony_ci DBG (10, "buffer_crop: start\n"); 10230141cc406Sopenharmony_ci 10231141cc406Sopenharmony_ci ret = sanei_magic_findEdges( 10232141cc406Sopenharmony_ci &s->s_params,s->buffers[side],s->resolution_x,s->resolution_y, 10233141cc406Sopenharmony_ci &s->crop_vals[0],&s->crop_vals[1],&s->crop_vals[2],&s->crop_vals[3]); 10234141cc406Sopenharmony_ci 10235141cc406Sopenharmony_ci if(ret){ 10236141cc406Sopenharmony_ci DBG (5, "buffer_crop: bad edges, bailing\n"); 10237141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 10238141cc406Sopenharmony_ci goto cleanup; 10239141cc406Sopenharmony_ci } 10240141cc406Sopenharmony_ci 10241141cc406Sopenharmony_ci DBG (15, "buffer_crop: t:%d b:%d l:%d r:%d\n", 10242141cc406Sopenharmony_ci s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); 10243141cc406Sopenharmony_ci 10244141cc406Sopenharmony_ci /* if we will later binarize this image, make sure the width 10245141cc406Sopenharmony_ci * is a multiple of 8 pixels, by adjusting the right side */ 10246141cc406Sopenharmony_ci if ( must_downsample(s) && s->u_mode < MODE_GRAYSCALE ){ 10247141cc406Sopenharmony_ci s->crop_vals[3] -= (s->crop_vals[3]-s->crop_vals[2]) % 8; 10248141cc406Sopenharmony_ci } 10249141cc406Sopenharmony_ci 10250141cc406Sopenharmony_ci /* now crop the image */ 10251141cc406Sopenharmony_ci ret = sanei_magic_crop(&s->s_params,s->buffers[side], 10252141cc406Sopenharmony_ci s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); 10253141cc406Sopenharmony_ci 10254141cc406Sopenharmony_ci if(ret){ 10255141cc406Sopenharmony_ci DBG (5, "buffer_crop: bad crop, bailing\n"); 10256141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 10257141cc406Sopenharmony_ci goto cleanup; 10258141cc406Sopenharmony_ci } 10259141cc406Sopenharmony_ci 10260141cc406Sopenharmony_ci /* need to update user with new size */ 10261141cc406Sopenharmony_ci update_u_params(s); 10262141cc406Sopenharmony_ci 10263141cc406Sopenharmony_ci /* update image size counter to new, smaller size */ 10264141cc406Sopenharmony_ci s->bytes_rx[side] = s->s_params.lines * s->s_params.bytes_per_line; 10265141cc406Sopenharmony_ci s->buff_rx[side] = s->bytes_rx[side]; 10266141cc406Sopenharmony_ci 10267141cc406Sopenharmony_ci cleanup: 10268141cc406Sopenharmony_ci DBG (10, "buffer_crop: finish\n"); 10269141cc406Sopenharmony_ci return ret; 10270141cc406Sopenharmony_ci} 10271141cc406Sopenharmony_ci 10272141cc406Sopenharmony_ci/* Look in image for disconnected 'spots' of the requested size. 10273141cc406Sopenharmony_ci * Replace the spots with the average color of the surrounding pixels. 10274141cc406Sopenharmony_ci * FIXME: should we do this before we binarize instead of after? */ 10275141cc406Sopenharmony_cistatic SANE_Status 10276141cc406Sopenharmony_cibuffer_despeck(struct fujitsu *s, int side) 10277141cc406Sopenharmony_ci{ 10278141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 10279141cc406Sopenharmony_ci 10280141cc406Sopenharmony_ci DBG (10, "buffer_despeck: start\n"); 10281141cc406Sopenharmony_ci 10282141cc406Sopenharmony_ci ret = sanei_magic_despeck(&s->s_params,s->buffers[side],s->swdespeck); 10283141cc406Sopenharmony_ci if(ret){ 10284141cc406Sopenharmony_ci DBG (5, "buffer_despeck: bad despeck, bailing\n"); 10285141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 10286141cc406Sopenharmony_ci goto cleanup; 10287141cc406Sopenharmony_ci } 10288141cc406Sopenharmony_ci 10289141cc406Sopenharmony_ci cleanup: 10290141cc406Sopenharmony_ci DBG (10, "buffer_despeck: finish\n"); 10291141cc406Sopenharmony_ci return ret; 10292141cc406Sopenharmony_ci} 10293141cc406Sopenharmony_ci 10294141cc406Sopenharmony_ci/* Look if image has too few dark pixels.*/ 10295141cc406Sopenharmony_cistatic int 10296141cc406Sopenharmony_cibuffer_isblank(struct fujitsu *s, int side) 10297141cc406Sopenharmony_ci{ 10298141cc406Sopenharmony_ci SANE_Status ret = SANE_STATUS_GOOD; 10299141cc406Sopenharmony_ci int status = 0; 10300141cc406Sopenharmony_ci 10301141cc406Sopenharmony_ci DBG (10, "buffer_isblank: start\n"); 10302141cc406Sopenharmony_ci 10303141cc406Sopenharmony_ci ret = sanei_magic_isBlank2(&s->s_params, s->buffers[side], 10304141cc406Sopenharmony_ci s->resolution_x, s->resolution_y, s->swskip); 10305141cc406Sopenharmony_ci 10306141cc406Sopenharmony_ci if(ret == SANE_STATUS_NO_DOCS){ 10307141cc406Sopenharmony_ci DBG (5, "buffer_isblank: blank!\n"); 10308141cc406Sopenharmony_ci status = 1; 10309141cc406Sopenharmony_ci } 10310141cc406Sopenharmony_ci else if(ret){ 10311141cc406Sopenharmony_ci DBG (5, "buffer_isblank: error %d\n",ret); 10312141cc406Sopenharmony_ci } 10313141cc406Sopenharmony_ci 10314141cc406Sopenharmony_ci DBG (10, "buffer_isblank: finished\n"); 10315141cc406Sopenharmony_ci return status; 10316141cc406Sopenharmony_ci} 10317