1141cc406Sopenharmony_ci/* 2141cc406Sopenharmony_ci epson.c - SANE library for Epson flatbed scanners. 3141cc406Sopenharmony_ci 4141cc406Sopenharmony_ci Based on Kazuhiro Sasayama previous 5141cc406Sopenharmony_ci Work on epson.[ch] file from the SANE package. 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci Original code taken from sane-0.71 8141cc406Sopenharmony_ci Copyright (C) 1997 Hypercore Software Design, Ltd. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci modifications 11141cc406Sopenharmony_ci Copyright (C) 1998-1999 Christian Bucher <bucher@vernetzt.at> 12141cc406Sopenharmony_ci Copyright (C) 1998-1999 Kling & Hautzinger GmbH 13141cc406Sopenharmony_ci Copyright (C) 1999 Norihiko Sawa <sawa@yb3.so-net.ne.jp> 14141cc406Sopenharmony_ci Copyright (C) 2000 Mike Porter <mike@udel.edu> (mjp) 15141cc406Sopenharmony_ci Copyright (C) 2003 EPSON KOWA Corporation 16141cc406Sopenharmony_ci Copyright (C) 1999-2005 Karl Heinz Kremer <khk@khk.net> 17141cc406Sopenharmony_ci Copyright (C) 2006 Claus Boje <claus@egehuset.dk> 18141cc406Sopenharmony_ci*/ 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci#define SANE_EPSON_VERSION "SANE Epson Backend v0.2.47 - 2006-08-21" 21141cc406Sopenharmony_ci#define SANE_EPSON_BUILD 247 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci/* 24141cc406Sopenharmony_ci This file is part of the SANE package. 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 27141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 28141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 29141cc406Sopenharmony_ci License, or (at your option) any later version. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 32141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 33141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 34141cc406Sopenharmony_ci General Public License for more details. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 37141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 40141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 43141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 44141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 45141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 46141cc406Sopenharmony_ci account of linking the SANE library code into it. 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 49141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 50141cc406Sopenharmony_ci License. 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 53141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 54141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 57141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 58141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. */ 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci/* 61141cc406Sopenharmony_ci 2006-08-21 Fix buffer overflow error (submitted by Johannes Meixner) 62141cc406Sopenharmony_ci 2006-06-11 Applied patch from Henning. Fixed a number of compiler warnings 63141cc406Sopenharmony_ci 2006-03-12 Added support for perfetion 4990 photo 4800 dpi 64141cc406Sopenharmony_ci 2005-01-09 "flaming hack to get USB scanners working without timeouts under linux" 65141cc406Sopenharmony_ci submitted by "Steve" (in comment to bug #300830) 66141cc406Sopenharmony_ci 2004-12-18 Added USB IDs for CX-4600 and CX-3650 67141cc406Sopenharmony_ci 2004-10-16 Added USB ID for Expression 10000XL 68141cc406Sopenharmony_ci 2004-05-08 Disable feed() for Perfection1640 69141cc406Sopenharmony_ci 2004-02-08 Reformat all source code with "indent -bli0" 70141cc406Sopenharmony_ci 2004-02-01 Added D7 function level as copy of D1 for CX-6400 71141cc406Sopenharmony_ci Added IDs for CX-6400 and Perfection 4870 72141cc406Sopenharmony_ci 2003-10-27 Replaced DBG(0, ... with DBG(1, ... 73141cc406Sopenharmony_ci 2003-09-12 Increment only once in loop to find USB scanners 74141cc406Sopenharmony_ci Fix rounding problem when determining number of lines to scan 75141cc406Sopenharmony_ci 2003-08-21 Removed '//' comments - again ... 76141cc406Sopenharmony_ci Added EPSON Kowa copyright message 77141cc406Sopenharmony_ci 2003-08-15 Added support for GT-30000, with support for the ADF in simplex mode 78141cc406Sopenharmony_ci Borrowed some code from the EPSON Kowa IScan version of the backend 79141cc406Sopenharmony_ci Use sanei_scsi_cmd2() to send commands. This makes this backend 80141cc406Sopenharmony_ci useable for SBP-2 under FreeBSD 81141cc406Sopenharmony_ci 2003-05-11 Initialize OPT_LIMIT_RESOLUTION before first call to filter_resolution_list() 82141cc406Sopenharmony_ci Fix memory problem in get_identity_information(). Both problems were 83141cc406Sopenharmony_ci reported to the Debian bug database. 84141cc406Sopenharmony_ci 2003-03-26 Fixed two warnings reported by der Mouse 85141cc406Sopenharmony_ci 2003-02-16 Code cleanup, use more descriptive variable names. 86141cc406Sopenharmony_ci 2003-02-15 Move sanei_usb_init() to sane_init(). Thanks to Ron Cemer 87141cc406Sopenharmony_ci for providing the patch. 88141cc406Sopenharmony_ci 2003-02-15 Fix problem with "usb <vendor> <product> syntax in config file 89141cc406Sopenharmony_ci 2002-12-28 Added advanced option to display only short resolution list for 90141cc406Sopenharmony_ci displays that can not show the complete list. 91141cc406Sopenharmony_ci 2002-11-23 Fixed problem with dropout color. 92141cc406Sopenharmony_ci 2002-11-03 Full libusb support. 93141cc406Sopenharmony_ci 2002-10-05 Fixed problem with incorrect response to sane_get_parameters() 94141cc406Sopenharmony_ci in certain situations. 95141cc406Sopenharmony_ci 2002-09-01 USB scanners are now using libsane-usb functions 96141cc406Sopenharmony_ci 2002-08-17 Fixed typo in variable name. 97141cc406Sopenharmony_ci Fixed IEEE-1394 problem with Perfection-2450. 98141cc406Sopenharmony_ci Fixed problem with older B3 level SCSI scanners that do 99141cc406Sopenharmony_ci not support the extended status request. 100141cc406Sopenharmony_ci 2002-04-22 Declare close_scanner() and open_scanner() before they 101141cc406Sopenharmony_ci are used. 102141cc406Sopenharmony_ci 2002-04-13 Check if scanner needs to be opened for the reset call. 103141cc406Sopenharmony_ci (Thanks to Thomas Wenrich for pointing this out) 104141cc406Sopenharmony_ci Added product IDs for Perfection 1650 and 2450 105141cc406Sopenharmony_ci 2002-01-18 Recognize GT-xxxx type scanners also when using the SCSI 106141cc406Sopenharmony_ci or IEEE-1394 interface 107141cc406Sopenharmony_ci 2002-01-06 Disable TEST_IOCTL again, which was enabled by accident. Also 108141cc406Sopenharmony_ci protect the ioctl portion with an #ifdef __linux__ 109141cc406Sopenharmony_ci 2002-01-05 Version 0.2.17 110141cc406Sopenharmony_ci Check for and set s->fd to -1 when device is closed. 111141cc406Sopenharmony_ci Removed black gamma table - only use RGB even for grayscale 112141cc406Sopenharmony_ci 2002-01-01 Do not call access() for OS/2 systems 113141cc406Sopenharmony_ci 2001-11-13 Version 0.2.16 114141cc406Sopenharmony_ci Do not call access() for parallel port scanners. 115141cc406Sopenharmony_ci 2001-11-11 Version 0.2.15 116141cc406Sopenharmony_ci Fixed "wait-for-button" functionality, accidentally merged back wrong 117141cc406Sopenharmony_ci version after code freeze. 118141cc406Sopenharmony_ci Corrected "need-strange-reorder" recognition. 119141cc406Sopenharmony_ci Added IOCTL support to header file. 120141cc406Sopenharmony_ci 2001-11-10 Version 0.2.14 121141cc406Sopenharmony_ci Added "wait-for-button" functionality 122141cc406Sopenharmony_ci 2001-10-30 I18N patches (Stefan Roellin) 123141cc406Sopenharmony_ci 2001-10-28 Fixed bug with 1650 recognition 124141cc406Sopenharmony_ci 2001-06-09 Version 0.2.09 125141cc406Sopenharmony_ci Changed debug level for sense handler from 0 to 2 126141cc406Sopenharmony_ci 2001-05-25 Version 0.2.07 127141cc406Sopenharmony_ci Allow more than 8 bit color depth even for preview mode 128141cc406Sopenharmony_ci since Xsane can handle this. Some code cleanup. 129141cc406Sopenharmony_ci 2001-05-24 Removed ancient code that was used to determine the resolution 130141cc406Sopenharmony_ci back when the backend still had a slider for the resolution 131141cc406Sopenharmony_ci selection. 132141cc406Sopenharmony_ci 2001-05-22 Version 0.2.06 133141cc406Sopenharmony_ci Added sense_handler to support the GT-8000 scanner. Thanks to Matthias Trute 134141cc406Sopenharmony_ci for figuring out the details. 135141cc406Sopenharmony_ci Also added experimental code to use USB scanner probing. Need kernel patch 136141cc406Sopenharmony_ci for this. 137141cc406Sopenharmony_ci 2001-05-19 Version 0.2.05 138141cc406Sopenharmony_ci fixed the year in the recent change log entries - I now that it's 139141cc406Sopenharmony_ci 2001... 140141cc406Sopenharmony_ci Finally fixed the TPU problem with B4 level scanners 141141cc406Sopenharmony_ci 2001-05-13 Version 0.2.04 142141cc406Sopenharmony_ci Removed check for '\n' before end of line 143141cc406Sopenharmony_ci Free memory malloced in sane_get_devices() in sane_exit() again 144141cc406Sopenharmony_ci 2001-04-22 Version 0.2.03 145141cc406Sopenharmony_ci Check first if the scanner does support the set film type 146141cc406Sopenharmony_ci and set focus position before the GUI elements are displayed. 147141cc406Sopenharmony_ci This caused problems with older (B4 level) scanners when a TPU 148141cc406Sopenharmony_ci was connected. 149141cc406Sopenharmony_ci 2001-03-31 Version 0.2.02 150141cc406Sopenharmony_ci 2001-03-17 Next attempt to get the reported number of lines correct 151141cc406Sopenharmony_ci for the "color shuffling" part. 152141cc406Sopenharmony_ci Added more comments. 153141cc406Sopenharmony_ci 2000-12-25 Version 0.2.01 154141cc406Sopenharmony_ci Fixed problem with bilevel scanning with Perfection610: The 155141cc406Sopenharmony_ci line count has to be an even number with this scanner. 156141cc406Sopenharmony_ci Several initialization fixes regarding bit depth selection. 157141cc406Sopenharmony_ci This version goes back into the CVS repository, the 1.0.4 158141cc406Sopenharmony_ci release is out and therefore the code freeze is over. 159141cc406Sopenharmony_ci Some general cleanup, added more comments. 160141cc406Sopenharmony_ci 2000-12-09 Version 0.2.00 161141cc406Sopenharmony_ci Cleaned up printing of gamma table data. 16 elements 162141cc406Sopenharmony_ci are now printed in one line without the [epson] in 163141cc406Sopenharmony_ci between the values. Values are only printed for 164141cc406Sopenharmony_ci Debug levels >= 10. 165141cc406Sopenharmony_ci 2000-12-04 We've introduced the concept of inverting images 166141cc406Sopenharmony_ci when scanning from a TPU. This is fine, but 167141cc406Sopenharmony_ci the user supplied gamma tables no longer work. 168141cc406Sopenharmony_ci This is because the data a frontend is going 169141cc406Sopenharmony_ci to compute a gamma table for is not what the 170141cc406Sopenharmony_ci scanner actually sent. So, we have to back into 171141cc406Sopenharmony_ci the proper gamma table. I think this works. See 172141cc406Sopenharmony_ci set_gamma_table. (mjp) 173141cc406Sopenharmony_ci 2000-12-03 added the 12/14/16 bit support again. 174141cc406Sopenharmony_ci 2000-12-03 Version 0.1.38 175141cc406Sopenharmony_ci removed changes regarding 12/14 bit support because 176141cc406Sopenharmony_ci of SANE feature freeze for 1.0.4. The D1 fix for 177141cc406Sopenharmony_ci reading the values from the scanner instead of using 178141cc406Sopenharmony_ci hardcoded values and the fix for the off-by-one error 179141cc406Sopenharmony_ci in the reorder routine are still in the code base. 180141cc406Sopenharmony_ci Also force reload after change of scan mode. 181141cc406Sopenharmony_ci The full backend can be downloaded from my web site at 182141cc406Sopenharmony_ci http://www.freecolormanagement.com/sane 183141cc406Sopenharmony_ci 2000-12-03 Fixed off-by-one error in color reordering function. 184141cc406Sopenharmony_ci 2000-12-02 Read information about optical resolution and line 185141cc406Sopenharmony_ci distance from scanner instead of hardcoded values. 186141cc406Sopenharmony_ci Add support for color depth > 8 bits per channel. 187141cc406Sopenharmony_ci 2000-11-23 Display "Set Focus" control only for scanners that 188141cc406Sopenharmony_ci can actually handle the command. 189141cc406Sopenharmony_ci 2000-11-19 Added support for the "set focus position" command, 190141cc406Sopenharmony_ci this is necessary for the Expression1600. 191141cc406Sopenharmony_ci 2000-07-28 Changed #include <...> to #include "..." for the 192141cc406Sopenharmony_ci sane/... include files. 193141cc406Sopenharmony_ci 2000-07-26 Fixed problem with Perfection610: The variable 194141cc406Sopenharmony_ci s->color_shuffle_line was never correctly initialized 195141cc406Sopenharmony_ci 2000-06-28 When closing the scanner device the data that's 196141cc406Sopenharmony_ci still in the scanner, waiting to be transferred 197141cc406Sopenharmony_ci is flushed. This fixes the problem with scanimage -T 198141cc406Sopenharmony_ci 2000-06-13 Invert image when scanning negative with TPU, 199141cc406Sopenharmony_ci Show film type only when TPU is selected 200141cc406Sopenharmony_ci 2000-06-13 Initialize optical_res to 0 (Dave Hill) 201141cc406Sopenharmony_ci 2000-06-07 Fix in sane_close() - found by Henning Meier-Geinitz 202141cc406Sopenharmony_ci 2000-06-01 Threshold should only be active when scan depth 203141cc406Sopenharmony_ci is 1 and halftoning is off. (mjp) 204141cc406Sopenharmony_ci 2000-05-28 Turned on scanner based color correction. 205141cc406Sopenharmony_ci Dependencies between many options are now 206141cc406Sopenharmony_ci being enforced. For instance, auto area seg 207141cc406Sopenharmony_ci (AAS) should only be on when scan depth == 1. 208141cc406Sopenharmony_ci Added some routines to active and deactivate 209141cc406Sopenharmony_ci options. Routines report if option changed. 210141cc406Sopenharmony_ci Help prevent extraneous option reloads. Split 211141cc406Sopenharmony_ci sane_control_option in getvalue and setvalue. 212141cc406Sopenharmony_ci Further split up setvalue into several different 213141cc406Sopenharmony_ci routines. (mjp) 214141cc406Sopenharmony_ci 2000-05-21 In sane_close use close_scanner instead of just the 215141cc406Sopenharmony_ci SCSI close function. 216141cc406Sopenharmony_ci 2000-05-20 ... finally fixed the problem with the 610 217141cc406Sopenharmony_ci Added resolution_list to Epson_Device structure in 218141cc406Sopenharmony_ci epson.h - this fixes a bug that caused problems when 219141cc406Sopenharmony_ci more than one EPSON scanner was connected. 220141cc406Sopenharmony_ci 2000-05-13 Fixed the color problem with the Perfection 610. The few 221141cc406Sopenharmony_ci lines with "garbage" at the beginning of the scan are not 222141cc406Sopenharmony_ci yet removed. 223141cc406Sopenharmony_ci 2000-05-06 Added support for multiple EPSON scanners. At this time 224141cc406Sopenharmony_ci this may not be bug free, but it's a start and it seems 225141cc406Sopenharmony_ci to work well with just one scanner. 226141cc406Sopenharmony_ci 2000-04-06 Did some cleanup on the gamma correction part. The user 227141cc406Sopenharmony_ci defined table is now initialized to gamma=1, the gamma 228141cc406Sopenharmony_ci handling is also no longer depending on platform specific 229141cc406Sopenharmony_ci tables (handled instead by pointers to the actual tables) 230141cc406Sopenharmony_ci 2000-03-27 Disable request for push button status 231141cc406Sopenharmony_ci 2000-03-22 Removed free() calls to static strings to remove 232141cc406Sopenharmony_ci compile warnings. These were introduced to apparently 233141cc406Sopenharmony_ci fix an OS/2 bug. It now turned out that they are not 234141cc406Sopenharmony_ci necessary. The real fix was in the repository for a 235141cc406Sopenharmony_ci long time (2000-01-25). 236141cc406Sopenharmony_ci 2000-03-19 Fixed problem with A4 level devices - they use the 237141cc406Sopenharmony_ci line mode instead of the block mode. The routine to 238141cc406Sopenharmony_ci handle this was screwed up pretty bad. Now I have 239141cc406Sopenharmony_ci a solid version that handles all variations of line 240141cc406Sopenharmony_ci mode (automatically deals with the order the color 241141cc406Sopenharmony_ci lines are sent). 242141cc406Sopenharmony_ci 2000-03-06 Fixed occasional crash after warm up when the "in warmup 243141cc406Sopenharmony_ci state" went away in between doing ESC G and getting the 244141cc406Sopenharmony_ci extended status message. 245141cc406Sopenharmony_ci 2000-03-02 Code cleanup, disabled ZOOM until I have time to 246141cc406Sopenharmony_ci deal with all the side effects. 247141cc406Sopenharmony_ci 2000-03-01 More D1 fixes. In the future I have to come up with 248141cc406Sopenharmony_ci a more elegant solution to distinguish between different 249141cc406Sopenharmony_ci function levels. The level > n does not work anymore with 250141cc406Sopenharmony_ci D1. 251141cc406Sopenharmony_ci Added support for "set threshold" and "set zoom". 252141cc406Sopenharmony_ci 2000-02-23 First stab at level D1 support, also added a test 253141cc406Sopenharmony_ci for valid "set halftone" command to enable OPT_HALFTONE 254141cc406Sopenharmony_ci 2000-02-21 Check for "warming up" in after sane_start. This is 255141cc406Sopenharmony_ci IMHO a horrible hack, but that's the only way without 256141cc406Sopenharmony_ci a major redesign that will work. (KHK) 257141cc406Sopenharmony_ci 2000-02-20 Added some cleanup on error conditions in attach() 258141cc406Sopenharmony_ci Use new sanei_config_read() instead of fgets() for 259141cc406Sopenharmony_ci compatibility with OS/2 (Yuri Dario) 260141cc406Sopenharmony_ci 2000-02-19 Changed some "int" to "size_t" types 261141cc406Sopenharmony_ci Removed "Preview Resolution" 262141cc406Sopenharmony_ci Implemented resolution list as WORD_LIST instead of 263141cc406Sopenharmony_ci a RANGE (KHK) 264141cc406Sopenharmony_ci 2000-02-11 Default scan source is always "Flatbed", regardless 265141cc406Sopenharmony_ci of installed options. Corrected some typos. (KHK) 266141cc406Sopenharmony_ci 2000-02-03 Gamma curves now coupled with gamma correction menu. 267141cc406Sopenharmony_ci Only when "User defined" is selected are the curves 268141cc406Sopenharmony_ci selected. (Dave Hill) 269141cc406Sopenharmony_ci Renamed "Contrast" to "Gamma Correction" (KHK) 270141cc406Sopenharmony_ci 2000-02-02 "Brown Paper Bag Release" Put the USB fix finally 271141cc406Sopenharmony_ci into the CVS repository. 272141cc406Sopenharmony_ci 2000-02-01 Fixed problem with USB scanner not being recognized 273141cc406Sopenharmony_ci because of the changes to attach a few days ago. (KHK) 274141cc406Sopenharmony_ci 2000-01-29 fixed core dump with xscanimage by moving the gamma 275141cc406Sopenharmony_ci curves to the standard interface (no longer advanced) 276141cc406Sopenharmony_ci Removed pragma pack() from source code to make it 277141cc406Sopenharmony_ci easier to compile on non-gcc compilers (KHK) 278141cc406Sopenharmony_ci 2000-01-26 fixed problem with resolution selection when using the 279141cc406Sopenharmony_ci resolution list in xsane (KHK) 280141cc406Sopenharmony_ci 2000-01-25 moved the section where the device name is assigned 281141cc406Sopenharmony_ci in attach. This avoids the core dump of frontend 282141cc406Sopenharmony_ci applications when no scanner is found (Dave Hill) 283141cc406Sopenharmony_ci 2000-01-24 reorganization of SCSI related "helper" functions 284141cc406Sopenharmony_ci started support for user defined color correction - 285141cc406Sopenharmony_ci this is not yet available via the UI (Christian Bucher) 286141cc406Sopenharmony_ci 2000-01-24 Removed C++ style comments '//' (KHK) 287141cc406Sopenharmony_ci*/ 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci/* #define TEST_IOCTL */ 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci/* DON'T CHANGE THE NEXT LINE ! */ 293141cc406Sopenharmony_ci/* #undef FORCE_COLOR_SHUFFLE */ 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci#ifdef _AIX 297141cc406Sopenharmony_ci#include <lalloca.h> /* MUST come first for AIX! */ 298141cc406Sopenharmony_ci#endif 299141cc406Sopenharmony_ci 300141cc406Sopenharmony_ci/* --------------------- SANE INTERNATIONALISATION ------------------ */ 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci#ifndef SANE_I18N 303141cc406Sopenharmony_ci#define SANE_I18N(text) (text) 304141cc406Sopenharmony_ci#endif 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci#include "../include/sane/config.h" 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci#include <lalloca.h> 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci#include <limits.h> 311141cc406Sopenharmony_ci#include <stdio.h> 312141cc406Sopenharmony_ci#include <string.h> 313141cc406Sopenharmony_ci#include <stdlib.h> 314141cc406Sopenharmony_ci#include <ctype.h> 315141cc406Sopenharmony_ci#include <fcntl.h> 316141cc406Sopenharmony_ci#include <unistd.h> 317141cc406Sopenharmony_ci#include <errno.h> 318141cc406Sopenharmony_ci 319141cc406Sopenharmony_ci#include "../include/sane/sane.h" 320141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 321141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci#include "../include/sane/sanei_pio.h" 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci#define BACKEND_NAME epson 328141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci#include "epson.h" 333141cc406Sopenharmony_ci#include "epson_scsi.h" 334141cc406Sopenharmony_ci#include "epson_usb.h" 335141cc406Sopenharmony_ci 336141cc406Sopenharmony_ci#define EPSON_CONFIG_FILE "epson.conf" 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci#ifndef PATH_MAX 339141cc406Sopenharmony_ci#define PATH_MAX (1024) 340141cc406Sopenharmony_ci#endif 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci#define walloc(x) (x *)malloc(sizeof(x)) 343141cc406Sopenharmony_ci#define walloca(x) (x *)alloca(sizeof(x)) 344141cc406Sopenharmony_ci 345141cc406Sopenharmony_ci#ifndef XtNumber 346141cc406Sopenharmony_ci#define XtNumber(x) ( sizeof(x)/ sizeof(x[0]) ) 347141cc406Sopenharmony_ci#define XtOffset(p_type,field) ((size_t)&(((p_type)NULL)->field)) 348141cc406Sopenharmony_ci#define XtOffsetOf(s_type,field) XtOffset(s_type*,field) 349141cc406Sopenharmony_ci#endif 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci#define NUM_OF_HEX_ELEMENTS (16) /* number of hex numbers per line for data dump */ 352141cc406Sopenharmony_ci#define DEVICE_NAME_LEN (16) /* length of device name in extended status */ 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_ci/* NOTE: you can find these codes with "man ascii". */ 355141cc406Sopenharmony_ci#define STX 0x02 356141cc406Sopenharmony_ci#define ACK 0x06 357141cc406Sopenharmony_ci#define NAK 0x15 358141cc406Sopenharmony_ci#define CAN 0x18 359141cc406Sopenharmony_ci#define ESC 0x1B 360141cc406Sopenharmony_ci#define PF 0x19 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci#define S_ACK "\006" 363141cc406Sopenharmony_ci#define S_CAN "\030" 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci#define STATUS_FER 0x80 /* fatal error */ 366141cc406Sopenharmony_ci#define STATUS_AREA_END 0x20 /* area end */ 367141cc406Sopenharmony_ci#define STATUS_OPTION 0x10 /* option installed */ 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci#define EXT_STATUS_FER 0x80 /* fatal error */ 370141cc406Sopenharmony_ci#define EXT_STATUS_FBF 0x40 /* flat bed scanner */ 371141cc406Sopenharmony_ci#define EXT_STATUS_WU 0x02 /* warming up */ 372141cc406Sopenharmony_ci#define EXT_STATUS_PB 0x01 /* scanner has a push button */ 373141cc406Sopenharmony_ci 374141cc406Sopenharmony_ci#define EXT_STATUS_IST 0x80 /* option detected */ 375141cc406Sopenharmony_ci#define EXT_STATUS_EN 0x40 /* option enabled */ 376141cc406Sopenharmony_ci#define EXT_STATUS_ERR 0x20 /* other error */ 377141cc406Sopenharmony_ci#define EXT_STATUS_PE 0x08 /* no paper */ 378141cc406Sopenharmony_ci#define EXT_STATUS_PJ 0x04 /* paper jam */ 379141cc406Sopenharmony_ci#define EXT_STATUS_OPN 0x02 /* cover open */ 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci#define EPSON_LEVEL_A1 0 382141cc406Sopenharmony_ci#define EPSON_LEVEL_A2 1 383141cc406Sopenharmony_ci#define EPSON_LEVEL_B1 2 384141cc406Sopenharmony_ci#define EPSON_LEVEL_B2 3 385141cc406Sopenharmony_ci#define EPSON_LEVEL_B3 4 386141cc406Sopenharmony_ci#define EPSON_LEVEL_B4 5 387141cc406Sopenharmony_ci#define EPSON_LEVEL_B5 6 388141cc406Sopenharmony_ci#define EPSON_LEVEL_B6 7 389141cc406Sopenharmony_ci#define EPSON_LEVEL_B7 8 390141cc406Sopenharmony_ci#define EPSON_LEVEL_B8 9 391141cc406Sopenharmony_ci#define EPSON_LEVEL_F5 10 392141cc406Sopenharmony_ci#define EPSON_LEVEL_D1 11 393141cc406Sopenharmony_ci#define EPSON_LEVEL_D7 12 394141cc406Sopenharmony_ci#define EPSON_LEVEL_D8 13 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci/* there is also a function level "A5", which I'm ignoring here until somebody can 397141cc406Sopenharmony_ci convince me that this is still needed. The A5 level was for the GT-300, which 398141cc406Sopenharmony_ci was (is) a monochrome only scanner. So if somebody really wants to use this 399141cc406Sopenharmony_ci scanner with SANE get in touch with me and we can work something out - khk */ 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci#define EPSON_LEVEL_DEFAULT EPSON_LEVEL_B3 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_cistatic EpsonCmdRec epson_cmd[] = { 404141cc406Sopenharmony_ci/* 405141cc406Sopenharmony_ci * request identity 406141cc406Sopenharmony_ci * | request identity2 407141cc406Sopenharmony_ci * | | request status 408141cc406Sopenharmony_ci * | | | request condition 409141cc406Sopenharmony_ci * | | | | set color mode 410141cc406Sopenharmony_ci * | | | | | start scanning 411141cc406Sopenharmony_ci * | | | | | | set data format 412141cc406Sopenharmony_ci * | | | | | | | set resolution 413141cc406Sopenharmony_ci * | | | | | | | | set zoom 414141cc406Sopenharmony_ci * | | | | | | | | | set scan area 415141cc406Sopenharmony_ci * | | | | | | | | | | set brightness 416141cc406Sopenharmony_ci * | | | | | | | | | | | set gamma 417141cc406Sopenharmony_ci * | | | | | | | | | | | | set halftoning 418141cc406Sopenharmony_ci * | | | | | | | | | | | | | set color correction 419141cc406Sopenharmony_ci * | | | | | | | | | | | | | | initialize scanner 420141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | set speed 421141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | set lcount 422141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | mirror image 423141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | set gamma table 424141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | set outline emphasis 425141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | set dither 426141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | set color correction coefficients 427141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | request extension status 428141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | control an extension 429141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | forward feed / eject 430141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | feed 431141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | request push button status 432141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | control auto area segmentation 433141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | set film type 434141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set exposure time 435141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set bay 436141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set threshold 437141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set focus position 438141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | request focus position 439141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 440141cc406Sopenharmony_ci * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 441141cc406Sopenharmony_ci */ 442141cc406Sopenharmony_ci {"A1", 'I', 0, 'F','S', 0, 'G', 0, 'R', 0, 'A', 0, {0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 443141cc406Sopenharmony_ci {"A2", 'I', 0, 'F','S', 0, 'G','D','R','H','A','L',{-3,3,0}, 'Z','B', 0, '@', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 444141cc406Sopenharmony_ci {"B1", 'I', 0, 'F','S','C','G','D','R', 0, 'A', 0, {0,0,0}, 0, 'B', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 445141cc406Sopenharmony_ci {"B2", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-3,3,0}, 'Z','B', 0, '@', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 446141cc406Sopenharmony_ci {"B3", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-3,3,0}, 'Z','B','M','@', 0, 0, 0, 0, 0, 0, 'm','f','e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 447141cc406Sopenharmony_ci {"B4", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-3,3,0}, 'Z','B','M','@','g','d', 0, 'z','Q','b','m','f','e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 448141cc406Sopenharmony_ci {"B5", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-3,3,0}, 'Z','B','M','@','g','d','K','z','Q','b','m','f','e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 449141cc406Sopenharmony_ci {"B6", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-3,3,0}, 'Z','B','M','@','g','d','K','z','Q','b','m','f','e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 450141cc406Sopenharmony_ci {"B7", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-4,3,0}, 'Z','B','M','@','g','d','K','z','Q','b','m','f','e','\f', 0, '!','s','N', 0, 0, 't', 0, 0}, 451141cc406Sopenharmony_ci {"B8", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-4,3,0}, 'Z','B','M','@','g','d','K','z','Q','b','m','f','e','\f', 0x19,'!','s','N', 0, 0, 0, 'p','q'}, 452141cc406Sopenharmony_ci {"F5", 'I', 0, 'F','S','C','G','D','R','H','A','L',{-3,3,0}, 'Z', 0, 'M','@','g','d','K','z','Q', 0, 'm','f','e','\f', 0, 0, 0, 'N','T','P', 0, 0, 0}, 453141cc406Sopenharmony_ci {"D1", 'I','i','F', 0, 'C','G','D','R', 0, 'A', 0, {0,0,0}, 'Z', 0, 0, '@','g','d', 0, 'z', 0, 0, 0, 'f', 0, 0, 0, '!', 0, 0, 0, 0, 0, 0, 0}, 454141cc406Sopenharmony_ci {"D7", 'I', 0, 'F', 0, 'C','G','D','R', 0, 'A', 0, {0,0,0}, 'Z', 0, 0, '@','g','d', 0, 'z', 0, 0, 0, 'f', 0, 0, 0, '!', 0, 0, 0, 0, 0, 0, 0}, 455141cc406Sopenharmony_ci {"D8", 'I','i','F', 0, 'C','G','D','R', 0, 'A', 0, {0,0,0}, 'Z', 0, 0, '@','g','d', 0, 'z', 0, 0, 0, 'f','e', 0, 0, '!', 0, 0, 0, 0, 0, 0, 0}, 456141cc406Sopenharmony_ci}; 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci/* 461141cc406Sopenharmony_ci * Definition of the mode_param struct, that is used to 462141cc406Sopenharmony_ci * specify the valid parameters for the different scan modes. 463141cc406Sopenharmony_ci * 464141cc406Sopenharmony_ci * The depth variable gets updated when the bit depth is modified. 465141cc406Sopenharmony_ci */ 466141cc406Sopenharmony_ci 467141cc406Sopenharmony_cistruct mode_param 468141cc406Sopenharmony_ci{ 469141cc406Sopenharmony_ci int color; 470141cc406Sopenharmony_ci int mode_flags; 471141cc406Sopenharmony_ci int dropout_mask; 472141cc406Sopenharmony_ci int depth; 473141cc406Sopenharmony_ci}; 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_cistatic struct mode_param mode_params[] = { 476141cc406Sopenharmony_ci {0, 0x00, 0x30, 1}, 477141cc406Sopenharmony_ci {0, 0x00, 0x30, 8}, 478141cc406Sopenharmony_ci {1, 0x02, 0x00, 8} 479141cc406Sopenharmony_ci}; 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] = { 482141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 483141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 484141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 485141cc406Sopenharmony_ci NULL 486141cc406Sopenharmony_ci}; 487141cc406Sopenharmony_ci 488141cc406Sopenharmony_cistatic const SANE_String_Const adf_mode_list[] = { 489141cc406Sopenharmony_ci SANE_I18N ("Simplex"), 490141cc406Sopenharmony_ci SANE_I18N ("Duplex"), 491141cc406Sopenharmony_ci NULL 492141cc406Sopenharmony_ci}; 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci/* 496141cc406Sopenharmony_ci * Define the different scan sources: 497141cc406Sopenharmony_ci */ 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci#define FBF_STR SANE_I18N("Flatbed") 500141cc406Sopenharmony_ci#define TPU_STR SANE_I18N("Transparency Unit") 501141cc406Sopenharmony_ci#define ADF_STR SANE_I18N("Automatic Document Feeder") 502141cc406Sopenharmony_ci 503141cc406Sopenharmony_ci/* 504141cc406Sopenharmony_ci * source list need one dummy entry (save device settings is crashing). 505141cc406Sopenharmony_ci * NOTE: no const - this list gets created while exploring the capabilities 506141cc406Sopenharmony_ci * of the scanner. 507141cc406Sopenharmony_ci */ 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_cistatic SANE_String_Const source_list[] = { 510141cc406Sopenharmony_ci FBF_STR, 511141cc406Sopenharmony_ci NULL, 512141cc406Sopenharmony_ci NULL, 513141cc406Sopenharmony_ci NULL 514141cc406Sopenharmony_ci}; 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci/* some defines to make handling the TPU easier: */ 517141cc406Sopenharmony_ci#define FILM_TYPE_POSITIVE (0) 518141cc406Sopenharmony_ci#define FILM_TYPE_NEGATIVE (1) 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_cistatic const SANE_String_Const film_list[] = { 521141cc406Sopenharmony_ci SANE_I18N ("Positive Film"), 522141cc406Sopenharmony_ci SANE_I18N ("Negative Film"), 523141cc406Sopenharmony_ci NULL 524141cc406Sopenharmony_ci}; 525141cc406Sopenharmony_ci 526141cc406Sopenharmony_cistatic const SANE_String_Const focus_list[] = { 527141cc406Sopenharmony_ci SANE_I18N ("Focus on glass"), 528141cc406Sopenharmony_ci SANE_I18N ("Focus 2.5mm above glass"), 529141cc406Sopenharmony_ci NULL 530141cc406Sopenharmony_ci}; 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci/* 533141cc406Sopenharmony_ci * TODO: add some missing const. 534141cc406Sopenharmony_ci */ 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_ci#define HALFTONE_NONE 0x01 537141cc406Sopenharmony_ci#define HALFTONE_TET 0x03 538141cc406Sopenharmony_ci 539141cc406Sopenharmony_cistatic int halftone_params[] = { 540141cc406Sopenharmony_ci HALFTONE_NONE, 541141cc406Sopenharmony_ci 0x00, 542141cc406Sopenharmony_ci 0x10, 543141cc406Sopenharmony_ci 0x20, 544141cc406Sopenharmony_ci 0x80, 545141cc406Sopenharmony_ci 0x90, 546141cc406Sopenharmony_ci 0xa0, 547141cc406Sopenharmony_ci 0xb0, 548141cc406Sopenharmony_ci HALFTONE_TET, 549141cc406Sopenharmony_ci 0xc0, 550141cc406Sopenharmony_ci 0xd0 551141cc406Sopenharmony_ci}; 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list[] = { 554141cc406Sopenharmony_ci SANE_I18N ("None"), 555141cc406Sopenharmony_ci SANE_I18N ("Halftone A (Hard Tone)"), 556141cc406Sopenharmony_ci SANE_I18N ("Halftone B (Soft Tone)"), 557141cc406Sopenharmony_ci SANE_I18N ("Halftone C (Net Screen)"), 558141cc406Sopenharmony_ci NULL 559141cc406Sopenharmony_ci}; 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list_4[] = { 562141cc406Sopenharmony_ci SANE_I18N ("None"), 563141cc406Sopenharmony_ci SANE_I18N ("Halftone A (Hard Tone)"), 564141cc406Sopenharmony_ci SANE_I18N ("Halftone B (Soft Tone)"), 565141cc406Sopenharmony_ci SANE_I18N ("Halftone C (Net Screen)"), 566141cc406Sopenharmony_ci SANE_I18N ("Dither A (4x4 Bayer)"), 567141cc406Sopenharmony_ci SANE_I18N ("Dither B (4x4 Spiral)"), 568141cc406Sopenharmony_ci SANE_I18N ("Dither C (4x4 Net Screen)"), 569141cc406Sopenharmony_ci SANE_I18N ("Dither D (8x4 Net Screen)"), 570141cc406Sopenharmony_ci NULL 571141cc406Sopenharmony_ci}; 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list_7[] = { 574141cc406Sopenharmony_ci SANE_I18N ("None"), 575141cc406Sopenharmony_ci SANE_I18N ("Halftone A (Hard Tone)"), 576141cc406Sopenharmony_ci SANE_I18N ("Halftone B (Soft Tone)"), 577141cc406Sopenharmony_ci SANE_I18N ("Halftone C (Net Screen)"), 578141cc406Sopenharmony_ci SANE_I18N ("Dither A (4x4 Bayer)"), 579141cc406Sopenharmony_ci SANE_I18N ("Dither B (4x4 Spiral)"), 580141cc406Sopenharmony_ci SANE_I18N ("Dither C (4x4 Net Screen)"), 581141cc406Sopenharmony_ci SANE_I18N ("Dither D (8x4 Net Screen)"), 582141cc406Sopenharmony_ci SANE_I18N ("Text Enhanced Technology"), 583141cc406Sopenharmony_ci SANE_I18N ("Download pattern A"), 584141cc406Sopenharmony_ci SANE_I18N ("Download pattern B"), 585141cc406Sopenharmony_ci NULL 586141cc406Sopenharmony_ci}; 587141cc406Sopenharmony_ci 588141cc406Sopenharmony_cistatic int dropout_params[] = { 589141cc406Sopenharmony_ci 0x00, /* none */ 590141cc406Sopenharmony_ci 0x10, /* red */ 591141cc406Sopenharmony_ci 0x20, /* green */ 592141cc406Sopenharmony_ci 0x30 /* blue */ 593141cc406Sopenharmony_ci}; 594141cc406Sopenharmony_ci 595141cc406Sopenharmony_cistatic const SANE_String_Const dropout_list[] = { 596141cc406Sopenharmony_ci SANE_I18N ("None"), 597141cc406Sopenharmony_ci SANE_I18N ("Red"), 598141cc406Sopenharmony_ci SANE_I18N ("Green"), 599141cc406Sopenharmony_ci SANE_I18N ("Blue"), 600141cc406Sopenharmony_ci NULL 601141cc406Sopenharmony_ci}; 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_ci/* 604141cc406Sopenharmony_ci * Color correction: 605141cc406Sopenharmony_ci * One array for the actual parameters that get sent to the scanner (color_params[]), 606141cc406Sopenharmony_ci * one array for the strings that get displayed in the user interface (color_list[]) 607141cc406Sopenharmony_ci * and one array to mark the user defined color correction (dolor_userdefined[]). 608141cc406Sopenharmony_ci */ 609141cc406Sopenharmony_ci 610141cc406Sopenharmony_cistatic int color_params[] = { 611141cc406Sopenharmony_ci 0x00, 612141cc406Sopenharmony_ci 0x01, 613141cc406Sopenharmony_ci 0x10, 614141cc406Sopenharmony_ci 0x20, 615141cc406Sopenharmony_ci 0x40, 616141cc406Sopenharmony_ci 0x80 617141cc406Sopenharmony_ci}; 618141cc406Sopenharmony_ci 619141cc406Sopenharmony_cistatic SANE_Bool color_userdefined[] = { 620141cc406Sopenharmony_ci SANE_FALSE, 621141cc406Sopenharmony_ci SANE_TRUE, 622141cc406Sopenharmony_ci SANE_FALSE, 623141cc406Sopenharmony_ci SANE_FALSE, 624141cc406Sopenharmony_ci SANE_FALSE, 625141cc406Sopenharmony_ci SANE_FALSE 626141cc406Sopenharmony_ci}; 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_cistatic const SANE_String_Const color_list[] = { 629141cc406Sopenharmony_ci SANE_I18N ("No Correction"), 630141cc406Sopenharmony_ci SANE_I18N ("User defined"), 631141cc406Sopenharmony_ci SANE_I18N ("Impact-dot printers"), 632141cc406Sopenharmony_ci SANE_I18N ("Thermal printers"), 633141cc406Sopenharmony_ci SANE_I18N ("Ink-jet printers"), 634141cc406Sopenharmony_ci SANE_I18N ("CRT monitors"), 635141cc406Sopenharmony_ci NULL 636141cc406Sopenharmony_ci}; 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci/* 639141cc406Sopenharmony_ci * Gamma correction: 640141cc406Sopenharmony_ci * The A and B level scanners work differently than the D level scanners, therefore 641141cc406Sopenharmony_ci * I define two different sets of arrays, plus one set of variables that get set to 642141cc406Sopenharmony_ci * the actually used params and list arrays at runtime. 643141cc406Sopenharmony_ci */ 644141cc406Sopenharmony_ci 645141cc406Sopenharmony_cistatic int gamma_params_ab[] = { 646141cc406Sopenharmony_ci 0x01, 647141cc406Sopenharmony_ci 0x03, 648141cc406Sopenharmony_ci 0x00, 649141cc406Sopenharmony_ci 0x10, 650141cc406Sopenharmony_ci 0x20 651141cc406Sopenharmony_ci}; 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_cistatic const SANE_String_Const gamma_list_ab[] = { 654141cc406Sopenharmony_ci SANE_I18N ("Default"), 655141cc406Sopenharmony_ci SANE_I18N ("User defined"), 656141cc406Sopenharmony_ci SANE_I18N ("High density printing"), 657141cc406Sopenharmony_ci SANE_I18N ("Low density printing"), 658141cc406Sopenharmony_ci SANE_I18N ("High contrast printing"), 659141cc406Sopenharmony_ci NULL 660141cc406Sopenharmony_ci}; 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_cistatic SANE_Bool gamma_userdefined_ab[] = { 663141cc406Sopenharmony_ci SANE_FALSE, 664141cc406Sopenharmony_ci SANE_TRUE, 665141cc406Sopenharmony_ci SANE_FALSE, 666141cc406Sopenharmony_ci SANE_FALSE, 667141cc406Sopenharmony_ci SANE_FALSE, 668141cc406Sopenharmony_ci}; 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_cistatic int gamma_params_d[] = { 671141cc406Sopenharmony_ci 0x03, 672141cc406Sopenharmony_ci 0x04 673141cc406Sopenharmony_ci}; 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_cistatic const SANE_String_Const gamma_list_d[] = { 676141cc406Sopenharmony_ci SANE_I18N ("User defined (Gamma=1.0)"), 677141cc406Sopenharmony_ci SANE_I18N ("User defined (Gamma=1.8)"), 678141cc406Sopenharmony_ci NULL 679141cc406Sopenharmony_ci}; 680141cc406Sopenharmony_ci 681141cc406Sopenharmony_cistatic SANE_Bool gamma_userdefined_d[] = { 682141cc406Sopenharmony_ci SANE_TRUE, 683141cc406Sopenharmony_ci SANE_TRUE 684141cc406Sopenharmony_ci}; 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_cistatic SANE_Bool *gamma_userdefined; 687141cc406Sopenharmony_cistatic int *gamma_params; 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci/* flaming hack to get USB scanners 690141cc406Sopenharmony_ci working without timeouts under linux */ 691141cc406Sopenharmony_ci/* (cribbed from fujitsu.c) */ 692141cc406Sopenharmony_cistatic unsigned int r_cmd_count = 0; 693141cc406Sopenharmony_cistatic unsigned int w_cmd_count = 0; 694141cc406Sopenharmony_ci 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci/* Bay list: 699141cc406Sopenharmony_ci * this is used for the FilmScan 700141cc406Sopenharmony_ci */ 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_cistatic const SANE_String_Const bay_list[] = { 703141cc406Sopenharmony_ci " 1 ", 704141cc406Sopenharmony_ci " 2 ", 705141cc406Sopenharmony_ci " 3 ", 706141cc406Sopenharmony_ci " 4 ", 707141cc406Sopenharmony_ci " 5 ", 708141cc406Sopenharmony_ci " 6 ", 709141cc406Sopenharmony_ci NULL 710141cc406Sopenharmony_ci}; 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci/* 713141cc406Sopenharmony_ci * minimum, maximum, quantization. 714141cc406Sopenharmony_ci */ 715141cc406Sopenharmony_ci 716141cc406Sopenharmony_cistatic const SANE_Range u8_range = { 0, 255, 0 }; 717141cc406Sopenharmony_cistatic const SANE_Range s8_range = { -127, 127, 0 }; 718141cc406Sopenharmony_cistatic const SANE_Range zoom_range = { 50, 200, 0 }; 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci/* 721141cc406Sopenharmony_ci * The "switch_params" are used for several boolean choices 722141cc406Sopenharmony_ci */ 723141cc406Sopenharmony_cistatic int switch_params[] = { 724141cc406Sopenharmony_ci 0, 725141cc406Sopenharmony_ci 1 726141cc406Sopenharmony_ci}; 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci#define mirror_params switch_params 729141cc406Sopenharmony_ci#define speed_params switch_params 730141cc406Sopenharmony_ci#define film_params switch_params 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_cistatic const SANE_Range outline_emphasis_range = { -2, 2, 0 }; 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci/* static const SANE_Range gamma_range = { -2, 2, 0 }; */ 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_cistruct qf_param 737141cc406Sopenharmony_ci{ 738141cc406Sopenharmony_ci SANE_Word tl_x; 739141cc406Sopenharmony_ci SANE_Word tl_y; 740141cc406Sopenharmony_ci SANE_Word br_x; 741141cc406Sopenharmony_ci SANE_Word br_y; 742141cc406Sopenharmony_ci}; 743141cc406Sopenharmony_ci 744141cc406Sopenharmony_ci/* gcc don't like to overwrite const field */ 745141cc406Sopenharmony_cistatic /*const */ struct qf_param qf_params[] = { 746141cc406Sopenharmony_ci {0, 0, SANE_FIX (120.0), SANE_FIX (120.0)}, 747141cc406Sopenharmony_ci {0, 0, SANE_FIX (148.5), SANE_FIX (210.0)}, 748141cc406Sopenharmony_ci {0, 0, SANE_FIX (210.0), SANE_FIX (148.5)}, 749141cc406Sopenharmony_ci {0, 0, SANE_FIX (215.9), SANE_FIX (279.4)}, /* 8.5" x 11" */ 750141cc406Sopenharmony_ci {0, 0, SANE_FIX (210.0), SANE_FIX (297.0)}, 751141cc406Sopenharmony_ci {0, 0, 0, 0} 752141cc406Sopenharmony_ci}; 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_cistatic const SANE_String_Const qf_list[] = { 755141cc406Sopenharmony_ci SANE_I18N ("CD"), 756141cc406Sopenharmony_ci SANE_I18N ("A5 portrait"), 757141cc406Sopenharmony_ci SANE_I18N ("A5 landscape"), 758141cc406Sopenharmony_ci SANE_I18N ("Letter"), 759141cc406Sopenharmony_ci SANE_I18N ("A4"), 760141cc406Sopenharmony_ci SANE_I18N ("Max"), 761141cc406Sopenharmony_ci NULL 762141cc406Sopenharmony_ci}; 763141cc406Sopenharmony_ci 764141cc406Sopenharmony_ci 765141cc406Sopenharmony_cistatic SANE_Word *bitDepthList = NULL; 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci/* 770141cc406Sopenharmony_ci * List of pointers to devices - will be dynamically allocated depending 771141cc406Sopenharmony_ci * on the number of devices found. 772141cc406Sopenharmony_ci */ 773141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 774141cc406Sopenharmony_ci 775141cc406Sopenharmony_ci 776141cc406Sopenharmony_ci/* 777141cc406Sopenharmony_ci * Some utility functions 778141cc406Sopenharmony_ci */ 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_cistatic size_t 781141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 782141cc406Sopenharmony_ci{ 783141cc406Sopenharmony_ci size_t size, max_size = 0; 784141cc406Sopenharmony_ci int i; 785141cc406Sopenharmony_ci 786141cc406Sopenharmony_ci for (i = 0; strings[i]; i++) 787141cc406Sopenharmony_ci { 788141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 789141cc406Sopenharmony_ci if (size > max_size) 790141cc406Sopenharmony_ci max_size = size; 791141cc406Sopenharmony_ci } 792141cc406Sopenharmony_ci return max_size; 793141cc406Sopenharmony_ci} 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_citypedef struct 796141cc406Sopenharmony_ci{ 797141cc406Sopenharmony_ci u_char code; 798141cc406Sopenharmony_ci u_char status; 799141cc406Sopenharmony_ci u_char count1; 800141cc406Sopenharmony_ci u_char count2; 801141cc406Sopenharmony_ci u_char buf[1]; 802141cc406Sopenharmony_ci 803141cc406Sopenharmony_ci} EpsonHdrRec, *EpsonHdr; 804141cc406Sopenharmony_ci 805141cc406Sopenharmony_citypedef struct 806141cc406Sopenharmony_ci{ 807141cc406Sopenharmony_ci u_char code; 808141cc406Sopenharmony_ci u_char status; 809141cc406Sopenharmony_ci u_char count1; 810141cc406Sopenharmony_ci u_char count2; 811141cc406Sopenharmony_ci 812141cc406Sopenharmony_ci u_char type; 813141cc406Sopenharmony_ci u_char level; 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci u_char buf[1]; 816141cc406Sopenharmony_ci 817141cc406Sopenharmony_ci} EpsonIdentRec, *EpsonIdent; 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_citypedef union 820141cc406Sopenharmony_ci{ 821141cc406Sopenharmony_ci EpsonHdrRec hdr; 822141cc406Sopenharmony_ci EpsonIdentRec ident; 823141cc406Sopenharmony_ci} EpsonHdrUnionRec, *EpsonHdrUnion; 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci 826141cc406Sopenharmony_citypedef struct 827141cc406Sopenharmony_ci{ 828141cc406Sopenharmony_ci u_char code; 829141cc406Sopenharmony_ci u_char status; 830141cc406Sopenharmony_ci u_short count; 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci u_char buf[1]; 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci} EpsonParameterRec, *EpsonParameter; 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_citypedef struct 837141cc406Sopenharmony_ci{ 838141cc406Sopenharmony_ci u_char code; 839141cc406Sopenharmony_ci u_char status; 840141cc406Sopenharmony_ci 841141cc406Sopenharmony_ci u_char buf[4]; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci} EpsonDataRec, *EpsonData; 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci/* 846141cc406Sopenharmony_ci * 847141cc406Sopenharmony_ci * 848141cc406Sopenharmony_ci */ 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_cistatic EpsonHdrUnion command (Epson_Scanner * s, u_char * cmd, size_t cmd_size, 851141cc406Sopenharmony_ci SANE_Status * status); 852141cc406Sopenharmony_cistatic SANE_Status get_identity_information (SANE_Handle handle); 853141cc406Sopenharmony_cistatic SANE_Status get_identity2_information (SANE_Handle handle); 854141cc406Sopenharmony_cistatic int send (Epson_Scanner * s, void *buf, size_t buf_size, 855141cc406Sopenharmony_ci SANE_Status * status); 856141cc406Sopenharmony_cistatic ssize_t receive (Epson_Scanner * s, void *buf, ssize_t buf_size, 857141cc406Sopenharmony_ci SANE_Status * status); 858141cc406Sopenharmony_cistatic SANE_Status color_shuffle (SANE_Handle handle, int *new_length); 859141cc406Sopenharmony_cistatic SANE_Status request_focus_position (SANE_Handle handle, 860141cc406Sopenharmony_ci u_char * position); 861141cc406Sopenharmony_cistatic SANE_Bool request_push_button_status (SANE_Handle handle, 862141cc406Sopenharmony_ci SANE_Bool * theButtonStatus); 863141cc406Sopenharmony_cistatic void activateOption (Epson_Scanner * s, SANE_Int option, 864141cc406Sopenharmony_ci SANE_Bool * change); 865141cc406Sopenharmony_cistatic void deactivateOption (Epson_Scanner * s, SANE_Int option, 866141cc406Sopenharmony_ci SANE_Bool * change); 867141cc406Sopenharmony_cistatic void setOptionState (Epson_Scanner * s, SANE_Bool state, 868141cc406Sopenharmony_ci SANE_Int option, SANE_Bool * change); 869141cc406Sopenharmony_cistatic void close_scanner (Epson_Scanner * s); 870141cc406Sopenharmony_cistatic SANE_Status open_scanner (Epson_Scanner * s); 871141cc406Sopenharmony_ciSANE_Status sane_auto_eject (Epson_Scanner * s); 872141cc406Sopenharmony_cistatic SANE_Status attach_one_usb (SANE_String_Const devname); 873141cc406Sopenharmony_cistatic void filter_resolution_list (Epson_Scanner * s); 874141cc406Sopenharmony_cistatic void get_size (char c1, char c2, double *w, double *h); 875141cc406Sopenharmony_cistatic void scan_finish (Epson_Scanner * s); 876141cc406Sopenharmony_ci 877141cc406Sopenharmony_ci/* 878141cc406Sopenharmony_ci * 879141cc406Sopenharmony_ci * 880141cc406Sopenharmony_ci */ 881141cc406Sopenharmony_ci 882141cc406Sopenharmony_cistatic int 883141cc406Sopenharmony_cisend (Epson_Scanner * s, void *buf, size_t buf_size, SANE_Status * status) 884141cc406Sopenharmony_ci{ 885141cc406Sopenharmony_ci DBG (3, "send buf, size = %lu\n", (u_long) buf_size); 886141cc406Sopenharmony_ci 887141cc406Sopenharmony_ci#if 1 888141cc406Sopenharmony_ci { 889141cc406Sopenharmony_ci unsigned int k; 890141cc406Sopenharmony_ci const u_char *s = buf; 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci for (k = 0; k < buf_size; k++) 893141cc406Sopenharmony_ci { 894141cc406Sopenharmony_ci DBG (125, "buf[%d] %02x %c\n", k, s[k], isprint (s[k]) ? s[k] : '.'); 895141cc406Sopenharmony_ci } 896141cc406Sopenharmony_ci } 897141cc406Sopenharmony_ci#endif 898141cc406Sopenharmony_ci 899141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_SCSI) 900141cc406Sopenharmony_ci { 901141cc406Sopenharmony_ci return sanei_epson_scsi_write (s->fd, buf, buf_size, status); 902141cc406Sopenharmony_ci } 903141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_PIO) 904141cc406Sopenharmony_ci { 905141cc406Sopenharmony_ci size_t n; 906141cc406Sopenharmony_ci 907141cc406Sopenharmony_ci if (buf_size == (n = sanei_pio_write (s->fd, buf, buf_size))) 908141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 909141cc406Sopenharmony_ci else 910141cc406Sopenharmony_ci *status = SANE_STATUS_INVAL; 911141cc406Sopenharmony_ci 912141cc406Sopenharmony_ci return n; 913141cc406Sopenharmony_ci } 914141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 915141cc406Sopenharmony_ci { 916141cc406Sopenharmony_ci size_t n; 917141cc406Sopenharmony_ci n = buf_size; 918141cc406Sopenharmony_ci *status = sanei_usb_write_bulk (s->fd, buf, &n); 919141cc406Sopenharmony_ci w_cmd_count++; 920141cc406Sopenharmony_ci DBG (5, "w_cmd_count = %d\n",w_cmd_count); 921141cc406Sopenharmony_ci DBG (5, "r_cmd_count = %d\n",r_cmd_count); 922141cc406Sopenharmony_ci 923141cc406Sopenharmony_ci return n; 924141cc406Sopenharmony_ci } 925141cc406Sopenharmony_ci 926141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 927141cc406Sopenharmony_ci /* never reached */ 928141cc406Sopenharmony_ci} 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_ci/* 931141cc406Sopenharmony_ci * 932141cc406Sopenharmony_ci * 933141cc406Sopenharmony_ci */ 934141cc406Sopenharmony_ci 935141cc406Sopenharmony_cistatic ssize_t 936141cc406Sopenharmony_cireceive (Epson_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status) 937141cc406Sopenharmony_ci{ 938141cc406Sopenharmony_ci ssize_t n = 0; 939141cc406Sopenharmony_ci 940141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_SCSI) 941141cc406Sopenharmony_ci { 942141cc406Sopenharmony_ci n = sanei_epson_scsi_read (s->fd, buf, buf_size, status); 943141cc406Sopenharmony_ci } 944141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_PIO) 945141cc406Sopenharmony_ci { 946141cc406Sopenharmony_ci if (buf_size == (n = sanei_pio_read (s->fd, buf, (size_t) buf_size))) 947141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 948141cc406Sopenharmony_ci else 949141cc406Sopenharmony_ci *status = SANE_STATUS_INVAL; 950141cc406Sopenharmony_ci } 951141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 952141cc406Sopenharmony_ci { 953141cc406Sopenharmony_ci /* !!! only report an error if we don't read anything */ 954141cc406Sopenharmony_ci n = buf_size; /* buf_size gets overwritten */ 955141cc406Sopenharmony_ci *status = sanei_usb_read_bulk (s->fd, (SANE_Byte *) buf, (size_t *) & n); 956141cc406Sopenharmony_ci r_cmd_count += (n+63)/64; /* add # of packets, rounding up */ 957141cc406Sopenharmony_ci DBG (5, "w_cmd_count = %d\n",w_cmd_count); 958141cc406Sopenharmony_ci DBG (5, "r_cmd_count = %d\n",r_cmd_count); 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci if (n > 0) 961141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 962141cc406Sopenharmony_ci } 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci DBG (7, "receive buf, expected = %lu, got = %ld\n", (u_long) buf_size, (long) n); 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci#if 1 967141cc406Sopenharmony_ci if (n > 0) 968141cc406Sopenharmony_ci { 969141cc406Sopenharmony_ci int k; 970141cc406Sopenharmony_ci const u_char *s = buf; 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci for (k = 0; k < n; k++) 973141cc406Sopenharmony_ci { 974141cc406Sopenharmony_ci DBG (127, "buf[%d] %02x %c\n", k, s[k], isprint (s[k]) ? s[k] : '.'); 975141cc406Sopenharmony_ci } 976141cc406Sopenharmony_ci } 977141cc406Sopenharmony_ci#else 978141cc406Sopenharmony_ci { 979141cc406Sopenharmony_ci int i; 980141cc406Sopenharmony_ci ssize_t k; 981141cc406Sopenharmony_ci ssize_t hex_start = 0; 982141cc406Sopenharmony_ci const u_char *s = buf; 983141cc406Sopenharmony_ci char hex_str[NUM_OF_HEX_ELEMENTS * 3 + 1]; 984141cc406Sopenharmony_ci char tmp_str[NUM_OF_HEX_ELEMENTS * 3 + 1]; 985141cc406Sopenharmony_ci char ascii_str[NUM_OF_HEX_ELEMENTS * 2 + 1]; 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci hex_str[0] = '\0'; 988141cc406Sopenharmony_ci ascii_str[0] = '\0'; 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci for (k = 0; k < buf_size; k++) 991141cc406Sopenharmony_ci { 992141cc406Sopenharmony_ci /* write out the data in lines of 16 bytes */ 993141cc406Sopenharmony_ci /* add the next hex value to the hex string */ 994141cc406Sopenharmony_ci sprintf (tmp_str, "%s %02x", hex_str, s[k]); 995141cc406Sopenharmony_ci strcpy (hex_str, tmp_str); 996141cc406Sopenharmony_ci 997141cc406Sopenharmony_ci /* add the character to the ascii string */ 998141cc406Sopenharmony_ci sprintf (tmp_str, "%s %c", ascii_str, isprint (s[k]) ? s[k] : '.'); 999141cc406Sopenharmony_ci strcpy (ascii_str, tmp_str); 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci if ((k % (NUM_OF_HEX_ELEMENTS)) == 0) 1002141cc406Sopenharmony_ci { 1003141cc406Sopenharmony_ci if (k != 0) /* don't do this the first time */ 1004141cc406Sopenharmony_ci { 1005141cc406Sopenharmony_ci for (i = strlen (hex_str); i < (NUM_OF_HEX_ELEMENTS * 3); i++) 1006141cc406Sopenharmony_ci { 1007141cc406Sopenharmony_ci hex_str[i] = ' '; 1008141cc406Sopenharmony_ci } 1009141cc406Sopenharmony_ci hex_str[NUM_OF_HEX_ELEMENTS + 1] = '\0'; 1010141cc406Sopenharmony_ci 1011141cc406Sopenharmony_ci DBG (125, "recv buf[%05d]: %s %s\n", hex_start, hex_str, 1012141cc406Sopenharmony_ci ascii_str); 1013141cc406Sopenharmony_ci hex_start = k; 1014141cc406Sopenharmony_ci hex_str[0] = '\0'; 1015141cc406Sopenharmony_ci ascii_str[0] = '\0'; 1016141cc406Sopenharmony_ci } 1017141cc406Sopenharmony_ci } 1018141cc406Sopenharmony_ci } 1019141cc406Sopenharmony_ci 1020141cc406Sopenharmony_ci for (i = strlen (hex_str); i < NUM_OF_HEX_ELEMENTS * 3; i++) 1021141cc406Sopenharmony_ci { 1022141cc406Sopenharmony_ci hex_str[i] = ' '; 1023141cc406Sopenharmony_ci } 1024141cc406Sopenharmony_ci hex_str[NUM_OF_HEX_ELEMENTS + 1] = '\0'; 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci DBG (125, "recv buf[%05d]: %s %s\n", hex_start, hex_str, ascii_str); 1027141cc406Sopenharmony_ci } 1028141cc406Sopenharmony_ci#endif 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci return n; 1031141cc406Sopenharmony_ci} 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ci/* 1034141cc406Sopenharmony_ci * 1035141cc406Sopenharmony_ci * 1036141cc406Sopenharmony_ci */ 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_cistatic SANE_Status 1039141cc406Sopenharmony_ciexpect_ack (Epson_Scanner * s) 1040141cc406Sopenharmony_ci{ 1041141cc406Sopenharmony_ci u_char result[1]; 1042141cc406Sopenharmony_ci size_t len; 1043141cc406Sopenharmony_ci SANE_Status status; 1044141cc406Sopenharmony_ci 1045141cc406Sopenharmony_ci len = sizeof (result); 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci receive (s, result, len, &status); 1048141cc406Sopenharmony_ci 1049141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 1050141cc406Sopenharmony_ci return status; 1051141cc406Sopenharmony_ci 1052141cc406Sopenharmony_ci if (ACK != result[0]) 1053141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1054141cc406Sopenharmony_ci 1055141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1056141cc406Sopenharmony_ci} 1057141cc406Sopenharmony_ci 1058141cc406Sopenharmony_ci/* 1059141cc406Sopenharmony_ci * 1060141cc406Sopenharmony_ci * 1061141cc406Sopenharmony_ci */ 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_cistatic SANE_Status 1064141cc406Sopenharmony_ciset_cmd (Epson_Scanner * s, u_char cmd, int val) 1065141cc406Sopenharmony_ci{ 1066141cc406Sopenharmony_ci SANE_Status status; 1067141cc406Sopenharmony_ci u_char params[2]; 1068141cc406Sopenharmony_ci 1069141cc406Sopenharmony_ci if (!cmd) 1070141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1071141cc406Sopenharmony_ci 1072141cc406Sopenharmony_ci params[0] = ESC; 1073141cc406Sopenharmony_ci params[1] = cmd; 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_ci send (s, params, 2, &status); 1076141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = expect_ack (s))) 1077141cc406Sopenharmony_ci return status; 1078141cc406Sopenharmony_ci 1079141cc406Sopenharmony_ci params[0] = val; 1080141cc406Sopenharmony_ci send (s, params, 1, &status); 1081141cc406Sopenharmony_ci status = expect_ack (s); 1082141cc406Sopenharmony_ci 1083141cc406Sopenharmony_ci return status; 1084141cc406Sopenharmony_ci} 1085141cc406Sopenharmony_ci 1086141cc406Sopenharmony_ci/* A little helper function to correct the extended status reply 1087141cc406Sopenharmony_ci gotten from scanners with known buggy firmware. 1088141cc406Sopenharmony_ci */ 1089141cc406Sopenharmony_cistatic void 1090141cc406Sopenharmony_cifix_up_extended_status_reply (const char *model, u_char * buf) 1091141cc406Sopenharmony_ci{ 1092141cc406Sopenharmony_ci 1093141cc406Sopenharmony_ci if (0 == strncmp (model, "ES-9000H", strlen ("ES-9000H")) 1094141cc406Sopenharmony_ci || 0 == strncmp (model, "GT-30000", strlen ("GT-30000"))) 1095141cc406Sopenharmony_ci { 1096141cc406Sopenharmony_ci DBG (1, "Fixing up buggy ADF max scan dimensions.\n"); 1097141cc406Sopenharmony_ci buf[2] = 0xB0; 1098141cc406Sopenharmony_ci buf[3] = 0x6D; 1099141cc406Sopenharmony_ci buf[4] = 0x60; 1100141cc406Sopenharmony_ci buf[5] = 0x9F; 1101141cc406Sopenharmony_ci } 1102141cc406Sopenharmony_ci} 1103141cc406Sopenharmony_ci 1104141cc406Sopenharmony_cistatic void 1105141cc406Sopenharmony_ciprint_params (const SANE_Parameters params) 1106141cc406Sopenharmony_ci{ 1107141cc406Sopenharmony_ci DBG (5, "params.format = %d\n", params.format); 1108141cc406Sopenharmony_ci DBG (5, "params.last_frame = %d\n", params.last_frame); 1109141cc406Sopenharmony_ci DBG (5, "params.bytes_per_line = %d\n", params.bytes_per_line); 1110141cc406Sopenharmony_ci DBG (5, "params.pixels_per_line = %d\n", params.pixels_per_line); 1111141cc406Sopenharmony_ci DBG (5, "params.lines = %d\n", params.lines); 1112141cc406Sopenharmony_ci DBG (5, "params.depth = %d\n", params.depth); 1113141cc406Sopenharmony_ci} 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci 1116141cc406Sopenharmony_ci/* 1117141cc406Sopenharmony_ci * 1118141cc406Sopenharmony_ci * 1119141cc406Sopenharmony_ci */ 1120141cc406Sopenharmony_ci 1121141cc406Sopenharmony_ci#define set_focus_position(s,v) set_cmd( s,(s)->hw->cmd->set_focus_position,v) 1122141cc406Sopenharmony_ci#define set_color_mode(s,v) set_cmd( s,(s)->hw->cmd->set_color_mode,v) 1123141cc406Sopenharmony_ci#define set_data_format(s,v) set_cmd( s,(s)->hw->cmd->set_data_format, v) 1124141cc406Sopenharmony_ci#define set_halftoning(s,v) set_cmd( s,(s)->hw->cmd->set_halftoning, v) 1125141cc406Sopenharmony_ci#define set_gamma(s,v) set_cmd( s,(s)->hw->cmd->set_gamma, v) 1126141cc406Sopenharmony_ci#define set_color_correction(s,v) set_cmd( s,(s)->hw->cmd->set_color_correction, v) 1127141cc406Sopenharmony_ci#define set_lcount(s,v) set_cmd( s,(s)->hw->cmd->set_lcount, v) 1128141cc406Sopenharmony_ci#define set_bright(s,v) set_cmd( s,(s)->hw->cmd->set_bright, v) 1129141cc406Sopenharmony_ci#define mirror_image(s,v) set_cmd( s,(s)->hw->cmd->mirror_image, v) 1130141cc406Sopenharmony_ci#define set_speed(s,v) set_cmd( s,(s)->hw->cmd->set_speed, v) 1131141cc406Sopenharmony_ci#define set_outline_emphasis(s,v) set_cmd( s,(s)->hw->cmd->set_outline_emphasis, v) 1132141cc406Sopenharmony_ci#define control_auto_area_segmentation(s,v) set_cmd( s,(s)->hw->cmd->control_auto_area_segmentation, v) 1133141cc406Sopenharmony_ci#define set_film_type(s,v) set_cmd( s,(s)->hw->cmd->set_film_type, v) 1134141cc406Sopenharmony_ci#define set_exposure_time(s,v) set_cmd( s,(s)->hw->cmd->set_exposure_time, v) 1135141cc406Sopenharmony_ci#define set_bay(s,v) set_cmd( s,(s)->hw->cmd->set_bay, v) 1136141cc406Sopenharmony_ci#define set_threshold(s,v) set_cmd( s,(s)->hw->cmd->set_threshold, v) 1137141cc406Sopenharmony_ci#define control_extension(s,v) set_cmd( s,(s)->hw->cmd->control_an_extension, v) 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci/*#define (s,v) set_cmd( s,(s)->hw->cmd->, v) */ 1140141cc406Sopenharmony_ci 1141141cc406Sopenharmony_cistatic SANE_Status 1142141cc406Sopenharmony_ciset_zoom (Epson_Scanner * s, int x_zoom, int y_zoom) 1143141cc406Sopenharmony_ci{ 1144141cc406Sopenharmony_ci SANE_Status status; 1145141cc406Sopenharmony_ci u_char cmd[2]; 1146141cc406Sopenharmony_ci u_char params[2]; 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci if (!s->hw->cmd->set_zoom) 1149141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1150141cc406Sopenharmony_ci 1151141cc406Sopenharmony_ci cmd[0] = ESC; 1152141cc406Sopenharmony_ci cmd[1] = s->hw->cmd->set_zoom; 1153141cc406Sopenharmony_ci 1154141cc406Sopenharmony_ci send (s, cmd, 2, &status); 1155141cc406Sopenharmony_ci status = expect_ack (s); 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1158141cc406Sopenharmony_ci return status; 1159141cc406Sopenharmony_ci 1160141cc406Sopenharmony_ci params[0] = x_zoom; 1161141cc406Sopenharmony_ci params[1] = y_zoom; 1162141cc406Sopenharmony_ci 1163141cc406Sopenharmony_ci send (s, params, 2, &status); 1164141cc406Sopenharmony_ci status = expect_ack (s); 1165141cc406Sopenharmony_ci 1166141cc406Sopenharmony_ci return status; 1167141cc406Sopenharmony_ci} 1168141cc406Sopenharmony_ci 1169141cc406Sopenharmony_ci 1170141cc406Sopenharmony_cistatic SANE_Status 1171141cc406Sopenharmony_ciset_resolution (Epson_Scanner * s, int xres, int yres) 1172141cc406Sopenharmony_ci{ 1173141cc406Sopenharmony_ci SANE_Status status; 1174141cc406Sopenharmony_ci u_char params[4]; 1175141cc406Sopenharmony_ci 1176141cc406Sopenharmony_ci if (!s->hw->cmd->set_resolution) 1177141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1178141cc406Sopenharmony_ci 1179141cc406Sopenharmony_ci params[0] = ESC; 1180141cc406Sopenharmony_ci params[1] = s->hw->cmd->set_resolution; 1181141cc406Sopenharmony_ci 1182141cc406Sopenharmony_ci send (s, params, 2, &status); 1183141cc406Sopenharmony_ci status = expect_ack (s); 1184141cc406Sopenharmony_ci 1185141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1186141cc406Sopenharmony_ci return status; 1187141cc406Sopenharmony_ci 1188141cc406Sopenharmony_ci params[0] = xres; 1189141cc406Sopenharmony_ci params[1] = xres >> 8; 1190141cc406Sopenharmony_ci params[2] = yres; 1191141cc406Sopenharmony_ci params[3] = yres >> 8; 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci send (s, params, 4, &status); 1194141cc406Sopenharmony_ci status = expect_ack (s); 1195141cc406Sopenharmony_ci 1196141cc406Sopenharmony_ci return status; 1197141cc406Sopenharmony_ci} 1198141cc406Sopenharmony_ci 1199141cc406Sopenharmony_ci/* 1200141cc406Sopenharmony_ci * set_scan_area() 1201141cc406Sopenharmony_ci * 1202141cc406Sopenharmony_ci * Sends the "set scan area" command to the scanner with the currently selected 1203141cc406Sopenharmony_ci * scan area. This scan area is already corrected for "color shuffling" if 1204141cc406Sopenharmony_ci * necessary. 1205141cc406Sopenharmony_ci */ 1206141cc406Sopenharmony_cistatic SANE_Status 1207141cc406Sopenharmony_ciset_scan_area (Epson_Scanner * s, int x, int y, int width, int height) 1208141cc406Sopenharmony_ci{ 1209141cc406Sopenharmony_ci SANE_Status status; 1210141cc406Sopenharmony_ci u_char params[8]; 1211141cc406Sopenharmony_ci 1212141cc406Sopenharmony_ci DBG (1, "set_scan_area: %p %d %d %d %d\n", (void *) s, x, y, width, height); 1213141cc406Sopenharmony_ci 1214141cc406Sopenharmony_ci if (!s->hw->cmd->set_scan_area) 1215141cc406Sopenharmony_ci { 1216141cc406Sopenharmony_ci DBG (1, "set_scan_area not supported\n"); 1217141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1218141cc406Sopenharmony_ci } 1219141cc406Sopenharmony_ci 1220141cc406Sopenharmony_ci /* verify the scan area */ 1221141cc406Sopenharmony_ci if (x < 0 || y < 0 || width <= 0 || height <= 0) 1222141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci params[0] = ESC; 1225141cc406Sopenharmony_ci params[1] = s->hw->cmd->set_scan_area; 1226141cc406Sopenharmony_ci 1227141cc406Sopenharmony_ci send (s, params, 2, &status); 1228141cc406Sopenharmony_ci status = expect_ack (s); 1229141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1230141cc406Sopenharmony_ci return status; 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci params[0] = x; 1233141cc406Sopenharmony_ci params[1] = x >> 8; 1234141cc406Sopenharmony_ci params[2] = y; 1235141cc406Sopenharmony_ci params[3] = y >> 8; 1236141cc406Sopenharmony_ci params[4] = width; 1237141cc406Sopenharmony_ci params[5] = width >> 8; 1238141cc406Sopenharmony_ci params[6] = height; 1239141cc406Sopenharmony_ci params[7] = height >> 8; 1240141cc406Sopenharmony_ci 1241141cc406Sopenharmony_ci send (s, params, 8, &status); 1242141cc406Sopenharmony_ci status = expect_ack (s); 1243141cc406Sopenharmony_ci 1244141cc406Sopenharmony_ci return status; 1245141cc406Sopenharmony_ci} 1246141cc406Sopenharmony_ci 1247141cc406Sopenharmony_ci/* 1248141cc406Sopenharmony_ci * set_color_correction_coefficients() 1249141cc406Sopenharmony_ci * 1250141cc406Sopenharmony_ci * Sends the "set color correction coefficients" command with the currently selected 1251141cc406Sopenharmony_ci * parameters to the scanner. 1252141cc406Sopenharmony_ci */ 1253141cc406Sopenharmony_ci 1254141cc406Sopenharmony_cistatic SANE_Status 1255141cc406Sopenharmony_ciset_color_correction_coefficients (Epson_Scanner * s) 1256141cc406Sopenharmony_ci{ 1257141cc406Sopenharmony_ci SANE_Status status; 1258141cc406Sopenharmony_ci u_char cmd = s->hw->cmd->set_color_correction_coefficients; 1259141cc406Sopenharmony_ci u_char params[2]; 1260141cc406Sopenharmony_ci const int length = 9; 1261141cc406Sopenharmony_ci signed char cct[9]; 1262141cc406Sopenharmony_ci 1263141cc406Sopenharmony_ci DBG (1, "set_color_correction_coefficients: starting.\n"); 1264141cc406Sopenharmony_ci if (!cmd) 1265141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1266141cc406Sopenharmony_ci 1267141cc406Sopenharmony_ci params[0] = ESC; 1268141cc406Sopenharmony_ci params[1] = cmd; 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci send (s, params, 2, &status); 1271141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = expect_ack (s))) 1272141cc406Sopenharmony_ci return status; 1273141cc406Sopenharmony_ci 1274141cc406Sopenharmony_ci cct[0] = s->val[OPT_CCT_1].w; 1275141cc406Sopenharmony_ci cct[1] = s->val[OPT_CCT_2].w; 1276141cc406Sopenharmony_ci cct[2] = s->val[OPT_CCT_3].w; 1277141cc406Sopenharmony_ci cct[3] = s->val[OPT_CCT_4].w; 1278141cc406Sopenharmony_ci cct[4] = s->val[OPT_CCT_5].w; 1279141cc406Sopenharmony_ci cct[5] = s->val[OPT_CCT_6].w; 1280141cc406Sopenharmony_ci cct[6] = s->val[OPT_CCT_7].w; 1281141cc406Sopenharmony_ci cct[7] = s->val[OPT_CCT_8].w; 1282141cc406Sopenharmony_ci cct[8] = s->val[OPT_CCT_9].w; 1283141cc406Sopenharmony_ci 1284141cc406Sopenharmony_ci DBG (1, "set_color_correction_coefficients: %d,%d,%d %d,%d,%d %d,%d,%d.\n", 1285141cc406Sopenharmony_ci cct[0], cct[1], cct[2], cct[3], 1286141cc406Sopenharmony_ci cct[4], cct[5], cct[6], cct[7], cct[8]); 1287141cc406Sopenharmony_ci 1288141cc406Sopenharmony_ci send (s, cct, length, &status); 1289141cc406Sopenharmony_ci status = expect_ack (s); 1290141cc406Sopenharmony_ci DBG (1, "set_color_correction_coefficients: ending=%d.\n", status); 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci return status; 1293141cc406Sopenharmony_ci} 1294141cc406Sopenharmony_ci 1295141cc406Sopenharmony_ci/* 1296141cc406Sopenharmony_ci * 1297141cc406Sopenharmony_ci * 1298141cc406Sopenharmony_ci */ 1299141cc406Sopenharmony_ci 1300141cc406Sopenharmony_cistatic SANE_Status 1301141cc406Sopenharmony_ciset_gamma_table (Epson_Scanner * s) 1302141cc406Sopenharmony_ci{ 1303141cc406Sopenharmony_ci 1304141cc406Sopenharmony_ci SANE_Status status; 1305141cc406Sopenharmony_ci u_char cmd = s->hw->cmd->set_gamma_table; 1306141cc406Sopenharmony_ci u_char params[2]; 1307141cc406Sopenharmony_ci const int length = 257; 1308141cc406Sopenharmony_ci u_char gamma[257]; 1309141cc406Sopenharmony_ci int n; 1310141cc406Sopenharmony_ci int table; 1311141cc406Sopenharmony_ci/* static const char gamma_cmds[] = { 'M', 'R', 'G', 'B' }; */ 1312141cc406Sopenharmony_ci static const char gamma_cmds[] = { 'R', 'G', 'B' }; 1313141cc406Sopenharmony_ci 1314141cc406Sopenharmony_ci 1315141cc406Sopenharmony_ci DBG (1, "set_gamma_table: starting.\n"); 1316141cc406Sopenharmony_ci if (!cmd) 1317141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1318141cc406Sopenharmony_ci 1319141cc406Sopenharmony_ci params[0] = ESC; 1320141cc406Sopenharmony_ci params[1] = cmd; 1321141cc406Sopenharmony_ci 1322141cc406Sopenharmony_ci/* 1323141cc406Sopenharmony_ci * Print the gamma tables before sending them to the scanner. 1324141cc406Sopenharmony_ci */ 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci if (DBG_LEVEL > 0) 1327141cc406Sopenharmony_ci { 1328141cc406Sopenharmony_ci int c, i, j; 1329141cc406Sopenharmony_ci 1330141cc406Sopenharmony_ci DBG (1, "set_gamma_table()\n"); 1331141cc406Sopenharmony_ci for (c = 0; c < 3; c++) 1332141cc406Sopenharmony_ci { 1333141cc406Sopenharmony_ci for (i = 0; i < 256; i += 16) 1334141cc406Sopenharmony_ci { 1335141cc406Sopenharmony_ci char gammaValues[16 * 3 + 1], newValue[4]; 1336141cc406Sopenharmony_ci 1337141cc406Sopenharmony_ci gammaValues[0] = '\0'; 1338141cc406Sopenharmony_ci 1339141cc406Sopenharmony_ci for (j = 0; j < 16; j++) 1340141cc406Sopenharmony_ci { 1341141cc406Sopenharmony_ci sprintf (newValue, " %02x", s->gamma_table[c][i + j]); 1342141cc406Sopenharmony_ci strcat (gammaValues, newValue); 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci DBG (10, "Gamma Table[%d][%d] %s\n", c, i, gammaValues); 1346141cc406Sopenharmony_ci } 1347141cc406Sopenharmony_ci } 1348141cc406Sopenharmony_ci } 1349141cc406Sopenharmony_ci 1350141cc406Sopenharmony_ci 1351141cc406Sopenharmony_ci/* 1352141cc406Sopenharmony_ci * TODO: &status in send makes no sense like that. 1353141cc406Sopenharmony_ci */ 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci/* 1356141cc406Sopenharmony_ci * When handling inverted images, we must also invert the user 1357141cc406Sopenharmony_ci * supplied gamma function. This is *not* just 255-gamma - 1358141cc406Sopenharmony_ci * this gives a negative image. 1359141cc406Sopenharmony_ci */ 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci for (table = 0; table < 3; table++) 1362141cc406Sopenharmony_ci { 1363141cc406Sopenharmony_ci gamma[0] = gamma_cmds[table]; 1364141cc406Sopenharmony_ci if (s->invert_image) 1365141cc406Sopenharmony_ci { 1366141cc406Sopenharmony_ci for (n = 0; n < 256; ++n) 1367141cc406Sopenharmony_ci { 1368141cc406Sopenharmony_ci gamma[n + 1] = 255 - s->gamma_table[table][255 - n]; 1369141cc406Sopenharmony_ci } 1370141cc406Sopenharmony_ci } 1371141cc406Sopenharmony_ci else 1372141cc406Sopenharmony_ci { 1373141cc406Sopenharmony_ci for (n = 0; n < 256; ++n) 1374141cc406Sopenharmony_ci { 1375141cc406Sopenharmony_ci gamma[n + 1] = s->gamma_table[table][n]; 1376141cc406Sopenharmony_ci } 1377141cc406Sopenharmony_ci } 1378141cc406Sopenharmony_ci 1379141cc406Sopenharmony_ci send (s, params, 2, &status); 1380141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = expect_ack (s))) 1381141cc406Sopenharmony_ci return status; 1382141cc406Sopenharmony_ci 1383141cc406Sopenharmony_ci send (s, gamma, length, &status); 1384141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = expect_ack (s))) 1385141cc406Sopenharmony_ci return status; 1386141cc406Sopenharmony_ci 1387141cc406Sopenharmony_ci } 1388141cc406Sopenharmony_ci 1389141cc406Sopenharmony_ci DBG (1, "set_gamma_table: complete = %d.\n", status); 1390141cc406Sopenharmony_ci 1391141cc406Sopenharmony_ci return status; 1392141cc406Sopenharmony_ci} 1393141cc406Sopenharmony_ci 1394141cc406Sopenharmony_ci 1395141cc406Sopenharmony_ci 1396141cc406Sopenharmony_civoid 1397141cc406Sopenharmony_ciget_size (char c1, char c2, double *w, double *h) 1398141cc406Sopenharmony_ci{ 1399141cc406Sopenharmony_ci int ind; 1400141cc406Sopenharmony_ci unsigned char flag; 1401141cc406Sopenharmony_ci 1402141cc406Sopenharmony_ci double wsizetbl[] = { 1403141cc406Sopenharmony_ci 11.60, /* A3V */ 1404141cc406Sopenharmony_ci 11.00, /* WLT */ 1405141cc406Sopenharmony_ci 10.12, /* B4V */ 1406141cc406Sopenharmony_ci 8.50, /* LGV */ 1407141cc406Sopenharmony_ci 8.27, /* A4V */ 1408141cc406Sopenharmony_ci 11.69, /* A4H */ 1409141cc406Sopenharmony_ci 8.50, /* LTV */ 1410141cc406Sopenharmony_ci 11.00, /* LTH */ 1411141cc406Sopenharmony_ci 7.17, /* B5V */ 1412141cc406Sopenharmony_ci 10.12, /* B5H */ 1413141cc406Sopenharmony_ci 5.83, /* A5V */ 1414141cc406Sopenharmony_ci 8.27, /* A5H */ 1415141cc406Sopenharmony_ci 7.25, /* EXV */ 1416141cc406Sopenharmony_ci 10.50, /* EXH */ 1417141cc406Sopenharmony_ci 11.69, /* unknown */ 1418141cc406Sopenharmony_ci 11.69, /* unknown */ 1419141cc406Sopenharmony_ci 11.69, /* unknown */ 1420141cc406Sopenharmony_ci }; 1421141cc406Sopenharmony_ci double hsizetbl[] = { 1422141cc406Sopenharmony_ci 16.54, /* A3V */ 1423141cc406Sopenharmony_ci 17.00, /* WLT */ 1424141cc406Sopenharmony_ci 14.33, /* B4V */ 1425141cc406Sopenharmony_ci 14.00, /* LGV */ 1426141cc406Sopenharmony_ci 11.69, /* A4V */ 1427141cc406Sopenharmony_ci 8.27, /* A4H */ 1428141cc406Sopenharmony_ci 11.00, /* LTV */ 1429141cc406Sopenharmony_ci 8.50, /* LTH */ 1430141cc406Sopenharmony_ci 10.12, /* B5V */ 1431141cc406Sopenharmony_ci 7.17, /* B5H */ 1432141cc406Sopenharmony_ci 8.27, /* A5V */ 1433141cc406Sopenharmony_ci 5.83, /* A5H */ 1434141cc406Sopenharmony_ci 10.50, /* EXV */ 1435141cc406Sopenharmony_ci 7.25, /* EXH */ 1436141cc406Sopenharmony_ci 17.00, /* unknown */ 1437141cc406Sopenharmony_ci 17.00, /* unknown */ 1438141cc406Sopenharmony_ci 17.00, /* unknown */ 1439141cc406Sopenharmony_ci }; 1440141cc406Sopenharmony_ci 1441141cc406Sopenharmony_ci flag = c1; 1442141cc406Sopenharmony_ci for (ind = 0; ind < 8; ind++) 1443141cc406Sopenharmony_ci { 1444141cc406Sopenharmony_ci if (flag & 0x80) 1445141cc406Sopenharmony_ci goto DetectSize; 1446141cc406Sopenharmony_ci flag = flag << 1; 1447141cc406Sopenharmony_ci } 1448141cc406Sopenharmony_ci flag = c2; 1449141cc406Sopenharmony_ci for (; ind < 16; ind++) 1450141cc406Sopenharmony_ci { 1451141cc406Sopenharmony_ci if (flag & 0x80) 1452141cc406Sopenharmony_ci goto DetectSize; 1453141cc406Sopenharmony_ci flag = flag << 1; 1454141cc406Sopenharmony_ci } 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ciDetectSize: 1457141cc406Sopenharmony_ci 1458141cc406Sopenharmony_ci *w = wsizetbl[ind]; 1459141cc406Sopenharmony_ci *h = hsizetbl[ind]; 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci DBG (10, "detected width: %f\n", *w); 1462141cc406Sopenharmony_ci DBG (10, "detected height: %f\n", *h); 1463141cc406Sopenharmony_ci} 1464141cc406Sopenharmony_ci 1465141cc406Sopenharmony_ci 1466141cc406Sopenharmony_ci/* 1467141cc406Sopenharmony_ci * check_ext_status() 1468141cc406Sopenharmony_ci * 1469141cc406Sopenharmony_ci * Requests the extended status flag from the scanner. The "warming up" condition 1470141cc406Sopenharmony_ci * is reported as a warning (only visible if debug level is set to 10 or greater) - 1471141cc406Sopenharmony_ci * every other condition is reported as an error. 1472141cc406Sopenharmony_ci * 1473141cc406Sopenharmony_ci * This function only gets called when we are dealing with a scanner that supports the 1474141cc406Sopenharmony_ci * "warming up" code, so it's not a problem for B3 level scanners, that don't handle 1475141cc406Sopenharmony_ci * request extended status commands. 1476141cc406Sopenharmony_ci */ 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_cistatic SANE_Status 1479141cc406Sopenharmony_cicheck_ext_status (Epson_Scanner * s, int *max_x, int *max_y) 1480141cc406Sopenharmony_ci{ 1481141cc406Sopenharmony_ci SANE_Status status; 1482141cc406Sopenharmony_ci u_char cmd = s->hw->cmd->request_extended_status; 1483141cc406Sopenharmony_ci u_char params[2]; 1484141cc406Sopenharmony_ci u_char *buf; 1485141cc406Sopenharmony_ci EpsonHdr head; 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci *max_x = 0; 1488141cc406Sopenharmony_ci *max_y = 0; 1489141cc406Sopenharmony_ci 1490141cc406Sopenharmony_ci if (cmd == 0) 1491141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1492141cc406Sopenharmony_ci 1493141cc406Sopenharmony_ci params[0] = ESC; 1494141cc406Sopenharmony_ci params[1] = cmd; 1495141cc406Sopenharmony_ci 1496141cc406Sopenharmony_ci head = (EpsonHdr) command (s, params, 2, &status); 1497141cc406Sopenharmony_ci if (NULL == head) 1498141cc406Sopenharmony_ci { 1499141cc406Sopenharmony_ci DBG (1, "Extended status flag request failed\n"); 1500141cc406Sopenharmony_ci return status; 1501141cc406Sopenharmony_ci } 1502141cc406Sopenharmony_ci 1503141cc406Sopenharmony_ci buf = &head->buf[0]; 1504141cc406Sopenharmony_ci 1505141cc406Sopenharmony_ci if (buf[0] & EXT_STATUS_WU) 1506141cc406Sopenharmony_ci { 1507141cc406Sopenharmony_ci DBG (10, "option: warming up\n"); 1508141cc406Sopenharmony_ci status = SANE_STATUS_DEVICE_BUSY; 1509141cc406Sopenharmony_ci } 1510141cc406Sopenharmony_ci 1511141cc406Sopenharmony_ci if (buf[0] & EXT_STATUS_FER) 1512141cc406Sopenharmony_ci { 1513141cc406Sopenharmony_ci DBG (1, "option: fatal error\n"); 1514141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1515141cc406Sopenharmony_ci } 1516141cc406Sopenharmony_ci 1517141cc406Sopenharmony_ci if (s->hw->ADF && s->hw->use_extension && s->hw->cmd->feed) 1518141cc406Sopenharmony_ci { 1519141cc406Sopenharmony_ci fix_up_extended_status_reply (s->hw->sane.model, buf); 1520141cc406Sopenharmony_ci 1521141cc406Sopenharmony_ci *max_x = buf[3] << 8 | buf[2]; 1522141cc406Sopenharmony_ci *max_y = buf[5] << 8 | buf[4]; 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci if (0 == strcmp ("ES-9000H", s->hw->sane.model) 1525141cc406Sopenharmony_ci || 0 == strcmp ("GT-30000", s->hw->sane.model)) 1526141cc406Sopenharmony_ci { 1527141cc406Sopenharmony_ci /* set size of current sheet, but don't clobber zoom 1528141cc406Sopenharmony_ci settings (which should always be smaller than the 1529141cc406Sopenharmony_ci detected sheet size) */ 1530141cc406Sopenharmony_ci double w, h; 1531141cc406Sopenharmony_ci get_size (buf[16], buf[17], &w, &h); 1532141cc406Sopenharmony_ci w = SANE_FIX (w * MM_PER_INCH); 1533141cc406Sopenharmony_ci h = SANE_FIX (h * MM_PER_INCH); 1534141cc406Sopenharmony_ci if (w < s->val[OPT_BR_X].w) 1535141cc406Sopenharmony_ci s->val[OPT_BR_X].w = w; 1536141cc406Sopenharmony_ci if (h < s->val[OPT_BR_Y].w) 1537141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = h; 1538141cc406Sopenharmony_ci } 1539141cc406Sopenharmony_ci } 1540141cc406Sopenharmony_ci 1541141cc406Sopenharmony_ci 1542141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_ERR) 1543141cc406Sopenharmony_ci { 1544141cc406Sopenharmony_ci DBG (1, "ADF: other error\n"); 1545141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1546141cc406Sopenharmony_ci } 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_PE) 1549141cc406Sopenharmony_ci { 1550141cc406Sopenharmony_ci DBG (1, "ADF: no paper\n"); 1551141cc406Sopenharmony_ci status = SANE_STATUS_NO_DOCS; 1552141cc406Sopenharmony_ci return status; 1553141cc406Sopenharmony_ci } 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_PJ) 1556141cc406Sopenharmony_ci { 1557141cc406Sopenharmony_ci DBG (1, "ADF: paper jam\n"); 1558141cc406Sopenharmony_ci status = SANE_STATUS_JAMMED; 1559141cc406Sopenharmony_ci } 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_OPN) 1562141cc406Sopenharmony_ci { 1563141cc406Sopenharmony_ci DBG (1, "ADF: cover open\n"); 1564141cc406Sopenharmony_ci status = SANE_STATUS_COVER_OPEN; 1565141cc406Sopenharmony_ci } 1566141cc406Sopenharmony_ci 1567141cc406Sopenharmony_ci if (buf[6] & EXT_STATUS_ERR) 1568141cc406Sopenharmony_ci { 1569141cc406Sopenharmony_ci DBG (1, "TPU: other error\n"); 1570141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1571141cc406Sopenharmony_ci } 1572141cc406Sopenharmony_ci 1573141cc406Sopenharmony_ci /* return the max. scan area for the ADF */ 1574141cc406Sopenharmony_ci if (buf[6] & EXT_STATUS_IST) 1575141cc406Sopenharmony_ci { 1576141cc406Sopenharmony_ci *max_x = buf[8] << 8 | buf[7]; 1577141cc406Sopenharmony_ci *max_y = buf[10] << 8 | buf[9]; 1578141cc406Sopenharmony_ci } 1579141cc406Sopenharmony_ci 1580141cc406Sopenharmony_ci /* return the max. scan area for the flatbed */ 1581141cc406Sopenharmony_ci if (s->hw->devtype == 3 && s->hw->use_extension == 0) 1582141cc406Sopenharmony_ci { 1583141cc406Sopenharmony_ci double w, h; 1584141cc406Sopenharmony_ci get_size (buf[18], buf[19], &w, &h); 1585141cc406Sopenharmony_ci *max_x = (int) (w * s->hw->dpi_range.max); 1586141cc406Sopenharmony_ci *max_y = (int) (h * s->hw->dpi_range.max); 1587141cc406Sopenharmony_ci } 1588141cc406Sopenharmony_ci 1589141cc406Sopenharmony_ci free (head); 1590141cc406Sopenharmony_ci 1591141cc406Sopenharmony_ci return status; 1592141cc406Sopenharmony_ci} 1593141cc406Sopenharmony_ci 1594141cc406Sopenharmony_ci/* 1595141cc406Sopenharmony_ci * reset() 1596141cc406Sopenharmony_ci * 1597141cc406Sopenharmony_ci * Send the "initialize scanner" command to the device and reset it. 1598141cc406Sopenharmony_ci * 1599141cc406Sopenharmony_ci */ 1600141cc406Sopenharmony_ci 1601141cc406Sopenharmony_cistatic SANE_Status 1602141cc406Sopenharmony_cireset (Epson_Scanner * s) 1603141cc406Sopenharmony_ci{ 1604141cc406Sopenharmony_ci SANE_Status status; 1605141cc406Sopenharmony_ci u_char param[2]; 1606141cc406Sopenharmony_ci SANE_Bool needToClose = SANE_FALSE; 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci DBG (5, "reset()\n"); 1609141cc406Sopenharmony_ci 1610141cc406Sopenharmony_ci if (!s->hw->cmd->initialize_scanner) 1611141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1612141cc406Sopenharmony_ci 1613141cc406Sopenharmony_ci param[0] = ESC; 1614141cc406Sopenharmony_ci param[1] = s->hw->cmd->initialize_scanner; 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci if (s->fd == -1) 1617141cc406Sopenharmony_ci { 1618141cc406Sopenharmony_ci needToClose = SANE_TRUE; 1619141cc406Sopenharmony_ci DBG (5, "reset calling open_scanner\n"); 1620141cc406Sopenharmony_ci if ((status = open_scanner (s)) != SANE_STATUS_GOOD) 1621141cc406Sopenharmony_ci return status; 1622141cc406Sopenharmony_ci } 1623141cc406Sopenharmony_ci 1624141cc406Sopenharmony_ci send (s, param, 2, &status); 1625141cc406Sopenharmony_ci status = expect_ack (s); 1626141cc406Sopenharmony_ci 1627141cc406Sopenharmony_ci if (needToClose) 1628141cc406Sopenharmony_ci { 1629141cc406Sopenharmony_ci close_scanner (s); 1630141cc406Sopenharmony_ci } 1631141cc406Sopenharmony_ci 1632141cc406Sopenharmony_ci return status; 1633141cc406Sopenharmony_ci} 1634141cc406Sopenharmony_ci 1635141cc406Sopenharmony_ci 1636141cc406Sopenharmony_ci/* 1637141cc406Sopenharmony_ci * close_scanner() 1638141cc406Sopenharmony_ci * 1639141cc406Sopenharmony_ci * Close the open scanner. Depending on the connection method, a different 1640141cc406Sopenharmony_ci * close function is called. 1641141cc406Sopenharmony_ci */ 1642141cc406Sopenharmony_ci 1643141cc406Sopenharmony_cistatic void 1644141cc406Sopenharmony_ciclose_scanner (Epson_Scanner * s) 1645141cc406Sopenharmony_ci{ 1646141cc406Sopenharmony_ci DBG (5, "close_scanner(fd = %d)\n", s->fd); 1647141cc406Sopenharmony_ci 1648141cc406Sopenharmony_ci if (s->fd == -1) 1649141cc406Sopenharmony_ci return; 1650141cc406Sopenharmony_ci 1651141cc406Sopenharmony_ci if (r_cmd_count % 2) 1652141cc406Sopenharmony_ci { 1653141cc406Sopenharmony_ci /* send a request_status. This toggles w_cmd_count and r_cmd_count */ 1654141cc406Sopenharmony_ci u_char param[3]; 1655141cc406Sopenharmony_ci u_char result[5]; 1656141cc406Sopenharmony_ci SANE_Status status; 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci param[0] = ESC; 1659141cc406Sopenharmony_ci param[1] = s->hw->cmd->request_status; 1660141cc406Sopenharmony_ci param[2]='\0'; 1661141cc406Sopenharmony_ci send(s,param,2,&status); 1662141cc406Sopenharmony_ci receive(s,result,4,&status); 1663141cc406Sopenharmony_ci } 1664141cc406Sopenharmony_ci 1665141cc406Sopenharmony_ci 1666141cc406Sopenharmony_ci DBG (5, "w_cmd_count = %d\n",w_cmd_count); 1667141cc406Sopenharmony_ci DBG (5, "r_cmd_count = %d\n",r_cmd_count); 1668141cc406Sopenharmony_ci 1669141cc406Sopenharmony_ci if (w_cmd_count % 2) 1670141cc406Sopenharmony_ci { 1671141cc406Sopenharmony_ci int junk1,junk2; 1672141cc406Sopenharmony_ci 1673141cc406Sopenharmony_ci /* check extended status. This toggles w_cmd_count%2 only */ 1674141cc406Sopenharmony_ci check_ext_status (s,&junk1,&junk2); 1675141cc406Sopenharmony_ci } 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci DBG (5, "w_cmd_count = %d\n",w_cmd_count); 1678141cc406Sopenharmony_ci DBG (5, "r_cmd_count = %d\n",r_cmd_count); 1679141cc406Sopenharmony_ci 1680141cc406Sopenharmony_ci 1681141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_SCSI) 1682141cc406Sopenharmony_ci { 1683141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 1684141cc406Sopenharmony_ci } 1685141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_PIO) 1686141cc406Sopenharmony_ci { 1687141cc406Sopenharmony_ci sanei_pio_close (s->fd); 1688141cc406Sopenharmony_ci } 1689141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 1690141cc406Sopenharmony_ci { 1691141cc406Sopenharmony_ci sanei_usb_close (s->fd); 1692141cc406Sopenharmony_ci } 1693141cc406Sopenharmony_ci 1694141cc406Sopenharmony_ci s->fd = -1; 1695141cc406Sopenharmony_ci return; 1696141cc406Sopenharmony_ci} 1697141cc406Sopenharmony_ci 1698141cc406Sopenharmony_ci/* 1699141cc406Sopenharmony_ci * open_scanner() 1700141cc406Sopenharmony_ci * 1701141cc406Sopenharmony_ci * Open the scanner device. Depending on the connection method, 1702141cc406Sopenharmony_ci * different open functions are called. 1703141cc406Sopenharmony_ci */ 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_cistatic SANE_Status 1706141cc406Sopenharmony_ciopen_scanner (Epson_Scanner * s) 1707141cc406Sopenharmony_ci{ 1708141cc406Sopenharmony_ci SANE_Status status = 0; 1709141cc406Sopenharmony_ci 1710141cc406Sopenharmony_ci DBG (5, "open_scanner()\n"); 1711141cc406Sopenharmony_ci 1712141cc406Sopenharmony_ci if (s->fd != -1) 1713141cc406Sopenharmony_ci { 1714141cc406Sopenharmony_ci DBG (5, "scanner is already open: fd = %d\n", s->fd); 1715141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no need to open the scanner */ 1716141cc406Sopenharmony_ci } 1717141cc406Sopenharmony_ci 1718141cc406Sopenharmony_ci /* don't do this for OS2: */ 1719141cc406Sopenharmony_ci#ifndef HAVE_OS2_H 1720141cc406Sopenharmony_ci#if 0 1721141cc406Sopenharmony_ci /* test the device name */ 1722141cc406Sopenharmony_ci if ((s->hw->connection != SANE_EPSON_PIO) 1723141cc406Sopenharmony_ci && (access (s->hw->sane.name, R_OK | W_OK) != 0)) 1724141cc406Sopenharmony_ci { 1725141cc406Sopenharmony_ci DBG (1, "sane_start: access(%s, R_OK | W_OK) failed\n", s->hw->sane.name); 1726141cc406Sopenharmony_ci return SANE_STATUS_ACCESS_DENIED; 1727141cc406Sopenharmony_ci } 1728141cc406Sopenharmony_ci#endif 1729141cc406Sopenharmony_ci#endif 1730141cc406Sopenharmony_ci 1731141cc406Sopenharmony_ci 1732141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_SCSI) 1733141cc406Sopenharmony_ci { 1734141cc406Sopenharmony_ci status = sanei_scsi_open (s->hw->sane.name, &s->fd, 1735141cc406Sopenharmony_ci sanei_epson_scsi_sense_handler, NULL); 1736141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 1737141cc406Sopenharmony_ci { 1738141cc406Sopenharmony_ci DBG (1, "sane_start: %s open failed: %s\n", s->hw->sane.name, 1739141cc406Sopenharmony_ci sane_strstatus (status)); 1740141cc406Sopenharmony_ci return status; 1741141cc406Sopenharmony_ci } 1742141cc406Sopenharmony_ci } 1743141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_PIO) 1744141cc406Sopenharmony_ci { 1745141cc406Sopenharmony_ci status = sanei_pio_open (s->hw->sane.name, &s->fd); 1746141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 1747141cc406Sopenharmony_ci { 1748141cc406Sopenharmony_ci DBG (1, "sane_start: %s open failed: %s\n", s->hw->sane.name, 1749141cc406Sopenharmony_ci sane_strstatus (status)); 1750141cc406Sopenharmony_ci return status; 1751141cc406Sopenharmony_ci } 1752141cc406Sopenharmony_ci } 1753141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 1754141cc406Sopenharmony_ci { 1755141cc406Sopenharmony_ci status = sanei_usb_open (s->hw->sane.name, &s->fd); 1756141cc406Sopenharmony_ci 1757141cc406Sopenharmony_ci return status; 1758141cc406Sopenharmony_ci } 1759141cc406Sopenharmony_ci 1760141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1761141cc406Sopenharmony_ci} 1762141cc406Sopenharmony_ci 1763141cc406Sopenharmony_ci 1764141cc406Sopenharmony_ci/* 1765141cc406Sopenharmony_ci * feed ( ) 1766141cc406Sopenharmony_ci */ 1767141cc406Sopenharmony_ci 1768141cc406Sopenharmony_cistatic SANE_Status 1769141cc406Sopenharmony_cifeed (Epson_Scanner * s) 1770141cc406Sopenharmony_ci{ 1771141cc406Sopenharmony_ci SANE_Status status; 1772141cc406Sopenharmony_ci u_char params[2]; 1773141cc406Sopenharmony_ci u_char cmd = s->hw->cmd->feed; 1774141cc406Sopenharmony_ci 1775141cc406Sopenharmony_ci DBG (5, "feed()\n"); 1776141cc406Sopenharmony_ci 1777141cc406Sopenharmony_ci if (!cmd) 1778141cc406Sopenharmony_ci { 1779141cc406Sopenharmony_ci DBG (5, "feed() is not supported\n"); 1780141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1781141cc406Sopenharmony_ci } 1782141cc406Sopenharmony_ci 1783141cc406Sopenharmony_ci params[0] = cmd; 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci send (s, params, 1, &status); 1786141cc406Sopenharmony_ci 1787141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = expect_ack (s))) 1788141cc406Sopenharmony_ci { 1789141cc406Sopenharmony_ci close_scanner (s); 1790141cc406Sopenharmony_ci return status; 1791141cc406Sopenharmony_ci } 1792141cc406Sopenharmony_ci 1793141cc406Sopenharmony_ci return status; 1794141cc406Sopenharmony_ci} 1795141cc406Sopenharmony_ci 1796141cc406Sopenharmony_ci 1797141cc406Sopenharmony_ci/* 1798141cc406Sopenharmony_ci * eject() 1799141cc406Sopenharmony_ci * 1800141cc406Sopenharmony_ci * Eject the current page from the ADF. The scanner is opened prior to 1801141cc406Sopenharmony_ci * sending the command and closed afterwards. 1802141cc406Sopenharmony_ci * 1803141cc406Sopenharmony_ci */ 1804141cc406Sopenharmony_ci 1805141cc406Sopenharmony_cistatic SANE_Status 1806141cc406Sopenharmony_cieject (Epson_Scanner * s) 1807141cc406Sopenharmony_ci{ 1808141cc406Sopenharmony_ci SANE_Status status; 1809141cc406Sopenharmony_ci u_char params[2]; 1810141cc406Sopenharmony_ci u_char cmd = s->hw->cmd->eject; 1811141cc406Sopenharmony_ci SANE_Bool needToClose = SANE_FALSE; 1812141cc406Sopenharmony_ci 1813141cc406Sopenharmony_ci DBG (5, "eject()\n"); 1814141cc406Sopenharmony_ci 1815141cc406Sopenharmony_ci if (!cmd) 1816141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1817141cc406Sopenharmony_ci 1818141cc406Sopenharmony_ci if (s->fd == -1) 1819141cc406Sopenharmony_ci { 1820141cc406Sopenharmony_ci needToClose = SANE_TRUE; 1821141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = open_scanner (s))) 1822141cc406Sopenharmony_ci return status; 1823141cc406Sopenharmony_ci } 1824141cc406Sopenharmony_ci 1825141cc406Sopenharmony_ci params[0] = cmd; 1826141cc406Sopenharmony_ci 1827141cc406Sopenharmony_ci send (s, params, 1, &status); 1828141cc406Sopenharmony_ci 1829141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = expect_ack (s))) 1830141cc406Sopenharmony_ci { 1831141cc406Sopenharmony_ci close_scanner (s); 1832141cc406Sopenharmony_ci return status; 1833141cc406Sopenharmony_ci } 1834141cc406Sopenharmony_ci 1835141cc406Sopenharmony_ci if (needToClose) 1836141cc406Sopenharmony_ci close_scanner (s); 1837141cc406Sopenharmony_ci 1838141cc406Sopenharmony_ci return status; 1839141cc406Sopenharmony_ci} 1840141cc406Sopenharmony_ci 1841141cc406Sopenharmony_ci/* 1842141cc406Sopenharmony_ci * 1843141cc406Sopenharmony_ci * 1844141cc406Sopenharmony_ci */ 1845141cc406Sopenharmony_ci 1846141cc406Sopenharmony_cistatic int num_devices = 0; /* number of EPSON scanners attached to backend */ 1847141cc406Sopenharmony_cistatic Epson_Device *first_dev = NULL; /* first EPSON scanner in list */ 1848141cc406Sopenharmony_cistatic Epson_Scanner *first_handle = NULL; 1849141cc406Sopenharmony_ci 1850141cc406Sopenharmony_ci 1851141cc406Sopenharmony_cistatic EpsonHdrUnion 1852141cc406Sopenharmony_cicommand (Epson_Scanner * s, u_char * cmd, size_t cmd_size, 1853141cc406Sopenharmony_ci SANE_Status * status) 1854141cc406Sopenharmony_ci{ 1855141cc406Sopenharmony_ci EpsonHdrUnion hdrunion, hdrunion_bak; 1856141cc406Sopenharmony_ci EpsonHdr head; 1857141cc406Sopenharmony_ci u_char *buf; 1858141cc406Sopenharmony_ci int count; 1859141cc406Sopenharmony_ci 1860141cc406Sopenharmony_ci if (NULL == (hdrunion = walloc (EpsonHdrUnionRec))) 1861141cc406Sopenharmony_ci { 1862141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 1863141cc406Sopenharmony_ci *status = SANE_STATUS_NO_MEM; 1864141cc406Sopenharmony_ci return (EpsonHdrUnion) 0; 1865141cc406Sopenharmony_ci } 1866141cc406Sopenharmony_ci 1867141cc406Sopenharmony_ci head = &(hdrunion->hdr); 1868141cc406Sopenharmony_ci 1869141cc406Sopenharmony_ci send (s, cmd, cmd_size, status); 1870141cc406Sopenharmony_ci 1871141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != *status) 1872141cc406Sopenharmony_ci { 1873141cc406Sopenharmony_ci /* this is necessary for the GT-8000. I don't know why, but 1874141cc406Sopenharmony_ci it seems to fix the problem. It should not have any 1875141cc406Sopenharmony_ci ill effects on other scanners. */ 1876141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 1877141cc406Sopenharmony_ci send (s, cmd, cmd_size, status); 1878141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != *status) 1879141cc406Sopenharmony_ci return (EpsonHdrUnion) 0; 1880141cc406Sopenharmony_ci } 1881141cc406Sopenharmony_ci 1882141cc406Sopenharmony_ci buf = (u_char *) head; 1883141cc406Sopenharmony_ci 1884141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_SCSI) 1885141cc406Sopenharmony_ci { 1886141cc406Sopenharmony_ci receive (s, buf, 4, status); 1887141cc406Sopenharmony_ci buf += 4; 1888141cc406Sopenharmony_ci } 1889141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 1890141cc406Sopenharmony_ci { 1891141cc406Sopenharmony_ci int bytes_read; 1892141cc406Sopenharmony_ci bytes_read = receive (s, buf, 4, status); 1893141cc406Sopenharmony_ci buf += bytes_read; 1894141cc406Sopenharmony_ci } 1895141cc406Sopenharmony_ci else 1896141cc406Sopenharmony_ci { 1897141cc406Sopenharmony_ci receive (s, buf, 1, status); 1898141cc406Sopenharmony_ci buf += 1; 1899141cc406Sopenharmony_ci } 1900141cc406Sopenharmony_ci 1901141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != *status) 1902141cc406Sopenharmony_ci return (EpsonHdrUnion) 0; 1903141cc406Sopenharmony_ci 1904141cc406Sopenharmony_ci DBG (4, "code %02x\n", (int) head->code); 1905141cc406Sopenharmony_ci 1906141cc406Sopenharmony_ci switch (head->code) 1907141cc406Sopenharmony_ci { 1908141cc406Sopenharmony_ci 1909141cc406Sopenharmony_ci case NAK: 1910141cc406Sopenharmony_ci /* fall through */ 1911141cc406Sopenharmony_ci /* !!! is this really sufficient to report an error ? */ 1912141cc406Sopenharmony_ci case ACK: 1913141cc406Sopenharmony_ci break; /* no need to read any more data after ACK or NAK */ 1914141cc406Sopenharmony_ci 1915141cc406Sopenharmony_ci case STX: 1916141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_SCSI) 1917141cc406Sopenharmony_ci { 1918141cc406Sopenharmony_ci /* nope */ 1919141cc406Sopenharmony_ci } 1920141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 1921141cc406Sopenharmony_ci { 1922141cc406Sopenharmony_ci /* we've already read the complete data */ 1923141cc406Sopenharmony_ci } 1924141cc406Sopenharmony_ci else 1925141cc406Sopenharmony_ci { 1926141cc406Sopenharmony_ci receive (s, buf, 3, status); 1927141cc406Sopenharmony_ci /* buf += 3; */ 1928141cc406Sopenharmony_ci } 1929141cc406Sopenharmony_ci 1930141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != *status) 1931141cc406Sopenharmony_ci return (EpsonHdrUnion) 0; 1932141cc406Sopenharmony_ci 1933141cc406Sopenharmony_ci DBG (4, "status %02x\n", (int) head->status); 1934141cc406Sopenharmony_ci 1935141cc406Sopenharmony_ci count = head->count2 * 255 + head->count1; 1936141cc406Sopenharmony_ci DBG (4, "count %d\n", count); 1937141cc406Sopenharmony_ci 1938141cc406Sopenharmony_ci hdrunion_bak = hdrunion; 1939141cc406Sopenharmony_ci if (NULL == (hdrunion = realloc (hdrunion, 1940141cc406Sopenharmony_ci sizeof (EpsonHdrUnionRec) + count))) 1941141cc406Sopenharmony_ci { 1942141cc406Sopenharmony_ci free(hdrunion_bak); 1943141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 1944141cc406Sopenharmony_ci *status = SANE_STATUS_NO_MEM; 1945141cc406Sopenharmony_ci return (EpsonHdrUnion) 0; 1946141cc406Sopenharmony_ci } 1947141cc406Sopenharmony_ci 1948141cc406Sopenharmony_ci head = &(hdrunion->hdr); 1949141cc406Sopenharmony_ci 1950141cc406Sopenharmony_ci buf = head->buf; 1951141cc406Sopenharmony_ci receive (s, buf, count, status); 1952141cc406Sopenharmony_ci 1953141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != *status) 1954141cc406Sopenharmony_ci return (EpsonHdrUnion) 0; 1955141cc406Sopenharmony_ci 1956141cc406Sopenharmony_ci break; 1957141cc406Sopenharmony_ci 1958141cc406Sopenharmony_ci default: 1959141cc406Sopenharmony_ci if (0 == head->code) 1960141cc406Sopenharmony_ci DBG (1, "Incompatible printer port (probably bi/directional)\n"); 1961141cc406Sopenharmony_ci else if (cmd[cmd_size - 1] == head->code) 1962141cc406Sopenharmony_ci DBG (1, "Incompatible printer port (probably not bi/directional)\n"); 1963141cc406Sopenharmony_ci 1964141cc406Sopenharmony_ci DBG (2, "Illegal response of scanner for command: %02x\n", head->code); 1965141cc406Sopenharmony_ci break; 1966141cc406Sopenharmony_ci } 1967141cc406Sopenharmony_ci 1968141cc406Sopenharmony_ci return hdrunion; 1969141cc406Sopenharmony_ci} 1970141cc406Sopenharmony_ci 1971141cc406Sopenharmony_ci 1972141cc406Sopenharmony_ci/* 1973141cc406Sopenharmony_ci * static SANE_Status attach() 1974141cc406Sopenharmony_ci * 1975141cc406Sopenharmony_ci * Attach one device with name *dev_name to the backend. 1976141cc406Sopenharmony_ci */ 1977141cc406Sopenharmony_ci 1978141cc406Sopenharmony_cistatic SANE_Status 1979141cc406Sopenharmony_ciattach (const char *dev_name, Epson_Device * *devp, int type) 1980141cc406Sopenharmony_ci{ 1981141cc406Sopenharmony_ci SANE_Status status; 1982141cc406Sopenharmony_ci Epson_Scanner *s = walloca (Epson_Scanner); 1983141cc406Sopenharmony_ci char *str; 1984141cc406Sopenharmony_ci struct Epson_Device *dev; 1985141cc406Sopenharmony_ci SANE_String_Const *source_list_add = source_list; 1986141cc406Sopenharmony_ci int port; 1987141cc406Sopenharmony_ci 1988141cc406Sopenharmony_ci DBG (1, "%s\n", SANE_EPSON_VERSION); 1989141cc406Sopenharmony_ci 1990141cc406Sopenharmony_ci DBG (5, "attach(%s, %d)\n", dev_name, type); 1991141cc406Sopenharmony_ci 1992141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1993141cc406Sopenharmony_ci { 1994141cc406Sopenharmony_ci if (strcmp (dev->sane.name, dev_name) == 0) 1995141cc406Sopenharmony_ci { 1996141cc406Sopenharmony_ci if (devp) 1997141cc406Sopenharmony_ci { 1998141cc406Sopenharmony_ci *devp = dev; 1999141cc406Sopenharmony_ci } 2000141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2001141cc406Sopenharmony_ci } 2002141cc406Sopenharmony_ci } 2003141cc406Sopenharmony_ci 2004141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 2005141cc406Sopenharmony_ci if (!dev) 2006141cc406Sopenharmony_ci { 2007141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 2008141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2009141cc406Sopenharmony_ci } 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci /* check for PIO devices */ 2012141cc406Sopenharmony_ci /* can we convert the device name to an integer? This is only possible 2013141cc406Sopenharmony_ci with PIO devices */ 2014141cc406Sopenharmony_ci port = atoi (dev_name); 2015141cc406Sopenharmony_ci if (port != 0) 2016141cc406Sopenharmony_ci { 2017141cc406Sopenharmony_ci type = SANE_EPSON_PIO; 2018141cc406Sopenharmony_ci } 2019141cc406Sopenharmony_ci 2020141cc406Sopenharmony_ci if (strncmp 2021141cc406Sopenharmony_ci (dev_name, SANE_EPSON_CONFIG_PIO, strlen (SANE_EPSON_CONFIG_PIO)) == 0) 2022141cc406Sopenharmony_ci { 2023141cc406Sopenharmony_ci /* we have a match for the PIO string and adjust the device name */ 2024141cc406Sopenharmony_ci dev_name += strlen (SANE_EPSON_CONFIG_PIO); 2025141cc406Sopenharmony_ci dev_name = sanei_config_skip_whitespace (dev_name); 2026141cc406Sopenharmony_ci type = SANE_EPSON_PIO; 2027141cc406Sopenharmony_ci } 2028141cc406Sopenharmony_ci 2029141cc406Sopenharmony_ci 2030141cc406Sopenharmony_ci /* 2031141cc406Sopenharmony_ci * set dummy values. 2032141cc406Sopenharmony_ci */ 2033141cc406Sopenharmony_ci 2034141cc406Sopenharmony_ci s->hw = dev; 2035141cc406Sopenharmony_ci s->hw->sane.name = NULL; 2036141cc406Sopenharmony_ci s->hw->sane.type = "flatbed scanner"; 2037141cc406Sopenharmony_ci s->hw->sane.vendor = "Epson"; 2038141cc406Sopenharmony_ci s->hw->sane.model = NULL; 2039141cc406Sopenharmony_ci s->hw->optical_res = 0; /* just to have it initialized */ 2040141cc406Sopenharmony_ci s->hw->color_shuffle = SANE_FALSE; 2041141cc406Sopenharmony_ci s->hw->extension = SANE_FALSE; 2042141cc406Sopenharmony_ci s->hw->use_extension = SANE_FALSE; 2043141cc406Sopenharmony_ci 2044141cc406Sopenharmony_ci s->hw->need_color_reorder = SANE_FALSE; 2045141cc406Sopenharmony_ci s->hw->need_double_vertical = SANE_FALSE; 2046141cc406Sopenharmony_ci 2047141cc406Sopenharmony_ci s->hw->cmd = &epson_cmd[EPSON_LEVEL_DEFAULT]; /* default function level */ 2048141cc406Sopenharmony_ci s->hw->connection = type; 2049141cc406Sopenharmony_ci 2050141cc406Sopenharmony_ci DBG (3, "attach: opening %s\n", dev_name); 2051141cc406Sopenharmony_ci 2052141cc406Sopenharmony_ci s->hw->last_res = 0; 2053141cc406Sopenharmony_ci s->hw->last_res_preview = 0; /* set resolution to safe values */ 2054141cc406Sopenharmony_ci 2055141cc406Sopenharmony_ci /* 2056141cc406Sopenharmony_ci * decide if interface is USB, SCSI or parallel. 2057141cc406Sopenharmony_ci */ 2058141cc406Sopenharmony_ci 2059141cc406Sopenharmony_ci /* 2060141cc406Sopenharmony_ci * if interface is SCSI do an inquiry. 2061141cc406Sopenharmony_ci */ 2062141cc406Sopenharmony_ci 2063141cc406Sopenharmony_ci if (s->hw->connection == SANE_EPSON_SCSI) 2064141cc406Sopenharmony_ci { 2065141cc406Sopenharmony_ci u_char buf[INQUIRY_BUF_SIZE + 1]; 2066141cc406Sopenharmony_ci size_t buf_size = INQUIRY_BUF_SIZE; 2067141cc406Sopenharmony_ci 2068141cc406Sopenharmony_ci status = 2069141cc406Sopenharmony_ci sanei_scsi_open (dev_name, &s->fd, sanei_epson_scsi_sense_handler, 2070141cc406Sopenharmony_ci NULL); 2071141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 2072141cc406Sopenharmony_ci { 2073141cc406Sopenharmony_ci DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); 2074141cc406Sopenharmony_ci return status; 2075141cc406Sopenharmony_ci } 2076141cc406Sopenharmony_ci DBG (3, "attach: sending INQUIRY\n"); 2077141cc406Sopenharmony_ci 2078141cc406Sopenharmony_ci status = sanei_epson_scsi_inquiry (s->fd, 0, buf, &buf_size); 2079141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 2080141cc406Sopenharmony_ci { 2081141cc406Sopenharmony_ci DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); 2082141cc406Sopenharmony_ci close_scanner (s); 2083141cc406Sopenharmony_ci return status; 2084141cc406Sopenharmony_ci } 2085141cc406Sopenharmony_ci 2086141cc406Sopenharmony_ci buf[INQUIRY_BUF_SIZE] = 0; 2087141cc406Sopenharmony_ci DBG (1, ">%s<\n", buf + 8); 2088141cc406Sopenharmony_ci 2089141cc406Sopenharmony_ci /* 2090141cc406Sopenharmony_ci * For USB and PIO scanners this will be done later, once 2091141cc406Sopenharmony_ci * we have communication established with the device. 2092141cc406Sopenharmony_ci */ 2093141cc406Sopenharmony_ci 2094141cc406Sopenharmony_ci if (buf[0] != TYPE_PROCESSOR 2095141cc406Sopenharmony_ci || strncmp ((char *) (buf + 8), "EPSON", 5) != 0 2096141cc406Sopenharmony_ci || (strncmp ((char *) buf + 16, "SCANNER ", 8) != 0 2097141cc406Sopenharmony_ci && strncmp ((char *) buf + 14, "SCANNER ", 8) != 0 2098141cc406Sopenharmony_ci && strncmp ((char *) buf + 14, "Perfection", 10) != 0 2099141cc406Sopenharmony_ci && strncmp ((char *) buf + 16, "Perfection", 10) != 0 2100141cc406Sopenharmony_ci && strncmp ((char *) buf + 16, "Expression", 10) != 0 2101141cc406Sopenharmony_ci && strncmp ((char *) buf + 16, "GT", 2) != 0)) 2102141cc406Sopenharmony_ci { 2103141cc406Sopenharmony_ci DBG (1, "attach: device doesn't look like an EPSON scanner\n"); 2104141cc406Sopenharmony_ci close_scanner (s); 2105141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2106141cc406Sopenharmony_ci } 2107141cc406Sopenharmony_ci } 2108141cc406Sopenharmony_ci /* use the SANEI functions to handle a PIO device */ 2109141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_PIO) 2110141cc406Sopenharmony_ci { 2111141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = sanei_pio_open (dev_name, &s->fd))) 2112141cc406Sopenharmony_ci { 2113141cc406Sopenharmony_ci DBG (1, "Cannot open %s as a parallel-port device: %s\n", 2114141cc406Sopenharmony_ci dev_name, sane_strstatus (status)); 2115141cc406Sopenharmony_ci return status; 2116141cc406Sopenharmony_ci } 2117141cc406Sopenharmony_ci } 2118141cc406Sopenharmony_ci /* use the SANEI functions to handle a USB device */ 2119141cc406Sopenharmony_ci else if (s->hw->connection == SANE_EPSON_USB) 2120141cc406Sopenharmony_ci { 2121141cc406Sopenharmony_ci SANE_Word vendor; 2122141cc406Sopenharmony_ci SANE_Word product; 2123141cc406Sopenharmony_ci SANE_Bool isLibUSB; 2124141cc406Sopenharmony_ci 2125141cc406Sopenharmony_ci isLibUSB = (strncmp (dev_name, "libusb:", strlen ("libusb:")) == 0); 2126141cc406Sopenharmony_ci 2127141cc406Sopenharmony_ci if ((!isLibUSB) && (strlen (dev_name) == 0)) 2128141cc406Sopenharmony_ci { 2129141cc406Sopenharmony_ci int i; 2130141cc406Sopenharmony_ci int numIds; 2131141cc406Sopenharmony_ci 2132141cc406Sopenharmony_ci numIds = sanei_epson_getNumberOfUSBProductIds (); 2133141cc406Sopenharmony_ci 2134141cc406Sopenharmony_ci for (i = 0; i < numIds; i++) 2135141cc406Sopenharmony_ci { 2136141cc406Sopenharmony_ci product = sanei_epson_usb_product_ids[i]; 2137141cc406Sopenharmony_ci vendor = 0x4b8; 2138141cc406Sopenharmony_ci 2139141cc406Sopenharmony_ci status = sanei_usb_find_devices (vendor, product, attach_one_usb); 2140141cc406Sopenharmony_ci } 2141141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* return - the attach_one_usb() 2142141cc406Sopenharmony_ci will take care of this */ 2143141cc406Sopenharmony_ci } 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_ci status = sanei_usb_open (dev_name, &s->fd); 2146141cc406Sopenharmony_ci 2147141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 2148141cc406Sopenharmony_ci { 2149141cc406Sopenharmony_ci return status; 2150141cc406Sopenharmony_ci } 2151141cc406Sopenharmony_ci 2152141cc406Sopenharmony_ci /* if the sanei_usb_get_vendor_product call is not supported, 2153141cc406Sopenharmony_ci then we just ignore this and rely on the user to config 2154141cc406Sopenharmony_ci the correct device. 2155141cc406Sopenharmony_ci */ 2156141cc406Sopenharmony_ci 2157141cc406Sopenharmony_ci if (sanei_usb_get_vendor_product (s->fd, &vendor, &product) == 2158141cc406Sopenharmony_ci SANE_STATUS_GOOD) 2159141cc406Sopenharmony_ci { 2160141cc406Sopenharmony_ci int i; /* loop variable */ 2161141cc406Sopenharmony_ci int numIds; 2162141cc406Sopenharmony_ci SANE_Bool is_valid; 2163141cc406Sopenharmony_ci 2164141cc406Sopenharmony_ci /* check the vendor ID to see if we are dealing with an EPSON device */ 2165141cc406Sopenharmony_ci if (vendor != SANE_EPSON_VENDOR_ID) 2166141cc406Sopenharmony_ci { 2167141cc406Sopenharmony_ci /* this is not a supported vendor ID */ 2168141cc406Sopenharmony_ci DBG (1, 2169141cc406Sopenharmony_ci "The device at %s is not manufactured by EPSON (vendor id=0x%x)\n", 2170141cc406Sopenharmony_ci dev_name, vendor); 2171141cc406Sopenharmony_ci sanei_usb_close (s->fd); 2172141cc406Sopenharmony_ci s->fd = -1; 2173141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2174141cc406Sopenharmony_ci } 2175141cc406Sopenharmony_ci 2176141cc406Sopenharmony_ci numIds = sanei_epson_getNumberOfUSBProductIds (); 2177141cc406Sopenharmony_ci is_valid = SANE_FALSE; 2178141cc406Sopenharmony_ci i = 0; 2179141cc406Sopenharmony_ci 2180141cc406Sopenharmony_ci /* check all known product IDs to verify that we know 2181141cc406Sopenharmony_ci about the device */ 2182141cc406Sopenharmony_ci while (i != numIds && !is_valid) 2183141cc406Sopenharmony_ci { 2184141cc406Sopenharmony_ci if (product == sanei_epson_usb_product_ids[i]) 2185141cc406Sopenharmony_ci is_valid = SANE_TRUE; 2186141cc406Sopenharmony_ci 2187141cc406Sopenharmony_ci i++; 2188141cc406Sopenharmony_ci } 2189141cc406Sopenharmony_ci 2190141cc406Sopenharmony_ci if (is_valid == SANE_FALSE) 2191141cc406Sopenharmony_ci { 2192141cc406Sopenharmony_ci DBG (1, 2193141cc406Sopenharmony_ci "The device at %s is not a supported EPSON scanner (product id=0x%x)\n", 2194141cc406Sopenharmony_ci dev_name, product); 2195141cc406Sopenharmony_ci sanei_usb_close (s->fd); 2196141cc406Sopenharmony_ci s->fd = -1; 2197141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2198141cc406Sopenharmony_ci } 2199141cc406Sopenharmony_ci DBG (1, "Found valid EPSON scanner: 0x%x/0x%x (vendorID/productID)\n", 2200141cc406Sopenharmony_ci vendor, product); 2201141cc406Sopenharmony_ci } 2202141cc406Sopenharmony_ci else 2203141cc406Sopenharmony_ci { 2204141cc406Sopenharmony_ci DBG (1, 2205141cc406Sopenharmony_ci "Cannot use IOCTL interface to verify that device is a scanner - will continue\n"); 2206141cc406Sopenharmony_ci } 2207141cc406Sopenharmony_ci } 2208141cc406Sopenharmony_ci 2209141cc406Sopenharmony_ci /* 2210141cc406Sopenharmony_ci * Initialize the scanner (ESC @). 2211141cc406Sopenharmony_ci */ 2212141cc406Sopenharmony_ci reset (s); 2213141cc406Sopenharmony_ci 2214141cc406Sopenharmony_ci 2215141cc406Sopenharmony_ci 2216141cc406Sopenharmony_ci /* 2217141cc406Sopenharmony_ci * Identification Request (ESC I). 2218141cc406Sopenharmony_ci */ 2219141cc406Sopenharmony_ci if (s->hw->cmd->request_identity != 0) 2220141cc406Sopenharmony_ci { 2221141cc406Sopenharmony_ci status = get_identity_information (s); 2222141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2223141cc406Sopenharmony_ci return status; 2224141cc406Sopenharmony_ci } /* request identity */ 2225141cc406Sopenharmony_ci 2226141cc406Sopenharmony_ci 2227141cc406Sopenharmony_ci /* 2228141cc406Sopenharmony_ci * Check for "Request Identity 2" command. If this command is available 2229141cc406Sopenharmony_ci * get the information from the scanner and store it in dev 2230141cc406Sopenharmony_ci */ 2231141cc406Sopenharmony_ci 2232141cc406Sopenharmony_ci if (s->hw->cmd->request_identity2 != 0) 2233141cc406Sopenharmony_ci { 2234141cc406Sopenharmony_ci status = get_identity2_information (s); 2235141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2236141cc406Sopenharmony_ci return status; 2237141cc406Sopenharmony_ci } /* request identity 2 */ 2238141cc406Sopenharmony_ci 2239141cc406Sopenharmony_ci 2240141cc406Sopenharmony_ci /* 2241141cc406Sopenharmony_ci * Check for the max. supported color depth and assign 2242141cc406Sopenharmony_ci * the values to the bitDepthList. 2243141cc406Sopenharmony_ci */ 2244141cc406Sopenharmony_ci 2245141cc406Sopenharmony_ci bitDepthList = malloc (sizeof (SANE_Word) * 4); 2246141cc406Sopenharmony_ci if (bitDepthList == NULL) 2247141cc406Sopenharmony_ci { 2248141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 2249141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2250141cc406Sopenharmony_ci } 2251141cc406Sopenharmony_ci 2252141cc406Sopenharmony_ci bitDepthList[0] = 1; /* we start with one element in the list */ 2253141cc406Sopenharmony_ci bitDepthList[1] = 8; /* 8bit is the default */ 2254141cc406Sopenharmony_ci 2255141cc406Sopenharmony_ci if (set_data_format (s, 16) == SANE_STATUS_GOOD) 2256141cc406Sopenharmony_ci { 2257141cc406Sopenharmony_ci s->hw->maxDepth = 16; 2258141cc406Sopenharmony_ci 2259141cc406Sopenharmony_ci bitDepthList[0]++; 2260141cc406Sopenharmony_ci bitDepthList[bitDepthList[0]] = 16; 2261141cc406Sopenharmony_ci 2262141cc406Sopenharmony_ci } 2263141cc406Sopenharmony_ci else if (set_data_format (s, 14) == SANE_STATUS_GOOD) 2264141cc406Sopenharmony_ci { 2265141cc406Sopenharmony_ci s->hw->maxDepth = 14; 2266141cc406Sopenharmony_ci 2267141cc406Sopenharmony_ci bitDepthList[0]++; 2268141cc406Sopenharmony_ci bitDepthList[bitDepthList[0]] = 14; 2269141cc406Sopenharmony_ci } 2270141cc406Sopenharmony_ci else if (set_data_format (s, 12) == SANE_STATUS_GOOD) 2271141cc406Sopenharmony_ci { 2272141cc406Sopenharmony_ci s->hw->maxDepth = 12; 2273141cc406Sopenharmony_ci 2274141cc406Sopenharmony_ci bitDepthList[0]++; 2275141cc406Sopenharmony_ci bitDepthList[bitDepthList[0]] = 12; 2276141cc406Sopenharmony_ci } 2277141cc406Sopenharmony_ci else 2278141cc406Sopenharmony_ci { 2279141cc406Sopenharmony_ci s->hw->maxDepth = 8; 2280141cc406Sopenharmony_ci 2281141cc406Sopenharmony_ci /* the default depth is already in the list */ 2282141cc406Sopenharmony_ci } 2283141cc406Sopenharmony_ci 2284141cc406Sopenharmony_ci DBG (1, "Max. supported color depth = %d\n", s->hw->maxDepth); 2285141cc406Sopenharmony_ci 2286141cc406Sopenharmony_ci 2287141cc406Sopenharmony_ci /* 2288141cc406Sopenharmony_ci * Check for "request focus position" command. If this command is 2289141cc406Sopenharmony_ci * supported, then the scanner does also support the "set focus 2290141cc406Sopenharmony_ci * position" command. 2291141cc406Sopenharmony_ci */ 2292141cc406Sopenharmony_ci 2293141cc406Sopenharmony_ci if (request_focus_position (s, &s->currentFocusPosition) == 2294141cc406Sopenharmony_ci SANE_STATUS_GOOD) 2295141cc406Sopenharmony_ci { 2296141cc406Sopenharmony_ci DBG (1, "Enabling 'Set Focus' support\n"); 2297141cc406Sopenharmony_ci s->hw->focusSupport = SANE_TRUE; 2298141cc406Sopenharmony_ci s->opt[OPT_FOCUS].cap &= ~SANE_CAP_INACTIVE; 2299141cc406Sopenharmony_ci 2300141cc406Sopenharmony_ci /* reflect the current focus position in the GUI */ 2301141cc406Sopenharmony_ci if (s->currentFocusPosition < 0x4C) 2302141cc406Sopenharmony_ci { 2303141cc406Sopenharmony_ci /* focus on glass */ 2304141cc406Sopenharmony_ci s->val[OPT_FOCUS].w = 0; 2305141cc406Sopenharmony_ci } 2306141cc406Sopenharmony_ci else 2307141cc406Sopenharmony_ci { 2308141cc406Sopenharmony_ci /* focus 2.5mm above glass */ 2309141cc406Sopenharmony_ci s->val[OPT_FOCUS].w = 1; 2310141cc406Sopenharmony_ci } 2311141cc406Sopenharmony_ci 2312141cc406Sopenharmony_ci } 2313141cc406Sopenharmony_ci else 2314141cc406Sopenharmony_ci { 2315141cc406Sopenharmony_ci DBG (1, "Disabling 'Set Focus' support\n"); 2316141cc406Sopenharmony_ci s->hw->focusSupport = SANE_FALSE; 2317141cc406Sopenharmony_ci s->opt[OPT_FOCUS].cap |= SANE_CAP_INACTIVE; 2318141cc406Sopenharmony_ci s->val[OPT_FOCUS].w = 0; /* on glass - just in case */ 2319141cc406Sopenharmony_ci } 2320141cc406Sopenharmony_ci 2321141cc406Sopenharmony_ci 2322141cc406Sopenharmony_ci 2323141cc406Sopenharmony_ci/* 2324141cc406Sopenharmony_ci * Set defaults for no extension. 2325141cc406Sopenharmony_ci */ 2326141cc406Sopenharmony_ci 2327141cc406Sopenharmony_ci dev->x_range = &dev->fbf_x_range; 2328141cc406Sopenharmony_ci dev->y_range = &dev->fbf_y_range; 2329141cc406Sopenharmony_ci 2330141cc406Sopenharmony_ci/* 2331141cc406Sopenharmony_ci * Correct for a firmware bug in some Perfection 1650 scanners: 2332141cc406Sopenharmony_ci * Firmware version 1.08 reports only half the vertical scan area, we have 2333141cc406Sopenharmony_ci * to double the number. To find out if we have to do this, we just compare 2334141cc406Sopenharmony_ci * is the vertical range is smaller than the horizontal range. 2335141cc406Sopenharmony_ci */ 2336141cc406Sopenharmony_ci 2337141cc406Sopenharmony_ci if ((dev->x_range->max - dev->x_range->min) > 2338141cc406Sopenharmony_ci (dev->y_range->max - dev->y_range->min)) 2339141cc406Sopenharmony_ci { 2340141cc406Sopenharmony_ci dev->y_range->max += (dev->y_range->max - dev->y_range->min); 2341141cc406Sopenharmony_ci dev->need_double_vertical = SANE_TRUE; 2342141cc406Sopenharmony_ci dev->need_color_reorder = SANE_TRUE; 2343141cc406Sopenharmony_ci } 2344141cc406Sopenharmony_ci 2345141cc406Sopenharmony_ci 2346141cc406Sopenharmony_ci/* 2347141cc406Sopenharmony_ci * Extended status flag request (ESC f). 2348141cc406Sopenharmony_ci * this also requests the scanner device name from the scanner 2349141cc406Sopenharmony_ci */ 2350141cc406Sopenharmony_ci /* 2351141cc406Sopenharmony_ci * because we are also using the device name from this command, 2352141cc406Sopenharmony_ci * we have to run this block even if the scanner does not report 2353141cc406Sopenharmony_ci * an extension. The extensions are only reported if the ADF or 2354141cc406Sopenharmony_ci * the TPU are actually detected. 2355141cc406Sopenharmony_ci */ 2356141cc406Sopenharmony_ci if (s->hw->cmd->request_extended_status != 0) 2357141cc406Sopenharmony_ci { 2358141cc406Sopenharmony_ci u_char *buf; 2359141cc406Sopenharmony_ci u_char params[2]; 2360141cc406Sopenharmony_ci EpsonHdr head; 2361141cc406Sopenharmony_ci 2362141cc406Sopenharmony_ci params[0] = ESC; 2363141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_extended_status; 2364141cc406Sopenharmony_ci 2365141cc406Sopenharmony_ci if (NULL == (head = (EpsonHdr) command (s, params, 2, &status))) 2366141cc406Sopenharmony_ci { 2367141cc406Sopenharmony_ci DBG (1, "Extended status flag request failed\n"); 2368141cc406Sopenharmony_ci dev->sane.model = strdup ("Unknown model"); 2369141cc406Sopenharmony_ci *source_list_add++ = FBF_STR; 2370141cc406Sopenharmony_ci } 2371141cc406Sopenharmony_ci else 2372141cc406Sopenharmony_ci { 2373141cc406Sopenharmony_ci buf = &head->buf[0]; 2374141cc406Sopenharmony_ci 2375141cc406Sopenharmony_ci/* 2376141cc406Sopenharmony_ci * Add the flatbed option to the source list 2377141cc406Sopenharmony_ci */ 2378141cc406Sopenharmony_ci 2379141cc406Sopenharmony_ci *source_list_add++ = FBF_STR; 2380141cc406Sopenharmony_ci 2381141cc406Sopenharmony_ci s->hw->devtype = buf[11] >> 6; 2382141cc406Sopenharmony_ci 2383141cc406Sopenharmony_ci/* 2384141cc406Sopenharmony_ci * Get the device name and copy it to dev->sane.model. 2385141cc406Sopenharmony_ci * The device name starts at buf[0x1A] and is up to 16 bytes long 2386141cc406Sopenharmony_ci * We are overwriting whatever was set previously! 2387141cc406Sopenharmony_ci */ 2388141cc406Sopenharmony_ci { 2389141cc406Sopenharmony_ci char device_name[DEVICE_NAME_LEN + 1]; 2390141cc406Sopenharmony_ci char *end_ptr; 2391141cc406Sopenharmony_ci int len; 2392141cc406Sopenharmony_ci 2393141cc406Sopenharmony_ci /* make sure that the end of string is marked */ 2394141cc406Sopenharmony_ci device_name[DEVICE_NAME_LEN] = '\0'; 2395141cc406Sopenharmony_ci 2396141cc406Sopenharmony_ci /* copy the string to an area where we can work with it */ 2397141cc406Sopenharmony_ci memcpy (device_name, buf + 0x1A, DEVICE_NAME_LEN); 2398141cc406Sopenharmony_ci end_ptr = strchr (device_name, ' '); 2399141cc406Sopenharmony_ci if (end_ptr != NULL) 2400141cc406Sopenharmony_ci { 2401141cc406Sopenharmony_ci *end_ptr = '\0'; 2402141cc406Sopenharmony_ci } 2403141cc406Sopenharmony_ci 2404141cc406Sopenharmony_ci len = strlen (device_name); 2405141cc406Sopenharmony_ci 2406141cc406Sopenharmony_ci str = malloc (len + 1); 2407141cc406Sopenharmony_ci str[len] = '\0'; 2408141cc406Sopenharmony_ci 2409141cc406Sopenharmony_ci dev->sane.model = (char *) memcpy (str, device_name, len); 2410141cc406Sopenharmony_ci } 2411141cc406Sopenharmony_ci/* 2412141cc406Sopenharmony_ci * ADF 2413141cc406Sopenharmony_ci */ 2414141cc406Sopenharmony_ci 2415141cc406Sopenharmony_ci if (dev->extension && (buf[1] & EXT_STATUS_IST)) 2416141cc406Sopenharmony_ci { 2417141cc406Sopenharmony_ci DBG (1, "ADF detected\n"); 2418141cc406Sopenharmony_ci 2419141cc406Sopenharmony_ci /* the GT-30000 does not report the ADF scan area */ 2420141cc406Sopenharmony_ci if ((strcmp (dev->sane.model, "GT-30000") == 0) || 2421141cc406Sopenharmony_ci (strcmp (dev->sane.model, "ES-9000H") == 0)) 2422141cc406Sopenharmony_ci { 2423141cc406Sopenharmony_ci fix_up_extended_status_reply ((const char *) buf + 26, buf); 2424141cc406Sopenharmony_ci 2425141cc406Sopenharmony_ci dev->duplexSupport = (buf[0] & 0x10) != 0; 2426141cc406Sopenharmony_ci if (dev->duplexSupport) 2427141cc406Sopenharmony_ci { 2428141cc406Sopenharmony_ci DBG (1, "Found DUPLEX ADF\n"); 2429141cc406Sopenharmony_ci } 2430141cc406Sopenharmony_ci 2431141cc406Sopenharmony_ci 2432141cc406Sopenharmony_ci 2433141cc406Sopenharmony_ci 2434141cc406Sopenharmony_ci } 2435141cc406Sopenharmony_ci 2436141cc406Sopenharmony_ci if (buf[1] & EXT_STATUS_EN) 2437141cc406Sopenharmony_ci { 2438141cc406Sopenharmony_ci DBG (1, "ADF is enabled\n"); 2439141cc406Sopenharmony_ci dev->x_range = &dev->adf_x_range; 2440141cc406Sopenharmony_ci dev->y_range = &dev->adf_y_range; 2441141cc406Sopenharmony_ci } 2442141cc406Sopenharmony_ci 2443141cc406Sopenharmony_ci dev->adf_x_range.min = 0; 2444141cc406Sopenharmony_ci dev->adf_x_range.max = 2445141cc406Sopenharmony_ci SANE_FIX ((buf[3] << 8 | buf[2]) * 25.4 / dev->dpi_range.max); 2446141cc406Sopenharmony_ci dev->adf_x_range.quant = 0; 2447141cc406Sopenharmony_ci 2448141cc406Sopenharmony_ci dev->adf_max_x = buf[3] << 8 | buf[2]; 2449141cc406Sopenharmony_ci 2450141cc406Sopenharmony_ci dev->adf_y_range.min = 0; 2451141cc406Sopenharmony_ci dev->adf_y_range.max = 2452141cc406Sopenharmony_ci SANE_FIX ((buf[5] << 8 | buf[4]) * 25.4 / dev->dpi_range.max); 2453141cc406Sopenharmony_ci dev->adf_y_range.quant = 0; 2454141cc406Sopenharmony_ci 2455141cc406Sopenharmony_ci dev->adf_max_y = buf[5] << 8 | buf[4]; 2456141cc406Sopenharmony_ci 2457141cc406Sopenharmony_ci DBG (5, "adf tlx %f tly %f brx %f bry %f [mm]\n", 2458141cc406Sopenharmony_ci SANE_UNFIX (dev->adf_x_range.min), 2459141cc406Sopenharmony_ci SANE_UNFIX (dev->adf_y_range.min), 2460141cc406Sopenharmony_ci SANE_UNFIX (dev->adf_x_range.max), 2461141cc406Sopenharmony_ci SANE_UNFIX (dev->adf_y_range.max)); 2462141cc406Sopenharmony_ci 2463141cc406Sopenharmony_ci *source_list_add++ = ADF_STR; 2464141cc406Sopenharmony_ci 2465141cc406Sopenharmony_ci dev->ADF = SANE_TRUE; 2466141cc406Sopenharmony_ci } 2467141cc406Sopenharmony_ci 2468141cc406Sopenharmony_ci 2469141cc406Sopenharmony_ci/* 2470141cc406Sopenharmony_ci * TPU 2471141cc406Sopenharmony_ci */ 2472141cc406Sopenharmony_ci 2473141cc406Sopenharmony_ci if (dev->extension && (buf[6] & EXT_STATUS_IST)) 2474141cc406Sopenharmony_ci { 2475141cc406Sopenharmony_ci DBG (1, "TPU detected\n"); 2476141cc406Sopenharmony_ci 2477141cc406Sopenharmony_ci if (buf[6] & EXT_STATUS_EN) 2478141cc406Sopenharmony_ci { 2479141cc406Sopenharmony_ci DBG (1, "TPU is enabled\n"); 2480141cc406Sopenharmony_ci dev->x_range = &dev->tpu_x_range; 2481141cc406Sopenharmony_ci dev->y_range = &dev->tpu_y_range; 2482141cc406Sopenharmony_ci } 2483141cc406Sopenharmony_ci 2484141cc406Sopenharmony_ci dev->tpu_x_range.min = 0; 2485141cc406Sopenharmony_ci dev->tpu_x_range.max = 2486141cc406Sopenharmony_ci SANE_FIX ((buf[8] << 8 | buf[7]) * 25.4 / dev->dpi_range.max); 2487141cc406Sopenharmony_ci dev->tpu_x_range.quant = 0; 2488141cc406Sopenharmony_ci 2489141cc406Sopenharmony_ci dev->tpu_y_range.min = 0; 2490141cc406Sopenharmony_ci dev->tpu_y_range.max = 2491141cc406Sopenharmony_ci SANE_FIX ((buf[10] << 8 | buf[9]) * 25.4 / dev->dpi_range.max); 2492141cc406Sopenharmony_ci dev->tpu_y_range.quant = 0; 2493141cc406Sopenharmony_ci 2494141cc406Sopenharmony_ci /* 2495141cc406Sopenharmony_ci * Check for Perfection 4990 photo/GT-X800 scanner. 2496141cc406Sopenharmony_ci * This scanner only report 3200 dpi back. 2497141cc406Sopenharmony_ci * The scanner physically supports 4800 dpi. 2498141cc406Sopenharmony_ci * This is simulated here... 2499141cc406Sopenharmony_ci * Further details read: 2500141cc406Sopenharmony_ci * EPSON Programming guide for EPSON Color Image Scanner Perfection 4990 2501141cc406Sopenharmony_ci */ 2502141cc406Sopenharmony_ci if (strncmp((char *) buf + 0x1A,"GT-X800",7) == 0) 2503141cc406Sopenharmony_ci { 2504141cc406Sopenharmony_ci dev->tpu_x_range.max = (dev->tpu_x_range.max/32)*48; 2505141cc406Sopenharmony_ci dev->tpu_y_range.max = (dev->tpu_y_range.max/32)*48; 2506141cc406Sopenharmony_ci DBG (5, "dpi_range.max %x \n", dev->dpi_range.max); 2507141cc406Sopenharmony_ci } 2508141cc406Sopenharmony_ci 2509141cc406Sopenharmony_ci DBG (5, "tpu tlx %f tly %f brx %f bry %f [mm]\n", 2510141cc406Sopenharmony_ci SANE_UNFIX (dev->tpu_x_range.min), 2511141cc406Sopenharmony_ci SANE_UNFIX (dev->tpu_y_range.min), 2512141cc406Sopenharmony_ci SANE_UNFIX (dev->tpu_x_range.max), 2513141cc406Sopenharmony_ci SANE_UNFIX (dev->tpu_y_range.max)); 2514141cc406Sopenharmony_ci 2515141cc406Sopenharmony_ci *source_list_add++ = TPU_STR; 2516141cc406Sopenharmony_ci 2517141cc406Sopenharmony_ci dev->TPU = SANE_TRUE; 2518141cc406Sopenharmony_ci } 2519141cc406Sopenharmony_ci 2520141cc406Sopenharmony_ci/* 2521141cc406Sopenharmony_ci * Get the device name and copy it to dev->sane.model. 2522141cc406Sopenharmony_ci * The device name starts at buf[0x1A] and is up to 16 bytes long 2523141cc406Sopenharmony_ci * We are overwriting whatever was set previously! 2524141cc406Sopenharmony_ci */ 2525141cc406Sopenharmony_ci { 2526141cc406Sopenharmony_ci char device_name[DEVICE_NAME_LEN + 1]; 2527141cc406Sopenharmony_ci char *end_ptr; 2528141cc406Sopenharmony_ci int len; 2529141cc406Sopenharmony_ci 2530141cc406Sopenharmony_ci /* make sure that the end of string is marked */ 2531141cc406Sopenharmony_ci device_name[DEVICE_NAME_LEN] = '\0'; 2532141cc406Sopenharmony_ci 2533141cc406Sopenharmony_ci /* copy the string to an area where we can work with it */ 2534141cc406Sopenharmony_ci memcpy (device_name, buf + 0x1A, DEVICE_NAME_LEN); 2535141cc406Sopenharmony_ci end_ptr = strchr (device_name, ' '); 2536141cc406Sopenharmony_ci if (end_ptr != NULL) 2537141cc406Sopenharmony_ci { 2538141cc406Sopenharmony_ci *end_ptr = '\0'; 2539141cc406Sopenharmony_ci } 2540141cc406Sopenharmony_ci 2541141cc406Sopenharmony_ci len = strlen (device_name); 2542141cc406Sopenharmony_ci 2543141cc406Sopenharmony_ci str = malloc (len + 1); 2544141cc406Sopenharmony_ci str[len] = '\0'; 2545141cc406Sopenharmony_ci 2546141cc406Sopenharmony_ci /* finally copy the device name to the structure */ 2547141cc406Sopenharmony_ci dev->sane.model = (char *) memcpy (str, device_name, len); 2548141cc406Sopenharmony_ci } 2549141cc406Sopenharmony_ci } 2550141cc406Sopenharmony_ci } 2551141cc406Sopenharmony_ci else /* command is not known */ 2552141cc406Sopenharmony_ci { 2553141cc406Sopenharmony_ci dev->sane.model = strdup ("EPSON Scanner"); 2554141cc406Sopenharmony_ci } 2555141cc406Sopenharmony_ci 2556141cc406Sopenharmony_ci *source_list_add = NULL; /* add end marker to source list */ 2557141cc406Sopenharmony_ci 2558141cc406Sopenharmony_ci DBG (1, "scanner model: %s\n", dev->sane.model); 2559141cc406Sopenharmony_ci 2560141cc406Sopenharmony_ci /* establish defaults */ 2561141cc406Sopenharmony_ci s->hw->need_reset_on_source_change = SANE_FALSE; 2562141cc406Sopenharmony_ci 2563141cc406Sopenharmony_ci if (strcmp ("ES-9000H", dev->sane.model) == 0 || 2564141cc406Sopenharmony_ci strcmp ("GT-30000", dev->sane.model) == 0) 2565141cc406Sopenharmony_ci { 2566141cc406Sopenharmony_ci s->hw->cmd->set_focus_position = 0; 2567141cc406Sopenharmony_ci s->hw->cmd->feed = 0x19; 2568141cc406Sopenharmony_ci } 2569141cc406Sopenharmony_ci else if (strcmp ("GT-8200", dev->sane.model) == 0 || 2570141cc406Sopenharmony_ci strcmp ("Perfection1650", dev->sane.model) == 0 || 2571141cc406Sopenharmony_ci strcmp ("Perfection1640", dev->sane.model) == 0 || 2572141cc406Sopenharmony_ci strcmp ("GT-8700", dev->sane.model) == 0) 2573141cc406Sopenharmony_ci { 2574141cc406Sopenharmony_ci s->hw->cmd->feed = 0; 2575141cc406Sopenharmony_ci s->hw->cmd->set_focus_position = 0; 2576141cc406Sopenharmony_ci s->hw->need_reset_on_source_change = SANE_TRUE; 2577141cc406Sopenharmony_ci } 2578141cc406Sopenharmony_ci 2579141cc406Sopenharmony_ci 2580141cc406Sopenharmony_ci/* 2581141cc406Sopenharmony_ci * Set values for quick format "max" entry. 2582141cc406Sopenharmony_ci */ 2583141cc406Sopenharmony_ci 2584141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].tl_x = dev->x_range->min; 2585141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].tl_y = dev->y_range->min; 2586141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].br_x = dev->x_range->max; 2587141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].br_y = dev->y_range->max; 2588141cc406Sopenharmony_ci 2589141cc406Sopenharmony_ci 2590141cc406Sopenharmony_ci/* 2591141cc406Sopenharmony_ci * Now we can finally set the device name: 2592141cc406Sopenharmony_ci */ 2593141cc406Sopenharmony_ci str = malloc (strlen (dev_name) + 1); 2594141cc406Sopenharmony_ci dev->sane.name = strcpy (str, dev_name); 2595141cc406Sopenharmony_ci 2596141cc406Sopenharmony_ci close_scanner (s); 2597141cc406Sopenharmony_ci 2598141cc406Sopenharmony_ci /* 2599141cc406Sopenharmony_ci * we are done with this one, prepare for the next scanner: 2600141cc406Sopenharmony_ci */ 2601141cc406Sopenharmony_ci 2602141cc406Sopenharmony_ci ++num_devices; 2603141cc406Sopenharmony_ci dev->next = first_dev; 2604141cc406Sopenharmony_ci first_dev = dev; 2605141cc406Sopenharmony_ci 2606141cc406Sopenharmony_ci if (devp) 2607141cc406Sopenharmony_ci { 2608141cc406Sopenharmony_ci *devp = dev; 2609141cc406Sopenharmony_ci } 2610141cc406Sopenharmony_ci 2611141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2612141cc406Sopenharmony_ci} 2613141cc406Sopenharmony_ci 2614141cc406Sopenharmony_ci 2615141cc406Sopenharmony_ci 2616141cc406Sopenharmony_ci/* 2617141cc406Sopenharmony_ci * attach_one() 2618141cc406Sopenharmony_ci * 2619141cc406Sopenharmony_ci * Part of the SANE API: Attaches the scanner with the device name in *dev. 2620141cc406Sopenharmony_ci */ 2621141cc406Sopenharmony_ci 2622141cc406Sopenharmony_cistatic SANE_Status 2623141cc406Sopenharmony_ciattach_one (const char *dev) 2624141cc406Sopenharmony_ci{ 2625141cc406Sopenharmony_ci DBG (5, "attach_one(%s)\n", dev); 2626141cc406Sopenharmony_ci 2627141cc406Sopenharmony_ci return attach (dev, 0, SANE_EPSON_SCSI); 2628141cc406Sopenharmony_ci} 2629141cc406Sopenharmony_ci 2630141cc406Sopenharmony_ciSANE_Status 2631141cc406Sopenharmony_ciattach_one_usb (SANE_String_Const devname) 2632141cc406Sopenharmony_ci{ 2633141cc406Sopenharmony_ci int len = strlen (devname); 2634141cc406Sopenharmony_ci char *attach_string; 2635141cc406Sopenharmony_ci 2636141cc406Sopenharmony_ci DBG (5, "attach_one_usb(%s)\n", devname); 2637141cc406Sopenharmony_ci 2638141cc406Sopenharmony_ci attach_string = alloca (len + 5); 2639141cc406Sopenharmony_ci if (attach_string == NULL) 2640141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2641141cc406Sopenharmony_ci 2642141cc406Sopenharmony_ci return attach (devname, 0, SANE_EPSON_USB); 2643141cc406Sopenharmony_ci} 2644141cc406Sopenharmony_ci 2645141cc406Sopenharmony_ci/* 2646141cc406Sopenharmony_ci * sane_init() 2647141cc406Sopenharmony_ci * 2648141cc406Sopenharmony_ci * 2649141cc406Sopenharmony_ci */ 2650141cc406Sopenharmony_ciSANE_Status 2651141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 2652141cc406Sopenharmony_ci{ 2653141cc406Sopenharmony_ci size_t len; 2654141cc406Sopenharmony_ci FILE *fp; 2655141cc406Sopenharmony_ci 2656141cc406Sopenharmony_ci (void) authorize; /* get rid of compiler warning */ 2657141cc406Sopenharmony_ci 2658141cc406Sopenharmony_ci /* sanei_authorization(devicename, STRINGIFY(BACKEND_NAME), auth_callback); */ 2659141cc406Sopenharmony_ci 2660141cc406Sopenharmony_ci DBG_INIT (); 2661141cc406Sopenharmony_ci#if defined PACKAGE && defined VERSION 2662141cc406Sopenharmony_ci DBG (2, "sane_init: " PACKAGE " " VERSION "\n"); 2663141cc406Sopenharmony_ci#endif 2664141cc406Sopenharmony_ci 2665141cc406Sopenharmony_ci if (version_code != NULL) 2666141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, SANE_EPSON_BUILD); 2667141cc406Sopenharmony_ci 2668141cc406Sopenharmony_ci sanei_usb_init (); 2669141cc406Sopenharmony_ci 2670141cc406Sopenharmony_ci /* default to /dev/scanner instead of insisting on config file */ 2671141cc406Sopenharmony_ci if ((fp = sanei_config_open (EPSON_CONFIG_FILE))) 2672141cc406Sopenharmony_ci { 2673141cc406Sopenharmony_ci char line[PATH_MAX]; 2674141cc406Sopenharmony_ci 2675141cc406Sopenharmony_ci while (sanei_config_read (line, sizeof (line), fp)) 2676141cc406Sopenharmony_ci { 2677141cc406Sopenharmony_ci int vendor, product; 2678141cc406Sopenharmony_ci 2679141cc406Sopenharmony_ci DBG (4, "sane_init, >%s<\n", line); 2680141cc406Sopenharmony_ci if (line[0] == '#') /* ignore line comments */ 2681141cc406Sopenharmony_ci continue; 2682141cc406Sopenharmony_ci len = strlen (line); 2683141cc406Sopenharmony_ci if (!len) 2684141cc406Sopenharmony_ci continue; /* ignore empty lines */ 2685141cc406Sopenharmony_ci 2686141cc406Sopenharmony_ci if (sscanf (line, "usb %i %i", &vendor, &product) == 2) 2687141cc406Sopenharmony_ci { 2688141cc406Sopenharmony_ci int numIds; 2689141cc406Sopenharmony_ci 2690141cc406Sopenharmony_ci /* add the vendor and product IDs to the list of 2691141cc406Sopenharmony_ci known devices before we call the attach function */ 2692141cc406Sopenharmony_ci numIds = sanei_epson_getNumberOfUSBProductIds (); 2693141cc406Sopenharmony_ci if (vendor != 0x4b8) 2694141cc406Sopenharmony_ci continue; /* this is not an EPSON device */ 2695141cc406Sopenharmony_ci 2696141cc406Sopenharmony_ci sanei_epson_usb_product_ids[numIds - 1] = product; 2697141cc406Sopenharmony_ci sanei_usb_attach_matching_devices (line, attach_one_usb); 2698141cc406Sopenharmony_ci } 2699141cc406Sopenharmony_ci else if (strncmp (line, "usb", 3) == 0) 2700141cc406Sopenharmony_ci { 2701141cc406Sopenharmony_ci const char *dev_name; 2702141cc406Sopenharmony_ci /* remove the "usb" sub string */ 2703141cc406Sopenharmony_ci dev_name = sanei_config_skip_whitespace (line + 3); 2704141cc406Sopenharmony_ci attach_one_usb (dev_name); 2705141cc406Sopenharmony_ci } 2706141cc406Sopenharmony_ci else 2707141cc406Sopenharmony_ci { 2708141cc406Sopenharmony_ci sanei_config_attach_matching_devices (line, attach_one); 2709141cc406Sopenharmony_ci } 2710141cc406Sopenharmony_ci } 2711141cc406Sopenharmony_ci fclose (fp); 2712141cc406Sopenharmony_ci } 2713141cc406Sopenharmony_ci 2714141cc406Sopenharmony_ci /* read the option section and assign the connection type to the 2715141cc406Sopenharmony_ci scanner structure - which we don't have at this time. So I have 2716141cc406Sopenharmony_ci to come up with something :-) */ 2717141cc406Sopenharmony_ci 2718141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2719141cc406Sopenharmony_ci} 2720141cc406Sopenharmony_ci 2721141cc406Sopenharmony_ci/* 2722141cc406Sopenharmony_ci * void sane_exit(void) 2723141cc406Sopenharmony_ci * 2724141cc406Sopenharmony_ci * Clean up the list of attached scanners. 2725141cc406Sopenharmony_ci */ 2726141cc406Sopenharmony_ci 2727141cc406Sopenharmony_civoid 2728141cc406Sopenharmony_cisane_exit (void) 2729141cc406Sopenharmony_ci{ 2730141cc406Sopenharmony_ci Epson_Device *dev, *next; 2731141cc406Sopenharmony_ci 2732141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 2733141cc406Sopenharmony_ci { 2734141cc406Sopenharmony_ci next = dev->next; 2735141cc406Sopenharmony_ci free ((void *) dev->sane.name); 2736141cc406Sopenharmony_ci free ((void *) dev->sane.model); 2737141cc406Sopenharmony_ci free (dev); 2738141cc406Sopenharmony_ci } 2739141cc406Sopenharmony_ci 2740141cc406Sopenharmony_ci free (devlist); 2741141cc406Sopenharmony_ci} 2742141cc406Sopenharmony_ci 2743141cc406Sopenharmony_ci/* 2744141cc406Sopenharmony_ci * 2745141cc406Sopenharmony_ci * 2746141cc406Sopenharmony_ci */ 2747141cc406Sopenharmony_ci 2748141cc406Sopenharmony_ciSANE_Status 2749141cc406Sopenharmony_cisane_get_devices (const SANE_Device * **device_list, SANE_Bool local_only) 2750141cc406Sopenharmony_ci{ 2751141cc406Sopenharmony_ci Epson_Device *dev; 2752141cc406Sopenharmony_ci int i; 2753141cc406Sopenharmony_ci 2754141cc406Sopenharmony_ci DBG (5, "sane_get_devices()\n"); 2755141cc406Sopenharmony_ci 2756141cc406Sopenharmony_ci (void) local_only; /* just to get rid of the compiler warning */ 2757141cc406Sopenharmony_ci 2758141cc406Sopenharmony_ci if (devlist) 2759141cc406Sopenharmony_ci { 2760141cc406Sopenharmony_ci free (devlist); 2761141cc406Sopenharmony_ci } 2762141cc406Sopenharmony_ci 2763141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 2764141cc406Sopenharmony_ci if (!devlist) 2765141cc406Sopenharmony_ci { 2766141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 2767141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2768141cc406Sopenharmony_ci } 2769141cc406Sopenharmony_ci 2770141cc406Sopenharmony_ci i = 0; 2771141cc406Sopenharmony_ci 2772141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 2773141cc406Sopenharmony_ci { 2774141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 2775141cc406Sopenharmony_ci } 2776141cc406Sopenharmony_ci 2777141cc406Sopenharmony_ci devlist[i++] = 0; 2778141cc406Sopenharmony_ci 2779141cc406Sopenharmony_ci *device_list = devlist; 2780141cc406Sopenharmony_ci 2781141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2782141cc406Sopenharmony_ci} 2783141cc406Sopenharmony_ci 2784141cc406Sopenharmony_ci/* 2785141cc406Sopenharmony_ci * 2786141cc406Sopenharmony_ci * 2787141cc406Sopenharmony_ci */ 2788141cc406Sopenharmony_ci 2789141cc406Sopenharmony_cistatic SANE_Status 2790141cc406Sopenharmony_ciinit_options (Epson_Scanner * s) 2791141cc406Sopenharmony_ci{ 2792141cc406Sopenharmony_ci int i; 2793141cc406Sopenharmony_ci SANE_Bool dummy; 2794141cc406Sopenharmony_ci 2795141cc406Sopenharmony_ci DBG (5, "init_options()\n"); 2796141cc406Sopenharmony_ci 2797141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 2798141cc406Sopenharmony_ci { 2799141cc406Sopenharmony_ci s->opt[i].size = sizeof (SANE_Word); 2800141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2801141cc406Sopenharmony_ci } 2802141cc406Sopenharmony_ci 2803141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2804141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2805141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2806141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2807141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 2808141cc406Sopenharmony_ci 2809141cc406Sopenharmony_ci /* "Scan Mode" group: */ 2810141cc406Sopenharmony_ci 2811141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); 2812141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 2813141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 2814141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 2815141cc406Sopenharmony_ci 2816141cc406Sopenharmony_ci /* scan mode */ 2817141cc406Sopenharmony_ci s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 2818141cc406Sopenharmony_ci s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 2819141cc406Sopenharmony_ci s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 2820141cc406Sopenharmony_ci s->opt[OPT_MODE].type = SANE_TYPE_STRING; 2821141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size (mode_list); 2822141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2823141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_list; 2824141cc406Sopenharmony_ci s->val[OPT_MODE].w = 0; /* Binary */ 2825141cc406Sopenharmony_ci 2826141cc406Sopenharmony_ci /* bit depth */ 2827141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; 2828141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; 2829141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; 2830141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; 2831141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE; 2832141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2833141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].constraint.word_list = bitDepthList; 2834141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; 2835141cc406Sopenharmony_ci s->val[OPT_BIT_DEPTH].w = bitDepthList[1]; /* the first "real" element is the default */ 2836141cc406Sopenharmony_ci 2837141cc406Sopenharmony_ci if (bitDepthList[0] == 1) /* only one element in the list -> hide the option */ 2838141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; 2839141cc406Sopenharmony_ci 2840141cc406Sopenharmony_ci /* halftone */ 2841141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE; 2842141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; 2843141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].desc = SANE_I18N ("Selects the halftone."); 2844141cc406Sopenharmony_ci 2845141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING; 2846141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].size = max_string_size (halftone_list_7); 2847141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2848141cc406Sopenharmony_ci 2849141cc406Sopenharmony_ci if (s->hw->level >= 7) 2850141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_7; 2851141cc406Sopenharmony_ci else if (s->hw->level >= 4) 2852141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_4; 2853141cc406Sopenharmony_ci else 2854141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list; 2855141cc406Sopenharmony_ci 2856141cc406Sopenharmony_ci s->val[OPT_HALFTONE].w = 1; /* Halftone A */ 2857141cc406Sopenharmony_ci 2858141cc406Sopenharmony_ci if (!s->hw->cmd->set_halftoning) 2859141cc406Sopenharmony_ci { 2860141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 2861141cc406Sopenharmony_ci } 2862141cc406Sopenharmony_ci 2863141cc406Sopenharmony_ci /* dropout */ 2864141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].name = "dropout"; 2865141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].title = SANE_I18N ("Dropout"); 2866141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].desc = SANE_I18N ("Selects the dropout."); 2867141cc406Sopenharmony_ci 2868141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].type = SANE_TYPE_STRING; 2869141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].size = max_string_size (dropout_list); 2870141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].cap |= SANE_CAP_ADVANCED; 2871141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2872141cc406Sopenharmony_ci s->opt[OPT_DROPOUT].constraint.string_list = dropout_list; 2873141cc406Sopenharmony_ci s->val[OPT_DROPOUT].w = 0; /* None */ 2874141cc406Sopenharmony_ci 2875141cc406Sopenharmony_ci /* brightness */ 2876141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 2877141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 2878141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].desc = SANE_I18N ("Selects the brightness."); 2879141cc406Sopenharmony_ci 2880141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 2881141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 2882141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2883141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->cmd->bright_range; 2884141cc406Sopenharmony_ci s->val[OPT_BRIGHTNESS].w = 0; /* Normal */ 2885141cc406Sopenharmony_ci 2886141cc406Sopenharmony_ci if (!s->hw->cmd->set_bright) 2887141cc406Sopenharmony_ci { 2888141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2889141cc406Sopenharmony_ci } 2890141cc406Sopenharmony_ci 2891141cc406Sopenharmony_ci /* sharpness */ 2892141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].name = "sharpness"; 2893141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].title = SANE_I18N ("Sharpness"); 2894141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].desc = ""; 2895141cc406Sopenharmony_ci 2896141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].type = SANE_TYPE_INT; 2897141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].unit = SANE_UNIT_NONE; 2898141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2899141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].constraint.range = &outline_emphasis_range; 2900141cc406Sopenharmony_ci s->val[OPT_SHARPNESS].w = 0; /* Normal */ 2901141cc406Sopenharmony_ci 2902141cc406Sopenharmony_ci if (!s->hw->cmd->set_outline_emphasis) 2903141cc406Sopenharmony_ci { 2904141cc406Sopenharmony_ci s->opt[OPT_SHARPNESS].cap |= SANE_CAP_INACTIVE; 2905141cc406Sopenharmony_ci } 2906141cc406Sopenharmony_ci 2907141cc406Sopenharmony_ci 2908141cc406Sopenharmony_ci /* gamma */ 2909141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].name = SANE_NAME_GAMMA_CORRECTION; 2910141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].title = SANE_TITLE_GAMMA_CORRECTION; 2911141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].desc = SANE_DESC_GAMMA_CORRECTION; 2912141cc406Sopenharmony_ci 2913141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].type = SANE_TYPE_STRING; 2914141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2915141cc406Sopenharmony_ci /* 2916141cc406Sopenharmony_ci * special handling for D1 function level - at this time I'm not 2917141cc406Sopenharmony_ci * testing for D1, I'm just assuming that all D level scanners will 2918141cc406Sopenharmony_ci * behave the same way. This has to be confirmed with the next D-level 2919141cc406Sopenharmony_ci * scanner 2920141cc406Sopenharmony_ci */ 2921141cc406Sopenharmony_ci if (s->hw->cmd->level[0] == 'D') 2922141cc406Sopenharmony_ci { 2923141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].size = max_string_size (gamma_list_d); 2924141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].constraint.string_list = gamma_list_d; 2925141cc406Sopenharmony_ci s->val[OPT_GAMMA_CORRECTION].w = 1; /* Default */ 2926141cc406Sopenharmony_ci gamma_userdefined = gamma_userdefined_d; 2927141cc406Sopenharmony_ci gamma_params = gamma_params_d; 2928141cc406Sopenharmony_ci } 2929141cc406Sopenharmony_ci else 2930141cc406Sopenharmony_ci { 2931141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].size = max_string_size (gamma_list_ab); 2932141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].constraint.string_list = gamma_list_ab; 2933141cc406Sopenharmony_ci s->val[OPT_GAMMA_CORRECTION].w = 0; /* Default */ 2934141cc406Sopenharmony_ci gamma_userdefined = gamma_userdefined_ab; 2935141cc406Sopenharmony_ci gamma_params = gamma_params_ab; 2936141cc406Sopenharmony_ci } 2937141cc406Sopenharmony_ci 2938141cc406Sopenharmony_ci if (!s->hw->cmd->set_gamma) 2939141cc406Sopenharmony_ci { 2940141cc406Sopenharmony_ci s->opt[OPT_GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE; 2941141cc406Sopenharmony_ci } 2942141cc406Sopenharmony_ci 2943141cc406Sopenharmony_ci 2944141cc406Sopenharmony_ci /* gamma vector */ 2945141cc406Sopenharmony_ci/* 2946141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 2947141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 2948141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 2949141cc406Sopenharmony_ci 2950141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 2951141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 2952141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); 2953141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 2954141cc406Sopenharmony_ci s->opt[ OPT_GAMMA_VECTOR].constraint.range = &u8_range; 2955141cc406Sopenharmony_ci s->val[ OPT_GAMMA_VECTOR].wa = &s->gamma_table [ 0] [ 0]; 2956141cc406Sopenharmony_ci*/ 2957141cc406Sopenharmony_ci 2958141cc406Sopenharmony_ci 2959141cc406Sopenharmony_ci /* red gamma vector */ 2960141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 2961141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 2962141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 2963141cc406Sopenharmony_ci 2964141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 2965141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 2966141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); 2967141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 2968141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; 2969141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[0][0]; 2970141cc406Sopenharmony_ci 2971141cc406Sopenharmony_ci 2972141cc406Sopenharmony_ci /* green gamma vector */ 2973141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 2974141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 2975141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 2976141cc406Sopenharmony_ci 2977141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 2978141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 2979141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); 2980141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 2981141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; 2982141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[1][0]; 2983141cc406Sopenharmony_ci 2984141cc406Sopenharmony_ci 2985141cc406Sopenharmony_ci /* red gamma vector */ 2986141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 2987141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 2988141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 2989141cc406Sopenharmony_ci 2990141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 2991141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 2992141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); 2993141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 2994141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; 2995141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[2][0]; 2996141cc406Sopenharmony_ci 2997141cc406Sopenharmony_ci if (s->hw->cmd->set_gamma_table && 2998141cc406Sopenharmony_ci gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w] == SANE_TRUE) 2999141cc406Sopenharmony_ci { 3000141cc406Sopenharmony_ci/* s->opt[ OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; */ 3001141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 3002141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 3003141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 3004141cc406Sopenharmony_ci } 3005141cc406Sopenharmony_ci else 3006141cc406Sopenharmony_ci { 3007141cc406Sopenharmony_ci/* s->opt[ OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; */ 3008141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 3009141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 3010141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 3011141cc406Sopenharmony_ci } 3012141cc406Sopenharmony_ci 3013141cc406Sopenharmony_ci /* initialize the Gamma tables */ 3014141cc406Sopenharmony_ci memset (&s->gamma_table[0], 0, 256 * sizeof (SANE_Word)); 3015141cc406Sopenharmony_ci memset (&s->gamma_table[1], 0, 256 * sizeof (SANE_Word)); 3016141cc406Sopenharmony_ci memset (&s->gamma_table[2], 0, 256 * sizeof (SANE_Word)); 3017141cc406Sopenharmony_ci/* memset(&s->gamma_table[3], 0, 256 * sizeof(SANE_Word)); */ 3018141cc406Sopenharmony_ci for (i = 0; i < 256; i++) 3019141cc406Sopenharmony_ci { 3020141cc406Sopenharmony_ci s->gamma_table[0][i] = i; 3021141cc406Sopenharmony_ci s->gamma_table[1][i] = i; 3022141cc406Sopenharmony_ci s->gamma_table[2][i] = i; 3023141cc406Sopenharmony_ci/* s->gamma_table[3][i] = i; */ 3024141cc406Sopenharmony_ci } 3025141cc406Sopenharmony_ci 3026141cc406Sopenharmony_ci 3027141cc406Sopenharmony_ci /* color correction */ 3028141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].name = "color-correction"; 3029141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].title = SANE_I18N ("Color correction"); 3030141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].desc = 3031141cc406Sopenharmony_ci SANE_I18N 3032141cc406Sopenharmony_ci ("Sets the color correction table for the selected output device."); 3033141cc406Sopenharmony_ci 3034141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].type = SANE_TYPE_STRING; 3035141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].size = 32; 3036141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_ADVANCED; 3037141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3038141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].constraint.string_list = color_list; 3039141cc406Sopenharmony_ci s->val[OPT_COLOR_CORRECTION].w = 5; /* scanner default: CRT monitors */ 3040141cc406Sopenharmony_ci 3041141cc406Sopenharmony_ci if (!s->hw->cmd->set_color_correction) 3042141cc406Sopenharmony_ci { 3043141cc406Sopenharmony_ci s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_INACTIVE; 3044141cc406Sopenharmony_ci } 3045141cc406Sopenharmony_ci 3046141cc406Sopenharmony_ci /* resolution */ 3047141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 3048141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 3049141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 3050141cc406Sopenharmony_ci 3051141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 3052141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 3053141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 3054141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->resolution_list; 3055141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; 3056141cc406Sopenharmony_ci 3057141cc406Sopenharmony_ci /* threshold */ 3058141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 3059141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 3060141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 3061141cc406Sopenharmony_ci 3062141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 3063141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 3064141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 3065141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint.range = &u8_range; 3066141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w = 0x80; 3067141cc406Sopenharmony_ci 3068141cc406Sopenharmony_ci if (!s->hw->cmd->set_threshold) 3069141cc406Sopenharmony_ci { 3070141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 3071141cc406Sopenharmony_ci } 3072141cc406Sopenharmony_ci 3073141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].title = SANE_I18N ("Color correction coefficients"); 3074141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].desc = SANE_I18N ("Matrix multiplication of RGB"); 3075141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].type = SANE_TYPE_GROUP; 3076141cc406Sopenharmony_ci s->opt[OPT_CCT_GROUP].cap = SANE_CAP_ADVANCED; 3077141cc406Sopenharmony_ci 3078141cc406Sopenharmony_ci 3079141cc406Sopenharmony_ci /* color correction coefficients */ 3080141cc406Sopenharmony_ci s->opt[OPT_CCT_1].name = "cct-1"; 3081141cc406Sopenharmony_ci s->opt[OPT_CCT_2].name = "cct-2"; 3082141cc406Sopenharmony_ci s->opt[OPT_CCT_3].name = "cct-3"; 3083141cc406Sopenharmony_ci s->opt[OPT_CCT_4].name = "cct-4"; 3084141cc406Sopenharmony_ci s->opt[OPT_CCT_5].name = "cct-5"; 3085141cc406Sopenharmony_ci s->opt[OPT_CCT_6].name = "cct-6"; 3086141cc406Sopenharmony_ci s->opt[OPT_CCT_7].name = "cct-7"; 3087141cc406Sopenharmony_ci s->opt[OPT_CCT_8].name = "cct-8"; 3088141cc406Sopenharmony_ci s->opt[OPT_CCT_9].name = "cct-9"; 3089141cc406Sopenharmony_ci 3090141cc406Sopenharmony_ci s->opt[OPT_CCT_1].title = SANE_I18N ("Green"); 3091141cc406Sopenharmony_ci s->opt[OPT_CCT_2].title = SANE_I18N ("Shift green to red"); 3092141cc406Sopenharmony_ci s->opt[OPT_CCT_3].title = SANE_I18N ("Shift green to blue"); 3093141cc406Sopenharmony_ci s->opt[OPT_CCT_4].title = SANE_I18N ("Shift red to green"); 3094141cc406Sopenharmony_ci s->opt[OPT_CCT_5].title = SANE_I18N ("Red"); 3095141cc406Sopenharmony_ci s->opt[OPT_CCT_6].title = SANE_I18N ("Shift red to blue"); 3096141cc406Sopenharmony_ci s->opt[OPT_CCT_7].title = SANE_I18N ("Shift blue to green"); 3097141cc406Sopenharmony_ci s->opt[OPT_CCT_8].title = SANE_I18N ("Shift blue to red"); 3098141cc406Sopenharmony_ci s->opt[OPT_CCT_9].title = SANE_I18N ("Blue"); 3099141cc406Sopenharmony_ci 3100141cc406Sopenharmony_ci s->opt[OPT_CCT_1].desc = SANE_I18N ("Controls green level"); 3101141cc406Sopenharmony_ci s->opt[OPT_CCT_2].desc = SANE_I18N ("Adds to red based on green level"); 3102141cc406Sopenharmony_ci s->opt[OPT_CCT_3].desc = SANE_I18N ("Adds to blue based on green level"); 3103141cc406Sopenharmony_ci s->opt[OPT_CCT_4].desc = SANE_I18N ("Adds to green based on red level"); 3104141cc406Sopenharmony_ci s->opt[OPT_CCT_5].desc = SANE_I18N ("Controls red level"); 3105141cc406Sopenharmony_ci s->opt[OPT_CCT_6].desc = SANE_I18N ("Adds to blue based on red level"); 3106141cc406Sopenharmony_ci s->opt[OPT_CCT_7].desc = SANE_I18N ("Adds to green based on blue level"); 3107141cc406Sopenharmony_ci s->opt[OPT_CCT_8].desc = SANE_I18N ("Adds to red based on blue level"); 3108141cc406Sopenharmony_ci s->opt[OPT_CCT_9].desc = SANE_I18N ("Controls blue level"); 3109141cc406Sopenharmony_ci 3110141cc406Sopenharmony_ci s->opt[OPT_CCT_1].type = SANE_TYPE_INT; 3111141cc406Sopenharmony_ci s->opt[OPT_CCT_2].type = SANE_TYPE_INT; 3112141cc406Sopenharmony_ci s->opt[OPT_CCT_3].type = SANE_TYPE_INT; 3113141cc406Sopenharmony_ci s->opt[OPT_CCT_4].type = SANE_TYPE_INT; 3114141cc406Sopenharmony_ci s->opt[OPT_CCT_5].type = SANE_TYPE_INT; 3115141cc406Sopenharmony_ci s->opt[OPT_CCT_6].type = SANE_TYPE_INT; 3116141cc406Sopenharmony_ci s->opt[OPT_CCT_7].type = SANE_TYPE_INT; 3117141cc406Sopenharmony_ci s->opt[OPT_CCT_8].type = SANE_TYPE_INT; 3118141cc406Sopenharmony_ci s->opt[OPT_CCT_9].type = SANE_TYPE_INT; 3119141cc406Sopenharmony_ci 3120141cc406Sopenharmony_ci s->opt[OPT_CCT_1].cap |= SANE_CAP_ADVANCED; 3121141cc406Sopenharmony_ci s->opt[OPT_CCT_2].cap |= SANE_CAP_ADVANCED; 3122141cc406Sopenharmony_ci s->opt[OPT_CCT_3].cap |= SANE_CAP_ADVANCED; 3123141cc406Sopenharmony_ci s->opt[OPT_CCT_4].cap |= SANE_CAP_ADVANCED; 3124141cc406Sopenharmony_ci s->opt[OPT_CCT_5].cap |= SANE_CAP_ADVANCED; 3125141cc406Sopenharmony_ci s->opt[OPT_CCT_6].cap |= SANE_CAP_ADVANCED; 3126141cc406Sopenharmony_ci s->opt[OPT_CCT_7].cap |= SANE_CAP_ADVANCED; 3127141cc406Sopenharmony_ci s->opt[OPT_CCT_8].cap |= SANE_CAP_ADVANCED; 3128141cc406Sopenharmony_ci s->opt[OPT_CCT_9].cap |= SANE_CAP_ADVANCED; 3129141cc406Sopenharmony_ci 3130141cc406Sopenharmony_ci s->opt[OPT_CCT_1].cap |= SANE_CAP_INACTIVE; 3131141cc406Sopenharmony_ci s->opt[OPT_CCT_2].cap |= SANE_CAP_INACTIVE; 3132141cc406Sopenharmony_ci s->opt[OPT_CCT_3].cap |= SANE_CAP_INACTIVE; 3133141cc406Sopenharmony_ci s->opt[OPT_CCT_4].cap |= SANE_CAP_INACTIVE; 3134141cc406Sopenharmony_ci s->opt[OPT_CCT_5].cap |= SANE_CAP_INACTIVE; 3135141cc406Sopenharmony_ci s->opt[OPT_CCT_6].cap |= SANE_CAP_INACTIVE; 3136141cc406Sopenharmony_ci s->opt[OPT_CCT_7].cap |= SANE_CAP_INACTIVE; 3137141cc406Sopenharmony_ci s->opt[OPT_CCT_8].cap |= SANE_CAP_INACTIVE; 3138141cc406Sopenharmony_ci s->opt[OPT_CCT_9].cap |= SANE_CAP_INACTIVE; 3139141cc406Sopenharmony_ci 3140141cc406Sopenharmony_ci s->opt[OPT_CCT_1].unit = SANE_UNIT_NONE; 3141141cc406Sopenharmony_ci s->opt[OPT_CCT_2].unit = SANE_UNIT_NONE; 3142141cc406Sopenharmony_ci s->opt[OPT_CCT_3].unit = SANE_UNIT_NONE; 3143141cc406Sopenharmony_ci s->opt[OPT_CCT_4].unit = SANE_UNIT_NONE; 3144141cc406Sopenharmony_ci s->opt[OPT_CCT_5].unit = SANE_UNIT_NONE; 3145141cc406Sopenharmony_ci s->opt[OPT_CCT_6].unit = SANE_UNIT_NONE; 3146141cc406Sopenharmony_ci s->opt[OPT_CCT_7].unit = SANE_UNIT_NONE; 3147141cc406Sopenharmony_ci s->opt[OPT_CCT_8].unit = SANE_UNIT_NONE; 3148141cc406Sopenharmony_ci s->opt[OPT_CCT_9].unit = SANE_UNIT_NONE; 3149141cc406Sopenharmony_ci 3150141cc406Sopenharmony_ci s->opt[OPT_CCT_1].constraint_type = SANE_CONSTRAINT_RANGE; 3151141cc406Sopenharmony_ci s->opt[OPT_CCT_2].constraint_type = SANE_CONSTRAINT_RANGE; 3152141cc406Sopenharmony_ci s->opt[OPT_CCT_3].constraint_type = SANE_CONSTRAINT_RANGE; 3153141cc406Sopenharmony_ci s->opt[OPT_CCT_4].constraint_type = SANE_CONSTRAINT_RANGE; 3154141cc406Sopenharmony_ci s->opt[OPT_CCT_5].constraint_type = SANE_CONSTRAINT_RANGE; 3155141cc406Sopenharmony_ci s->opt[OPT_CCT_6].constraint_type = SANE_CONSTRAINT_RANGE; 3156141cc406Sopenharmony_ci s->opt[OPT_CCT_7].constraint_type = SANE_CONSTRAINT_RANGE; 3157141cc406Sopenharmony_ci s->opt[OPT_CCT_8].constraint_type = SANE_CONSTRAINT_RANGE; 3158141cc406Sopenharmony_ci s->opt[OPT_CCT_9].constraint_type = SANE_CONSTRAINT_RANGE; 3159141cc406Sopenharmony_ci 3160141cc406Sopenharmony_ci s->opt[OPT_CCT_1].constraint.range = &s8_range; 3161141cc406Sopenharmony_ci s->opt[OPT_CCT_2].constraint.range = &s8_range; 3162141cc406Sopenharmony_ci s->opt[OPT_CCT_3].constraint.range = &s8_range; 3163141cc406Sopenharmony_ci s->opt[OPT_CCT_4].constraint.range = &s8_range; 3164141cc406Sopenharmony_ci s->opt[OPT_CCT_5].constraint.range = &s8_range; 3165141cc406Sopenharmony_ci s->opt[OPT_CCT_6].constraint.range = &s8_range; 3166141cc406Sopenharmony_ci s->opt[OPT_CCT_7].constraint.range = &s8_range; 3167141cc406Sopenharmony_ci s->opt[OPT_CCT_8].constraint.range = &s8_range; 3168141cc406Sopenharmony_ci s->opt[OPT_CCT_9].constraint.range = &s8_range; 3169141cc406Sopenharmony_ci 3170141cc406Sopenharmony_ci s->val[OPT_CCT_1].w = 32; 3171141cc406Sopenharmony_ci s->val[OPT_CCT_2].w = 0; 3172141cc406Sopenharmony_ci s->val[OPT_CCT_3].w = 0; 3173141cc406Sopenharmony_ci s->val[OPT_CCT_4].w = 0; 3174141cc406Sopenharmony_ci s->val[OPT_CCT_5].w = 32; 3175141cc406Sopenharmony_ci s->val[OPT_CCT_6].w = 0; 3176141cc406Sopenharmony_ci s->val[OPT_CCT_7].w = 0; 3177141cc406Sopenharmony_ci s->val[OPT_CCT_8].w = 0; 3178141cc406Sopenharmony_ci s->val[OPT_CCT_9].w = 32; 3179141cc406Sopenharmony_ci 3180141cc406Sopenharmony_ci if (!s->hw->cmd->set_color_correction_coefficients) 3181141cc406Sopenharmony_ci { 3182141cc406Sopenharmony_ci s->opt[OPT_CCT_1].cap |= SANE_CAP_INACTIVE; 3183141cc406Sopenharmony_ci s->opt[OPT_CCT_2].cap |= SANE_CAP_INACTIVE; 3184141cc406Sopenharmony_ci s->opt[OPT_CCT_3].cap |= SANE_CAP_INACTIVE; 3185141cc406Sopenharmony_ci s->opt[OPT_CCT_4].cap |= SANE_CAP_INACTIVE; 3186141cc406Sopenharmony_ci s->opt[OPT_CCT_5].cap |= SANE_CAP_INACTIVE; 3187141cc406Sopenharmony_ci s->opt[OPT_CCT_6].cap |= SANE_CAP_INACTIVE; 3188141cc406Sopenharmony_ci s->opt[OPT_CCT_7].cap |= SANE_CAP_INACTIVE; 3189141cc406Sopenharmony_ci s->opt[OPT_CCT_8].cap |= SANE_CAP_INACTIVE; 3190141cc406Sopenharmony_ci s->opt[OPT_CCT_9].cap |= SANE_CAP_INACTIVE; 3191141cc406Sopenharmony_ci } 3192141cc406Sopenharmony_ci 3193141cc406Sopenharmony_ci 3194141cc406Sopenharmony_ci /* "Advanced" group: */ 3195141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].title = SANE_I18N ("Advanced"); 3196141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].desc = ""; 3197141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; 3198141cc406Sopenharmony_ci s->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; 3199141cc406Sopenharmony_ci 3200141cc406Sopenharmony_ci 3201141cc406Sopenharmony_ci /* mirror */ 3202141cc406Sopenharmony_ci s->opt[OPT_MIRROR].name = "mirror"; 3203141cc406Sopenharmony_ci s->opt[OPT_MIRROR].title = SANE_I18N ("Mirror image"); 3204141cc406Sopenharmony_ci s->opt[OPT_MIRROR].desc = SANE_I18N ("Mirror the image."); 3205141cc406Sopenharmony_ci 3206141cc406Sopenharmony_ci s->opt[OPT_MIRROR].type = SANE_TYPE_BOOL; 3207141cc406Sopenharmony_ci s->val[OPT_MIRROR].w = SANE_FALSE; 3208141cc406Sopenharmony_ci 3209141cc406Sopenharmony_ci if (!s->hw->cmd->mirror_image) 3210141cc406Sopenharmony_ci { 3211141cc406Sopenharmony_ci s->opt[OPT_MIRROR].cap |= SANE_CAP_INACTIVE; 3212141cc406Sopenharmony_ci } 3213141cc406Sopenharmony_ci 3214141cc406Sopenharmony_ci 3215141cc406Sopenharmony_ci /* speed */ 3216141cc406Sopenharmony_ci s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; 3217141cc406Sopenharmony_ci s->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; 3218141cc406Sopenharmony_ci s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; 3219141cc406Sopenharmony_ci 3220141cc406Sopenharmony_ci s->opt[OPT_SPEED].type = SANE_TYPE_BOOL; 3221141cc406Sopenharmony_ci s->val[OPT_SPEED].w = SANE_FALSE; 3222141cc406Sopenharmony_ci 3223141cc406Sopenharmony_ci if (!s->hw->cmd->set_speed) 3224141cc406Sopenharmony_ci { 3225141cc406Sopenharmony_ci s->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE; 3226141cc406Sopenharmony_ci } 3227141cc406Sopenharmony_ci 3228141cc406Sopenharmony_ci /* preview speed */ 3229141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_SPEED].name = "preview-speed"; 3230141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_SPEED].title = SANE_I18N ("Fast preview"); 3231141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_SPEED].desc = ""; 3232141cc406Sopenharmony_ci 3233141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_SPEED].type = SANE_TYPE_BOOL; 3234141cc406Sopenharmony_ci s->val[OPT_PREVIEW_SPEED].w = SANE_FALSE; 3235141cc406Sopenharmony_ci 3236141cc406Sopenharmony_ci if (!s->hw->cmd->set_speed) 3237141cc406Sopenharmony_ci { 3238141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_SPEED].cap |= SANE_CAP_INACTIVE; 3239141cc406Sopenharmony_ci } 3240141cc406Sopenharmony_ci 3241141cc406Sopenharmony_ci /* auto area segmentation */ 3242141cc406Sopenharmony_ci s->opt[OPT_AAS].name = "auto-area-segmentation"; 3243141cc406Sopenharmony_ci s->opt[OPT_AAS].title = SANE_I18N ("Auto area segmentation"); 3244141cc406Sopenharmony_ci s->opt[OPT_AAS].desc = ""; 3245141cc406Sopenharmony_ci 3246141cc406Sopenharmony_ci s->opt[OPT_AAS].type = SANE_TYPE_BOOL; 3247141cc406Sopenharmony_ci s->val[OPT_AAS].w = SANE_TRUE; 3248141cc406Sopenharmony_ci 3249141cc406Sopenharmony_ci if (!s->hw->cmd->control_auto_area_segmentation) 3250141cc406Sopenharmony_ci { 3251141cc406Sopenharmony_ci s->opt[OPT_AAS].cap |= SANE_CAP_INACTIVE; 3252141cc406Sopenharmony_ci } 3253141cc406Sopenharmony_ci 3254141cc406Sopenharmony_ci /* limit resolution list */ 3255141cc406Sopenharmony_ci s->opt[OPT_LIMIT_RESOLUTION].name = "short-resolution"; 3256141cc406Sopenharmony_ci s->opt[OPT_LIMIT_RESOLUTION].title = SANE_I18N ("Short resolution list"); 3257141cc406Sopenharmony_ci s->opt[OPT_LIMIT_RESOLUTION].desc = 3258141cc406Sopenharmony_ci SANE_I18N ("Display short resolution list"); 3259141cc406Sopenharmony_ci s->opt[OPT_LIMIT_RESOLUTION].type = SANE_TYPE_BOOL; 3260141cc406Sopenharmony_ci s->val[OPT_LIMIT_RESOLUTION].w = SANE_FALSE; 3261141cc406Sopenharmony_ci 3262141cc406Sopenharmony_ci 3263141cc406Sopenharmony_ci /* zoom */ 3264141cc406Sopenharmony_ci s->opt[OPT_ZOOM].name = "zoom"; 3265141cc406Sopenharmony_ci s->opt[OPT_ZOOM].title = SANE_I18N ("Zoom"); 3266141cc406Sopenharmony_ci s->opt[OPT_ZOOM].desc = 3267141cc406Sopenharmony_ci SANE_I18N ("Defines the zoom factor the scanner will use"); 3268141cc406Sopenharmony_ci 3269141cc406Sopenharmony_ci s->opt[OPT_ZOOM].type = SANE_TYPE_INT; 3270141cc406Sopenharmony_ci s->opt[OPT_ZOOM].unit = SANE_UNIT_NONE; 3271141cc406Sopenharmony_ci s->opt[OPT_ZOOM].constraint_type = SANE_CONSTRAINT_RANGE; 3272141cc406Sopenharmony_ci s->opt[OPT_ZOOM].constraint.range = &zoom_range; 3273141cc406Sopenharmony_ci s->val[OPT_ZOOM].w = 100; 3274141cc406Sopenharmony_ci 3275141cc406Sopenharmony_ci/* if( ! s->hw->cmd->set_zoom) */ 3276141cc406Sopenharmony_ci { 3277141cc406Sopenharmony_ci s->opt[OPT_ZOOM].cap |= SANE_CAP_INACTIVE; 3278141cc406Sopenharmony_ci } 3279141cc406Sopenharmony_ci 3280141cc406Sopenharmony_ci 3281141cc406Sopenharmony_ci /* "Preview settings" group: */ 3282141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].title = SANE_TITLE_PREVIEW; 3283141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].desc = ""; 3284141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].type = SANE_TYPE_GROUP; 3285141cc406Sopenharmony_ci s->opt[OPT_PREVIEW_GROUP].cap = SANE_CAP_ADVANCED; 3286141cc406Sopenharmony_ci 3287141cc406Sopenharmony_ci /* preview */ 3288141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 3289141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 3290141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 3291141cc406Sopenharmony_ci 3292141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 3293141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = SANE_FALSE; 3294141cc406Sopenharmony_ci 3295141cc406Sopenharmony_ci /* "Geometry" group: */ 3296141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); 3297141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 3298141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 3299141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 3300141cc406Sopenharmony_ci 3301141cc406Sopenharmony_ci /* top-left x */ 3302141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 3303141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 3304141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 3305141cc406Sopenharmony_ci 3306141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 3307141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 3308141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 3309141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = s->hw->x_range; 3310141cc406Sopenharmony_ci s->val[OPT_TL_X].w = 0; 3311141cc406Sopenharmony_ci 3312141cc406Sopenharmony_ci /* top-left y */ 3313141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 3314141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 3315141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 3316141cc406Sopenharmony_ci 3317141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 3318141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 3319141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 3320141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = s->hw->y_range; 3321141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = 0; 3322141cc406Sopenharmony_ci 3323141cc406Sopenharmony_ci /* bottom-right x */ 3324141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 3325141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 3326141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 3327141cc406Sopenharmony_ci 3328141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 3329141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 3330141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 3331141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = s->hw->x_range; 3332141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->x_range->max; 3333141cc406Sopenharmony_ci 3334141cc406Sopenharmony_ci /* bottom-right y */ 3335141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 3336141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 3337141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 3338141cc406Sopenharmony_ci 3339141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 3340141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 3341141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 3342141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; 3343141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->y_range->max; 3344141cc406Sopenharmony_ci 3345141cc406Sopenharmony_ci /* Quick format */ 3346141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].name = "quick-format"; 3347141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].title = SANE_I18N ("Quick format"); 3348141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].desc = ""; 3349141cc406Sopenharmony_ci 3350141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].type = SANE_TYPE_STRING; 3351141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].size = max_string_size (qf_list); 3352141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].cap |= SANE_CAP_ADVANCED; 3353141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3354141cc406Sopenharmony_ci s->opt[OPT_QUICK_FORMAT].constraint.string_list = qf_list; 3355141cc406Sopenharmony_ci s->val[OPT_QUICK_FORMAT].w = XtNumber (qf_params) - 1; /* max */ 3356141cc406Sopenharmony_ci 3357141cc406Sopenharmony_ci /* "Optional equipment" group: */ 3358141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].title = SANE_I18N ("Optional equipment"); 3359141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].desc = ""; 3360141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].type = SANE_TYPE_GROUP; 3361141cc406Sopenharmony_ci s->opt[OPT_EQU_GROUP].cap = SANE_CAP_ADVANCED; 3362141cc406Sopenharmony_ci 3363141cc406Sopenharmony_ci 3364141cc406Sopenharmony_ci /* source */ 3365141cc406Sopenharmony_ci s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 3366141cc406Sopenharmony_ci s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 3367141cc406Sopenharmony_ci s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 3368141cc406Sopenharmony_ci 3369141cc406Sopenharmony_ci s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; 3370141cc406Sopenharmony_ci s->opt[OPT_SOURCE].size = max_string_size (source_list); 3371141cc406Sopenharmony_ci 3372141cc406Sopenharmony_ci s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3373141cc406Sopenharmony_ci s->opt[OPT_SOURCE].constraint.string_list = source_list; 3374141cc406Sopenharmony_ci 3375141cc406Sopenharmony_ci if (!s->hw->extension) 3376141cc406Sopenharmony_ci { 3377141cc406Sopenharmony_ci s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; 3378141cc406Sopenharmony_ci } 3379141cc406Sopenharmony_ci s->val[OPT_SOURCE].w = 0; /* always use Flatbed as default */ 3380141cc406Sopenharmony_ci 3381141cc406Sopenharmony_ci 3382141cc406Sopenharmony_ci /* film type */ 3383141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].name = "film-type"; 3384141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].title = SANE_I18N ("Film type"); 3385141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].desc = ""; 3386141cc406Sopenharmony_ci 3387141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].type = SANE_TYPE_STRING; 3388141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].size = max_string_size (film_list); 3389141cc406Sopenharmony_ci 3390141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3391141cc406Sopenharmony_ci s->opt[OPT_FILM_TYPE].constraint.string_list = film_list; 3392141cc406Sopenharmony_ci 3393141cc406Sopenharmony_ci s->val[OPT_FILM_TYPE].w = 0; 3394141cc406Sopenharmony_ci 3395141cc406Sopenharmony_ci deactivateOption (s, OPT_FILM_TYPE, &dummy); /* default is inactive */ 3396141cc406Sopenharmony_ci 3397141cc406Sopenharmony_ci /* focus position */ 3398141cc406Sopenharmony_ci s->opt[OPT_FOCUS].name = SANE_EPSON_FOCUS_NAME; 3399141cc406Sopenharmony_ci s->opt[OPT_FOCUS].title = SANE_EPSON_FOCUS_TITLE; 3400141cc406Sopenharmony_ci s->opt[OPT_FOCUS].desc = SANE_EPSON_FOCUS_DESC; 3401141cc406Sopenharmony_ci s->opt[OPT_FOCUS].type = SANE_TYPE_STRING; 3402141cc406Sopenharmony_ci s->opt[OPT_FOCUS].size = max_string_size (focus_list); 3403141cc406Sopenharmony_ci s->opt[OPT_FOCUS].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3404141cc406Sopenharmony_ci s->opt[OPT_FOCUS].constraint.string_list = focus_list; 3405141cc406Sopenharmony_ci s->val[OPT_FOCUS].w = 0; 3406141cc406Sopenharmony_ci 3407141cc406Sopenharmony_ci s->opt[OPT_FOCUS].cap |= SANE_CAP_ADVANCED; 3408141cc406Sopenharmony_ci if (s->hw->focusSupport == SANE_TRUE) 3409141cc406Sopenharmony_ci { 3410141cc406Sopenharmony_ci s->opt[OPT_FOCUS].cap &= ~SANE_CAP_INACTIVE; 3411141cc406Sopenharmony_ci } 3412141cc406Sopenharmony_ci else 3413141cc406Sopenharmony_ci { 3414141cc406Sopenharmony_ci s->opt[OPT_FOCUS].cap |= SANE_CAP_INACTIVE; 3415141cc406Sopenharmony_ci } 3416141cc406Sopenharmony_ci 3417141cc406Sopenharmony_ci#if 0 3418141cc406Sopenharmony_ci if ((!s->hw->TPU) && (!s->hw->cmd->set_bay)) 3419141cc406Sopenharmony_ci { /* Hack: Using set_bay to indicate. */ 3420141cc406Sopenharmony_ci SANE_Bool dummy; 3421141cc406Sopenharmony_ci deactivateOption (s, OPT_FILM_TYPE, &dummy); 3422141cc406Sopenharmony_ci 3423141cc406Sopenharmony_ci } 3424141cc406Sopenharmony_ci#endif 3425141cc406Sopenharmony_ci 3426141cc406Sopenharmony_ci 3427141cc406Sopenharmony_ci /* forward feed / eject */ 3428141cc406Sopenharmony_ci s->opt[OPT_EJECT].name = "eject"; 3429141cc406Sopenharmony_ci s->opt[OPT_EJECT].title = SANE_I18N ("Eject"); 3430141cc406Sopenharmony_ci s->opt[OPT_EJECT].desc = SANE_I18N ("Eject the sheet in the ADF"); 3431141cc406Sopenharmony_ci 3432141cc406Sopenharmony_ci s->opt[OPT_EJECT].type = SANE_TYPE_BUTTON; 3433141cc406Sopenharmony_ci 3434141cc406Sopenharmony_ci if ((!s->hw->ADF) && (!s->hw->cmd->set_bay)) 3435141cc406Sopenharmony_ci { /* Hack: Using set_bay to indicate. */ 3436141cc406Sopenharmony_ci s->opt[OPT_EJECT].cap |= SANE_CAP_INACTIVE; 3437141cc406Sopenharmony_ci } 3438141cc406Sopenharmony_ci 3439141cc406Sopenharmony_ci 3440141cc406Sopenharmony_ci /* auto forward feed / eject */ 3441141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].name = "auto-eject"; 3442141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].title = SANE_I18N ("Auto eject"); 3443141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].desc = SANE_I18N ("Eject document after scanning"); 3444141cc406Sopenharmony_ci 3445141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].type = SANE_TYPE_BOOL; 3446141cc406Sopenharmony_ci s->val[OPT_AUTO_EJECT].w = SANE_FALSE; 3447141cc406Sopenharmony_ci 3448141cc406Sopenharmony_ci if (!s->hw->ADF) 3449141cc406Sopenharmony_ci { 3450141cc406Sopenharmony_ci s->opt[OPT_AUTO_EJECT].cap |= SANE_CAP_INACTIVE; 3451141cc406Sopenharmony_ci } 3452141cc406Sopenharmony_ci 3453141cc406Sopenharmony_ci 3454141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].name = "adf_mode"; 3455141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].title = SANE_I18N ("ADF Mode"); 3456141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].desc = 3457141cc406Sopenharmony_ci SANE_I18N ("Selects the ADF mode (simplex/duplex)"); 3458141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING; 3459141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].size = max_string_size (adf_mode_list); 3460141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3461141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list; 3462141cc406Sopenharmony_ci s->val[OPT_ADF_MODE].w = 0; /* simplex */ 3463141cc406Sopenharmony_ci 3464141cc406Sopenharmony_ci if ((!s->hw->ADF) || (s->hw->duplexSupport == SANE_FALSE)) 3465141cc406Sopenharmony_ci { 3466141cc406Sopenharmony_ci s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE; 3467141cc406Sopenharmony_ci } 3468141cc406Sopenharmony_ci 3469141cc406Sopenharmony_ci /* select bay */ 3470141cc406Sopenharmony_ci s->opt[OPT_BAY].name = "bay"; 3471141cc406Sopenharmony_ci s->opt[OPT_BAY].title = SANE_I18N ("Bay"); 3472141cc406Sopenharmony_ci s->opt[OPT_BAY].desc = SANE_I18N ("Select bay to scan"); 3473141cc406Sopenharmony_ci 3474141cc406Sopenharmony_ci s->opt[OPT_BAY].type = SANE_TYPE_STRING; 3475141cc406Sopenharmony_ci s->opt[OPT_BAY].size = max_string_size (bay_list); 3476141cc406Sopenharmony_ci s->opt[OPT_BAY].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3477141cc406Sopenharmony_ci s->opt[OPT_BAY].constraint.string_list = bay_list; 3478141cc406Sopenharmony_ci s->val[OPT_BAY].w = 0; /* Bay 1 */ 3479141cc406Sopenharmony_ci 3480141cc406Sopenharmony_ci if (!s->hw->cmd->set_bay) 3481141cc406Sopenharmony_ci { 3482141cc406Sopenharmony_ci s->opt[OPT_BAY].cap |= SANE_CAP_INACTIVE; 3483141cc406Sopenharmony_ci } 3484141cc406Sopenharmony_ci 3485141cc406Sopenharmony_ci 3486141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].name = SANE_EPSON_WAIT_FOR_BUTTON_NAME; 3487141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].title = SANE_EPSON_WAIT_FOR_BUTTON_TITLE; 3488141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].desc = SANE_EPSON_WAIT_FOR_BUTTON_DESC; 3489141cc406Sopenharmony_ci 3490141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].type = SANE_TYPE_BOOL; 3491141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].unit = SANE_UNIT_NONE; 3492141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].constraint_type = SANE_CONSTRAINT_NONE; 3493141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].constraint.range = NULL; 3494141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_ADVANCED; 3495141cc406Sopenharmony_ci 3496141cc406Sopenharmony_ci if (!s->hw->cmd->request_push_button_status) 3497141cc406Sopenharmony_ci { 3498141cc406Sopenharmony_ci s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_INACTIVE; 3499141cc406Sopenharmony_ci } 3500141cc406Sopenharmony_ci 3501141cc406Sopenharmony_ci 3502141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3503141cc406Sopenharmony_ci} 3504141cc406Sopenharmony_ci 3505141cc406Sopenharmony_ci/* 3506141cc406Sopenharmony_ci * 3507141cc406Sopenharmony_ci * 3508141cc406Sopenharmony_ci */ 3509141cc406Sopenharmony_ci 3510141cc406Sopenharmony_ciSANE_Status 3511141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 3512141cc406Sopenharmony_ci{ 3513141cc406Sopenharmony_ci Epson_Device *dev; 3514141cc406Sopenharmony_ci Epson_Scanner *s; 3515141cc406Sopenharmony_ci 3516141cc406Sopenharmony_ci DBG (5, "sane_open(%s)\n", devicename); 3517141cc406Sopenharmony_ci 3518141cc406Sopenharmony_ci /* search for device */ 3519141cc406Sopenharmony_ci if (devicename[0]) 3520141cc406Sopenharmony_ci { 3521141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 3522141cc406Sopenharmony_ci { 3523141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 3524141cc406Sopenharmony_ci { 3525141cc406Sopenharmony_ci break; 3526141cc406Sopenharmony_ci } 3527141cc406Sopenharmony_ci } 3528141cc406Sopenharmony_ci 3529141cc406Sopenharmony_ci if (!dev) 3530141cc406Sopenharmony_ci { 3531141cc406Sopenharmony_ci#if 0 3532141cc406Sopenharmony_ci status = attach (devicename, &dev, SANE_EPSON_); 3533141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3534141cc406Sopenharmony_ci { 3535141cc406Sopenharmony_ci return status; 3536141cc406Sopenharmony_ci } 3537141cc406Sopenharmony_ci#endif 3538141cc406Sopenharmony_ci DBG (1, "Error opening the device"); 3539141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3540141cc406Sopenharmony_ci } 3541141cc406Sopenharmony_ci } 3542141cc406Sopenharmony_ci else 3543141cc406Sopenharmony_ci { 3544141cc406Sopenharmony_ci dev = first_dev; 3545141cc406Sopenharmony_ci } 3546141cc406Sopenharmony_ci 3547141cc406Sopenharmony_ci if (!dev) 3548141cc406Sopenharmony_ci { 3549141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3550141cc406Sopenharmony_ci } 3551141cc406Sopenharmony_ci 3552141cc406Sopenharmony_ci s = calloc (sizeof (Epson_Scanner), 1); 3553141cc406Sopenharmony_ci if (!s) 3554141cc406Sopenharmony_ci { 3555141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 3556141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3557141cc406Sopenharmony_ci } 3558141cc406Sopenharmony_ci 3559141cc406Sopenharmony_ci s->fd = -1; 3560141cc406Sopenharmony_ci s->hw = dev; 3561141cc406Sopenharmony_ci 3562141cc406Sopenharmony_ci init_options (s); 3563141cc406Sopenharmony_ci 3564141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles */ 3565141cc406Sopenharmony_ci s->next = first_handle; 3566141cc406Sopenharmony_ci first_handle = s; 3567141cc406Sopenharmony_ci 3568141cc406Sopenharmony_ci *handle = (SANE_Handle) s; 3569141cc406Sopenharmony_ci 3570141cc406Sopenharmony_ci open_scanner (s); 3571141cc406Sopenharmony_ci 3572141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3573141cc406Sopenharmony_ci} 3574141cc406Sopenharmony_ci 3575141cc406Sopenharmony_ci/* 3576141cc406Sopenharmony_ci * 3577141cc406Sopenharmony_ci * 3578141cc406Sopenharmony_ci */ 3579141cc406Sopenharmony_ci 3580141cc406Sopenharmony_civoid 3581141cc406Sopenharmony_cisane_close (SANE_Handle handle) 3582141cc406Sopenharmony_ci{ 3583141cc406Sopenharmony_ci Epson_Scanner *s, *prev; 3584141cc406Sopenharmony_ci 3585141cc406Sopenharmony_ci /* 3586141cc406Sopenharmony_ci * Test if there is still data pending from 3587141cc406Sopenharmony_ci * the scanner. If so, then do a cancel 3588141cc406Sopenharmony_ci */ 3589141cc406Sopenharmony_ci 3590141cc406Sopenharmony_ci s = (Epson_Scanner *) handle; 3591141cc406Sopenharmony_ci 3592141cc406Sopenharmony_ci /* remove handle from list of open handles */ 3593141cc406Sopenharmony_ci prev = 0; 3594141cc406Sopenharmony_ci for (s = first_handle; s; s = s->next) 3595141cc406Sopenharmony_ci { 3596141cc406Sopenharmony_ci if (s == handle) 3597141cc406Sopenharmony_ci break; 3598141cc406Sopenharmony_ci prev = s; 3599141cc406Sopenharmony_ci } 3600141cc406Sopenharmony_ci 3601141cc406Sopenharmony_ci if (!s) 3602141cc406Sopenharmony_ci { 3603141cc406Sopenharmony_ci DBG (1, "close: invalid handle (0x%p)\n", handle); 3604141cc406Sopenharmony_ci return; 3605141cc406Sopenharmony_ci } 3606141cc406Sopenharmony_ci 3607141cc406Sopenharmony_ci if (prev) 3608141cc406Sopenharmony_ci prev->next = s->next; 3609141cc406Sopenharmony_ci else 3610141cc406Sopenharmony_ci first_handle = s->next; 3611141cc406Sopenharmony_ci 3612141cc406Sopenharmony_ci if (s->fd != -1) 3613141cc406Sopenharmony_ci close_scanner (s); 3614141cc406Sopenharmony_ci 3615141cc406Sopenharmony_ci free (s); 3616141cc406Sopenharmony_ci} 3617141cc406Sopenharmony_ci 3618141cc406Sopenharmony_ci/* 3619141cc406Sopenharmony_ci * 3620141cc406Sopenharmony_ci * 3621141cc406Sopenharmony_ci */ 3622141cc406Sopenharmony_ci 3623141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 3624141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 3625141cc406Sopenharmony_ci{ 3626141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 3627141cc406Sopenharmony_ci 3628141cc406Sopenharmony_ci if (option < 0 || option >= NUM_OPTIONS) 3629141cc406Sopenharmony_ci return NULL; 3630141cc406Sopenharmony_ci 3631141cc406Sopenharmony_ci return (s->opt + option); 3632141cc406Sopenharmony_ci} 3633141cc406Sopenharmony_ci 3634141cc406Sopenharmony_ci/* 3635141cc406Sopenharmony_ci * 3636141cc406Sopenharmony_ci * 3637141cc406Sopenharmony_ci */ 3638141cc406Sopenharmony_ci 3639141cc406Sopenharmony_cistatic const SANE_String_Const * 3640141cc406Sopenharmony_cisearch_string_list (const SANE_String_Const * list, SANE_String value) 3641141cc406Sopenharmony_ci{ 3642141cc406Sopenharmony_ci while (*list != NULL && strcmp (value, *list) != 0) 3643141cc406Sopenharmony_ci { 3644141cc406Sopenharmony_ci ++list; 3645141cc406Sopenharmony_ci } 3646141cc406Sopenharmony_ci 3647141cc406Sopenharmony_ci return ((*list == NULL) ? NULL : list); 3648141cc406Sopenharmony_ci} 3649141cc406Sopenharmony_ci 3650141cc406Sopenharmony_ci/* 3651141cc406Sopenharmony_ci * 3652141cc406Sopenharmony_ci * 3653141cc406Sopenharmony_ci */ 3654141cc406Sopenharmony_ci 3655141cc406Sopenharmony_ci/* 3656141cc406Sopenharmony_ci Activate, deactivate an option. Subroutines so we can add 3657141cc406Sopenharmony_ci debugging info if we want. The change flag is set to TRUE 3658141cc406Sopenharmony_ci if we changed an option. If we did not change an option, 3659141cc406Sopenharmony_ci then the value of the changed flag is not modified. 3660141cc406Sopenharmony_ci*/ 3661141cc406Sopenharmony_ci 3662141cc406Sopenharmony_cistatic void 3663141cc406Sopenharmony_ciactivateOption (Epson_Scanner * s, SANE_Int option, SANE_Bool * change) 3664141cc406Sopenharmony_ci{ 3665141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) 3666141cc406Sopenharmony_ci { 3667141cc406Sopenharmony_ci s->opt[option].cap &= ~SANE_CAP_INACTIVE; 3668141cc406Sopenharmony_ci *change = SANE_TRUE; 3669141cc406Sopenharmony_ci } 3670141cc406Sopenharmony_ci} 3671141cc406Sopenharmony_ci 3672141cc406Sopenharmony_cistatic void 3673141cc406Sopenharmony_cideactivateOption (Epson_Scanner * s, SANE_Int option, SANE_Bool * change) 3674141cc406Sopenharmony_ci{ 3675141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) 3676141cc406Sopenharmony_ci { 3677141cc406Sopenharmony_ci s->opt[option].cap |= SANE_CAP_INACTIVE; 3678141cc406Sopenharmony_ci *change = SANE_TRUE; 3679141cc406Sopenharmony_ci } 3680141cc406Sopenharmony_ci} 3681141cc406Sopenharmony_ci 3682141cc406Sopenharmony_cistatic void 3683141cc406Sopenharmony_cisetOptionState (Epson_Scanner * s, SANE_Bool state, 3684141cc406Sopenharmony_ci SANE_Int option, SANE_Bool * change) 3685141cc406Sopenharmony_ci{ 3686141cc406Sopenharmony_ci if (state) 3687141cc406Sopenharmony_ci { 3688141cc406Sopenharmony_ci activateOption (s, option, change); 3689141cc406Sopenharmony_ci } 3690141cc406Sopenharmony_ci else 3691141cc406Sopenharmony_ci { 3692141cc406Sopenharmony_ci deactivateOption (s, option, change); 3693141cc406Sopenharmony_ci } 3694141cc406Sopenharmony_ci} 3695141cc406Sopenharmony_ci 3696141cc406Sopenharmony_ci/** 3697141cc406Sopenharmony_ci End of activateOption, deactivateOption, setOptionState. 3698141cc406Sopenharmony_ci**/ 3699141cc406Sopenharmony_ci 3700141cc406Sopenharmony_cistatic SANE_Status 3701141cc406Sopenharmony_cigetvalue (SANE_Handle handle, SANE_Int option, void *value) 3702141cc406Sopenharmony_ci{ 3703141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 3704141cc406Sopenharmony_ci SANE_Option_Descriptor *sopt = &(s->opt[option]); 3705141cc406Sopenharmony_ci Option_Value *sval = &(s->val[option]); 3706141cc406Sopenharmony_ci 3707141cc406Sopenharmony_ci switch (option) 3708141cc406Sopenharmony_ci { 3709141cc406Sopenharmony_ci/* case OPT_GAMMA_VECTOR: */ 3710141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3711141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3712141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3713141cc406Sopenharmony_ci memcpy (value, sval->wa, sopt->size); 3714141cc406Sopenharmony_ci break; 3715141cc406Sopenharmony_ci 3716141cc406Sopenharmony_ci case OPT_NUM_OPTS: 3717141cc406Sopenharmony_ci case OPT_RESOLUTION: 3718141cc406Sopenharmony_ci case OPT_TL_X: 3719141cc406Sopenharmony_ci case OPT_TL_Y: 3720141cc406Sopenharmony_ci case OPT_BR_X: 3721141cc406Sopenharmony_ci case OPT_BR_Y: 3722141cc406Sopenharmony_ci case OPT_MIRROR: 3723141cc406Sopenharmony_ci case OPT_SPEED: 3724141cc406Sopenharmony_ci case OPT_PREVIEW_SPEED: 3725141cc406Sopenharmony_ci case OPT_AAS: 3726141cc406Sopenharmony_ci case OPT_PREVIEW: 3727141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3728141cc406Sopenharmony_ci case OPT_SHARPNESS: 3729141cc406Sopenharmony_ci case OPT_AUTO_EJECT: 3730141cc406Sopenharmony_ci case OPT_CCT_1: 3731141cc406Sopenharmony_ci case OPT_CCT_2: 3732141cc406Sopenharmony_ci case OPT_CCT_3: 3733141cc406Sopenharmony_ci case OPT_CCT_4: 3734141cc406Sopenharmony_ci case OPT_CCT_5: 3735141cc406Sopenharmony_ci case OPT_CCT_6: 3736141cc406Sopenharmony_ci case OPT_CCT_7: 3737141cc406Sopenharmony_ci case OPT_CCT_8: 3738141cc406Sopenharmony_ci case OPT_CCT_9: 3739141cc406Sopenharmony_ci case OPT_THRESHOLD: 3740141cc406Sopenharmony_ci case OPT_ZOOM: 3741141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 3742141cc406Sopenharmony_ci case OPT_WAIT_FOR_BUTTON: 3743141cc406Sopenharmony_ci case OPT_LIMIT_RESOLUTION: 3744141cc406Sopenharmony_ci *((SANE_Word *) value) = sval->w; 3745141cc406Sopenharmony_ci break; 3746141cc406Sopenharmony_ci case OPT_MODE: 3747141cc406Sopenharmony_ci case OPT_ADF_MODE: 3748141cc406Sopenharmony_ci case OPT_HALFTONE: 3749141cc406Sopenharmony_ci case OPT_DROPOUT: 3750141cc406Sopenharmony_ci case OPT_QUICK_FORMAT: 3751141cc406Sopenharmony_ci case OPT_SOURCE: 3752141cc406Sopenharmony_ci case OPT_FILM_TYPE: 3753141cc406Sopenharmony_ci case OPT_GAMMA_CORRECTION: 3754141cc406Sopenharmony_ci case OPT_COLOR_CORRECTION: 3755141cc406Sopenharmony_ci case OPT_BAY: 3756141cc406Sopenharmony_ci case OPT_FOCUS: 3757141cc406Sopenharmony_ci strcpy ((char *) value, sopt->constraint.string_list[sval->w]); 3758141cc406Sopenharmony_ci break; 3759141cc406Sopenharmony_ci#if 0 3760141cc406Sopenharmony_ci case OPT_MODEL: 3761141cc406Sopenharmony_ci strcpy (value, sval->s); 3762141cc406Sopenharmony_ci break; 3763141cc406Sopenharmony_ci#endif 3764141cc406Sopenharmony_ci 3765141cc406Sopenharmony_ci 3766141cc406Sopenharmony_ci default: 3767141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3768141cc406Sopenharmony_ci 3769141cc406Sopenharmony_ci } 3770141cc406Sopenharmony_ci 3771141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3772141cc406Sopenharmony_ci} 3773141cc406Sopenharmony_ci 3774141cc406Sopenharmony_ci 3775141cc406Sopenharmony_ci/** 3776141cc406Sopenharmony_ci End of getvalue. 3777141cc406Sopenharmony_ci**/ 3778141cc406Sopenharmony_ci 3779141cc406Sopenharmony_ci 3780141cc406Sopenharmony_cistatic void 3781141cc406Sopenharmony_cihandle_depth_halftone (Epson_Scanner * s, SANE_Bool * reload) 3782141cc406Sopenharmony_ci/* 3783141cc406Sopenharmony_ci This routine handles common options between OPT_MODE and 3784141cc406Sopenharmony_ci OPT_HALFTONE. These options are TET (a HALFTONE mode), AAS 3785141cc406Sopenharmony_ci - auto area segmentation, and threshold. Apparently AAS 3786141cc406Sopenharmony_ci is some method to differentiate between text and photos. 3787141cc406Sopenharmony_ci Or something like that. 3788141cc406Sopenharmony_ci 3789141cc406Sopenharmony_ci AAS is available when the scan color depth is 1 and the 3790141cc406Sopenharmony_ci halftone method is not TET. 3791141cc406Sopenharmony_ci 3792141cc406Sopenharmony_ci Threshold is available when halftone is NONE, and depth is 1. 3793141cc406Sopenharmony_ci*/ 3794141cc406Sopenharmony_ci{ 3795141cc406Sopenharmony_ci int hti = s->val[OPT_HALFTONE].w; 3796141cc406Sopenharmony_ci int mdi = s->val[OPT_MODE].w; 3797141cc406Sopenharmony_ci SANE_Bool aas = SANE_FALSE; 3798141cc406Sopenharmony_ci SANE_Bool thresh = SANE_FALSE; 3799141cc406Sopenharmony_ci 3800141cc406Sopenharmony_ci if (!s->hw->cmd->control_auto_area_segmentation) 3801141cc406Sopenharmony_ci return; 3802141cc406Sopenharmony_ci 3803141cc406Sopenharmony_ci if (mode_params[mdi].depth == 1) 3804141cc406Sopenharmony_ci { 3805141cc406Sopenharmony_ci if (halftone_params[hti] != HALFTONE_TET) 3806141cc406Sopenharmony_ci { 3807141cc406Sopenharmony_ci aas = SANE_TRUE; 3808141cc406Sopenharmony_ci } 3809141cc406Sopenharmony_ci if (halftone_params[hti] == HALFTONE_NONE) 3810141cc406Sopenharmony_ci { 3811141cc406Sopenharmony_ci thresh = SANE_TRUE; 3812141cc406Sopenharmony_ci } 3813141cc406Sopenharmony_ci } 3814141cc406Sopenharmony_ci setOptionState (s, aas, OPT_AAS, reload); 3815141cc406Sopenharmony_ci setOptionState (s, thresh, OPT_THRESHOLD, reload); 3816141cc406Sopenharmony_ci} 3817141cc406Sopenharmony_ci 3818141cc406Sopenharmony_ci/** 3819141cc406Sopenharmony_ci End of handle_depth_halftone. 3820141cc406Sopenharmony_ci**/ 3821141cc406Sopenharmony_ci 3822141cc406Sopenharmony_ci 3823141cc406Sopenharmony_cistatic void 3824141cc406Sopenharmony_cihandle_source (Epson_Scanner * s, SANE_Int optindex, char *value) 3825141cc406Sopenharmony_ci/* 3826141cc406Sopenharmony_ci Handles setting the source (flatbed, transparency adapter (TPU), 3827141cc406Sopenharmony_ci or auto document feeder (ADF)). 3828141cc406Sopenharmony_ci 3829141cc406Sopenharmony_ci For newer scanners it also sets the focus according to the 3830141cc406Sopenharmony_ci glass / TPU settings. 3831141cc406Sopenharmony_ci*/ 3832141cc406Sopenharmony_ci{ 3833141cc406Sopenharmony_ci int force_max = SANE_FALSE; 3834141cc406Sopenharmony_ci SANE_Bool dummy; 3835141cc406Sopenharmony_ci 3836141cc406Sopenharmony_ci /* reset the scanner when we are changing the source setting - 3837141cc406Sopenharmony_ci this is necessary for the Perfection 1650 */ 3838141cc406Sopenharmony_ci if (s->hw->need_reset_on_source_change) 3839141cc406Sopenharmony_ci reset (s); 3840141cc406Sopenharmony_ci 3841141cc406Sopenharmony_ci s->focusOnGlass = SANE_TRUE; /* this is the default */ 3842141cc406Sopenharmony_ci 3843141cc406Sopenharmony_ci if (s->val[OPT_SOURCE].w == optindex) 3844141cc406Sopenharmony_ci return; 3845141cc406Sopenharmony_ci 3846141cc406Sopenharmony_ci s->val[OPT_SOURCE].w = optindex; 3847141cc406Sopenharmony_ci 3848141cc406Sopenharmony_ci if (s->val[OPT_TL_X].w == s->hw->x_range->min 3849141cc406Sopenharmony_ci && s->val[OPT_TL_Y].w == s->hw->y_range->min 3850141cc406Sopenharmony_ci && s->val[OPT_BR_X].w == s->hw->x_range->max 3851141cc406Sopenharmony_ci && s->val[OPT_BR_Y].w == s->hw->y_range->max) 3852141cc406Sopenharmony_ci { 3853141cc406Sopenharmony_ci force_max = SANE_TRUE; 3854141cc406Sopenharmony_ci } 3855141cc406Sopenharmony_ci if (strcmp (ADF_STR, value) == 0) 3856141cc406Sopenharmony_ci { 3857141cc406Sopenharmony_ci s->hw->x_range = &s->hw->adf_x_range; 3858141cc406Sopenharmony_ci s->hw->y_range = &s->hw->adf_y_range; 3859141cc406Sopenharmony_ci s->hw->use_extension = SANE_TRUE; 3860141cc406Sopenharmony_ci /* disable film type option */ 3861141cc406Sopenharmony_ci deactivateOption (s, OPT_FILM_TYPE, &dummy); 3862141cc406Sopenharmony_ci s->val[OPT_FOCUS].w = 0; 3863141cc406Sopenharmony_ci if (s->hw->duplexSupport) 3864141cc406Sopenharmony_ci { 3865141cc406Sopenharmony_ci activateOption (s, OPT_ADF_MODE, &dummy); 3866141cc406Sopenharmony_ci } 3867141cc406Sopenharmony_ci else 3868141cc406Sopenharmony_ci { 3869141cc406Sopenharmony_ci deactivateOption (s, OPT_ADF_MODE, &dummy); 3870141cc406Sopenharmony_ci s->val[OPT_ADF_MODE].w = 0; 3871141cc406Sopenharmony_ci } 3872141cc406Sopenharmony_ci } 3873141cc406Sopenharmony_ci else if (strcmp (TPU_STR, value) == 0) 3874141cc406Sopenharmony_ci { 3875141cc406Sopenharmony_ci s->hw->x_range = &s->hw->tpu_x_range; 3876141cc406Sopenharmony_ci s->hw->y_range = &s->hw->tpu_y_range; 3877141cc406Sopenharmony_ci s->hw->use_extension = SANE_TRUE; 3878141cc406Sopenharmony_ci /* enable film type option only if the scanner supports it */ 3879141cc406Sopenharmony_ci if (s->hw->cmd->set_film_type != 0) 3880141cc406Sopenharmony_ci { 3881141cc406Sopenharmony_ci activateOption (s, OPT_FILM_TYPE, &dummy); 3882141cc406Sopenharmony_ci } 3883141cc406Sopenharmony_ci else 3884141cc406Sopenharmony_ci { 3885141cc406Sopenharmony_ci deactivateOption (s, OPT_FILM_TYPE, &dummy); 3886141cc406Sopenharmony_ci } 3887141cc406Sopenharmony_ci /* enable focus position if the scanner supports it */ 3888141cc406Sopenharmony_ci if (s->hw->cmd->set_focus_position != 0) 3889141cc406Sopenharmony_ci { 3890141cc406Sopenharmony_ci s->val[OPT_FOCUS].w = 1; 3891141cc406Sopenharmony_ci s->focusOnGlass = SANE_FALSE; 3892141cc406Sopenharmony_ci } 3893141cc406Sopenharmony_ci deactivateOption (s, OPT_ADF_MODE, &dummy); 3894141cc406Sopenharmony_ci deactivateOption (s, OPT_EJECT, &dummy); 3895141cc406Sopenharmony_ci deactivateOption (s, OPT_AUTO_EJECT, &dummy); 3896141cc406Sopenharmony_ci } 3897141cc406Sopenharmony_ci else /* neither ADF nor TPU active */ 3898141cc406Sopenharmony_ci { 3899141cc406Sopenharmony_ci s->hw->x_range = &s->hw->fbf_x_range; 3900141cc406Sopenharmony_ci s->hw->y_range = &s->hw->fbf_y_range; 3901141cc406Sopenharmony_ci s->hw->use_extension = SANE_FALSE; 3902141cc406Sopenharmony_ci /* disable film type option */ 3903141cc406Sopenharmony_ci deactivateOption (s, OPT_FILM_TYPE, &dummy); 3904141cc406Sopenharmony_ci s->val[OPT_FOCUS].w = 0; 3905141cc406Sopenharmony_ci deactivateOption (s, OPT_ADF_MODE, &dummy); 3906141cc406Sopenharmony_ci } 3907141cc406Sopenharmony_ci 3908141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].tl_x = s->hw->x_range->min; 3909141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].tl_y = s->hw->y_range->min; 3910141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].br_x = s->hw->x_range->max; 3911141cc406Sopenharmony_ci qf_params[XtNumber (qf_params) - 1].br_y = s->hw->y_range->max; 3912141cc406Sopenharmony_ci 3913141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = s->hw->x_range; 3914141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; 3915141cc406Sopenharmony_ci 3916141cc406Sopenharmony_ci if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max) 3917141cc406Sopenharmony_ci s->val[OPT_TL_X].w = s->hw->x_range->min; 3918141cc406Sopenharmony_ci 3919141cc406Sopenharmony_ci if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max) 3920141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = s->hw->y_range->min; 3921141cc406Sopenharmony_ci 3922141cc406Sopenharmony_ci if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max) 3923141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->x_range->max; 3924141cc406Sopenharmony_ci 3925141cc406Sopenharmony_ci if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max) 3926141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->y_range->max; 3927141cc406Sopenharmony_ci 3928141cc406Sopenharmony_ci setOptionState (s, s->hw->ADF && s->hw->use_extension, 3929141cc406Sopenharmony_ci OPT_AUTO_EJECT, &dummy); 3930141cc406Sopenharmony_ci setOptionState (s, s->hw->ADF && s->hw->use_extension, OPT_EJECT, &dummy); 3931141cc406Sopenharmony_ci 3932141cc406Sopenharmony_ci#if 0 3933141cc406Sopenharmony_ci BAY is part of the filmscan device.We are not sure 3934141cc406Sopenharmony_ci if we are really going to support this device in this 3935141cc406Sopenharmony_ci code.Is there an online manual for it ? 3936141cc406Sopenharmony_ci setOptionState (s, s->hw->ADF && s->hw->use_extension, OPT_BAY, &reload); 3937141cc406Sopenharmony_ci#endif 3938141cc406Sopenharmony_ci} 3939141cc406Sopenharmony_ci 3940141cc406Sopenharmony_ci/** 3941141cc406Sopenharmony_ci End of handle_source. 3942141cc406Sopenharmony_ci**/ 3943141cc406Sopenharmony_ci 3944141cc406Sopenharmony_cistatic SANE_Status 3945141cc406Sopenharmony_cisetvalue (SANE_Handle handle, SANE_Int option, void *value, SANE_Int * info) 3946141cc406Sopenharmony_ci{ 3947141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 3948141cc406Sopenharmony_ci SANE_Option_Descriptor *sopt = &(s->opt[option]); 3949141cc406Sopenharmony_ci Option_Value *sval = &(s->val[option]); 3950141cc406Sopenharmony_ci 3951141cc406Sopenharmony_ci SANE_Status status; 3952141cc406Sopenharmony_ci const SANE_String_Const *optval; 3953141cc406Sopenharmony_ci int optindex; 3954141cc406Sopenharmony_ci SANE_Bool reload = SANE_FALSE; 3955141cc406Sopenharmony_ci 3956141cc406Sopenharmony_ci DBG (5, "setvalue(option = %d, value = %p)\n", option, value); 3957141cc406Sopenharmony_ci 3958141cc406Sopenharmony_ci status = sanei_constrain_value (sopt, value, info); 3959141cc406Sopenharmony_ci 3960141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3961141cc406Sopenharmony_ci return status; 3962141cc406Sopenharmony_ci 3963141cc406Sopenharmony_ci s->option_has_changed = SANE_TRUE; 3964141cc406Sopenharmony_ci 3965141cc406Sopenharmony_ci optval = NULL; 3966141cc406Sopenharmony_ci optindex = 0; 3967141cc406Sopenharmony_ci 3968141cc406Sopenharmony_ci if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) 3969141cc406Sopenharmony_ci { 3970141cc406Sopenharmony_ci optval = search_string_list (sopt->constraint.string_list, 3971141cc406Sopenharmony_ci (char *) value); 3972141cc406Sopenharmony_ci 3973141cc406Sopenharmony_ci if (optval == NULL) 3974141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3975141cc406Sopenharmony_ci optindex = optval - sopt->constraint.string_list; 3976141cc406Sopenharmony_ci } 3977141cc406Sopenharmony_ci 3978141cc406Sopenharmony_ci switch (option) 3979141cc406Sopenharmony_ci { 3980141cc406Sopenharmony_ci/* case OPT_GAMMA_VECTOR: */ 3981141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3982141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3983141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3984141cc406Sopenharmony_ci memcpy (sval->wa, value, sopt->size); /* Word arrays */ 3985141cc406Sopenharmony_ci break; 3986141cc406Sopenharmony_ci 3987141cc406Sopenharmony_ci case OPT_CCT_1: 3988141cc406Sopenharmony_ci case OPT_CCT_2: 3989141cc406Sopenharmony_ci case OPT_CCT_3: 3990141cc406Sopenharmony_ci case OPT_CCT_4: 3991141cc406Sopenharmony_ci case OPT_CCT_5: 3992141cc406Sopenharmony_ci case OPT_CCT_6: 3993141cc406Sopenharmony_ci case OPT_CCT_7: 3994141cc406Sopenharmony_ci case OPT_CCT_8: 3995141cc406Sopenharmony_ci case OPT_CCT_9: 3996141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); /* Simple values */ 3997141cc406Sopenharmony_ci break; 3998141cc406Sopenharmony_ci 3999141cc406Sopenharmony_ci case OPT_DROPOUT: 4000141cc406Sopenharmony_ci case OPT_FILM_TYPE: 4001141cc406Sopenharmony_ci case OPT_BAY: 4002141cc406Sopenharmony_ci case OPT_FOCUS: 4003141cc406Sopenharmony_ci sval->w = optindex; /* Simple lists */ 4004141cc406Sopenharmony_ci break; 4005141cc406Sopenharmony_ci 4006141cc406Sopenharmony_ci case OPT_EJECT: 4007141cc406Sopenharmony_ci/* return eject( s ); */ 4008141cc406Sopenharmony_ci eject (s); 4009141cc406Sopenharmony_ci break; 4010141cc406Sopenharmony_ci 4011141cc406Sopenharmony_ci case OPT_RESOLUTION: 4012141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 4013141cc406Sopenharmony_ci reload = SANE_TRUE; 4014141cc406Sopenharmony_ci break; 4015141cc406Sopenharmony_ci 4016141cc406Sopenharmony_ci case OPT_TL_X: 4017141cc406Sopenharmony_ci case OPT_TL_Y: 4018141cc406Sopenharmony_ci case OPT_BR_X: 4019141cc406Sopenharmony_ci case OPT_BR_Y: 4020141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 4021141cc406Sopenharmony_ci DBG (1, "set = %f\n", SANE_UNFIX (sval->w)); 4022141cc406Sopenharmony_ci if (NULL != info) 4023141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 4024141cc406Sopenharmony_ci break; 4025141cc406Sopenharmony_ci 4026141cc406Sopenharmony_ci case OPT_SOURCE: 4027141cc406Sopenharmony_ci handle_source (s, optindex, (char *) value); 4028141cc406Sopenharmony_ci reload = SANE_TRUE; 4029141cc406Sopenharmony_ci break; 4030141cc406Sopenharmony_ci 4031141cc406Sopenharmony_ci case OPT_MODE: 4032141cc406Sopenharmony_ci { 4033141cc406Sopenharmony_ci SANE_Bool isColor = mode_params[optindex].color; 4034141cc406Sopenharmony_ci SANE_Bool userDefined = 4035141cc406Sopenharmony_ci color_userdefined[s->val[OPT_COLOR_CORRECTION].w]; 4036141cc406Sopenharmony_ci 4037141cc406Sopenharmony_ci sval->w = optindex; 4038141cc406Sopenharmony_ci 4039141cc406Sopenharmony_ci if (s->hw->cmd->set_halftoning != 0) 4040141cc406Sopenharmony_ci { 4041141cc406Sopenharmony_ci setOptionState (s, mode_params[optindex].depth == 1, 4042141cc406Sopenharmony_ci OPT_HALFTONE, &reload); 4043141cc406Sopenharmony_ci } 4044141cc406Sopenharmony_ci 4045141cc406Sopenharmony_ci setOptionState (s, !isColor, OPT_DROPOUT, &reload); 4046141cc406Sopenharmony_ci if (s->hw->cmd->set_color_correction) 4047141cc406Sopenharmony_ci { 4048141cc406Sopenharmony_ci setOptionState (s, isColor, OPT_COLOR_CORRECTION, &reload); 4049141cc406Sopenharmony_ci } 4050141cc406Sopenharmony_ci if (s->hw->cmd->set_color_correction_coefficients) 4051141cc406Sopenharmony_ci { 4052141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_1, &reload); 4053141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_2, &reload); 4054141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_3, &reload); 4055141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_4, &reload); 4056141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_5, &reload); 4057141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_6, &reload); 4058141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_7, &reload); 4059141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_8, &reload); 4060141cc406Sopenharmony_ci setOptionState (s, isColor && userDefined, OPT_CCT_9, &reload); 4061141cc406Sopenharmony_ci } 4062141cc406Sopenharmony_ci 4063141cc406Sopenharmony_ci /* if binary, then disable the bit depth selection */ 4064141cc406Sopenharmony_ci if (optindex == 0) 4065141cc406Sopenharmony_ci { 4066141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; 4067141cc406Sopenharmony_ci } 4068141cc406Sopenharmony_ci else 4069141cc406Sopenharmony_ci { 4070141cc406Sopenharmony_ci if (bitDepthList[0] == 1) 4071141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; 4072141cc406Sopenharmony_ci else 4073141cc406Sopenharmony_ci { 4074141cc406Sopenharmony_ci s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; 4075141cc406Sopenharmony_ci s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth; 4076141cc406Sopenharmony_ci } 4077141cc406Sopenharmony_ci } 4078141cc406Sopenharmony_ci 4079141cc406Sopenharmony_ci handle_depth_halftone (s, &reload); 4080141cc406Sopenharmony_ci reload = SANE_TRUE; 4081141cc406Sopenharmony_ci 4082141cc406Sopenharmony_ci break; 4083141cc406Sopenharmony_ci } 4084141cc406Sopenharmony_ci 4085141cc406Sopenharmony_ci case OPT_ADF_MODE: 4086141cc406Sopenharmony_ci sval->w = optindex; 4087141cc406Sopenharmony_ci break; 4088141cc406Sopenharmony_ci 4089141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 4090141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 4091141cc406Sopenharmony_ci mode_params[s->val[OPT_MODE].w].depth = sval->w; 4092141cc406Sopenharmony_ci reload = SANE_TRUE; 4093141cc406Sopenharmony_ci break; 4094141cc406Sopenharmony_ci 4095141cc406Sopenharmony_ci case OPT_HALFTONE: 4096141cc406Sopenharmony_ci sval->w = optindex; 4097141cc406Sopenharmony_ci handle_depth_halftone (s, &reload); 4098141cc406Sopenharmony_ci break; 4099141cc406Sopenharmony_ci 4100141cc406Sopenharmony_ci case OPT_COLOR_CORRECTION: 4101141cc406Sopenharmony_ci { 4102141cc406Sopenharmony_ci SANE_Bool f = color_userdefined[optindex]; 4103141cc406Sopenharmony_ci 4104141cc406Sopenharmony_ci sval->w = optindex; 4105141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_1, &reload); 4106141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_2, &reload); 4107141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_3, &reload); 4108141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_4, &reload); 4109141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_5, &reload); 4110141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_6, &reload); 4111141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_7, &reload); 4112141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_8, &reload); 4113141cc406Sopenharmony_ci setOptionState (s, f, OPT_CCT_9, &reload); 4114141cc406Sopenharmony_ci 4115141cc406Sopenharmony_ci break; 4116141cc406Sopenharmony_ci } 4117141cc406Sopenharmony_ci 4118141cc406Sopenharmony_ci case OPT_GAMMA_CORRECTION: 4119141cc406Sopenharmony_ci { 4120141cc406Sopenharmony_ci SANE_Bool f = gamma_userdefined[optindex]; 4121141cc406Sopenharmony_ci 4122141cc406Sopenharmony_ci sval->w = optindex; 4123141cc406Sopenharmony_ci/* setOptionState(s, f, OPT_GAMMA_VECTOR, &reload ); */ 4124141cc406Sopenharmony_ci setOptionState (s, f, OPT_GAMMA_VECTOR_R, &reload); 4125141cc406Sopenharmony_ci setOptionState (s, f, OPT_GAMMA_VECTOR_G, &reload); 4126141cc406Sopenharmony_ci setOptionState (s, f, OPT_GAMMA_VECTOR_B, &reload); 4127141cc406Sopenharmony_ci setOptionState (s, !f, OPT_BRIGHTNESS, &reload); /* Note... */ 4128141cc406Sopenharmony_ci 4129141cc406Sopenharmony_ci break; 4130141cc406Sopenharmony_ci } 4131141cc406Sopenharmony_ci 4132141cc406Sopenharmony_ci case OPT_MIRROR: 4133141cc406Sopenharmony_ci case OPT_SPEED: 4134141cc406Sopenharmony_ci case OPT_PREVIEW_SPEED: 4135141cc406Sopenharmony_ci case OPT_AAS: 4136141cc406Sopenharmony_ci case OPT_PREVIEW: /* needed? */ 4137141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 4138141cc406Sopenharmony_ci case OPT_SHARPNESS: 4139141cc406Sopenharmony_ci case OPT_AUTO_EJECT: 4140141cc406Sopenharmony_ci case OPT_THRESHOLD: 4141141cc406Sopenharmony_ci case OPT_ZOOM: 4142141cc406Sopenharmony_ci case OPT_WAIT_FOR_BUTTON: 4143141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 4144141cc406Sopenharmony_ci break; 4145141cc406Sopenharmony_ci 4146141cc406Sopenharmony_ci case OPT_LIMIT_RESOLUTION: 4147141cc406Sopenharmony_ci sval->w = *((SANE_Word *) value); 4148141cc406Sopenharmony_ci filter_resolution_list (s); 4149141cc406Sopenharmony_ci reload = SANE_TRUE; 4150141cc406Sopenharmony_ci break; 4151141cc406Sopenharmony_ci 4152141cc406Sopenharmony_ci case OPT_QUICK_FORMAT: 4153141cc406Sopenharmony_ci sval->w = optindex; 4154141cc406Sopenharmony_ci 4155141cc406Sopenharmony_ci s->val[OPT_TL_X].w = qf_params[sval->w].tl_x; 4156141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = qf_params[sval->w].tl_y; 4157141cc406Sopenharmony_ci s->val[OPT_BR_X].w = qf_params[sval->w].br_x; 4158141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = qf_params[sval->w].br_y; 4159141cc406Sopenharmony_ci 4160141cc406Sopenharmony_ci if (s->val[OPT_TL_X].w < s->hw->x_range->min) 4161141cc406Sopenharmony_ci s->val[OPT_TL_X].w = s->hw->x_range->min; 4162141cc406Sopenharmony_ci 4163141cc406Sopenharmony_ci if (s->val[OPT_TL_Y].w < s->hw->y_range->min) 4164141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = s->hw->y_range->min; 4165141cc406Sopenharmony_ci 4166141cc406Sopenharmony_ci if (s->val[OPT_BR_X].w > s->hw->x_range->max) 4167141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->x_range->max; 4168141cc406Sopenharmony_ci 4169141cc406Sopenharmony_ci if (s->val[OPT_BR_Y].w > s->hw->y_range->max) 4170141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->y_range->max; 4171141cc406Sopenharmony_ci 4172141cc406Sopenharmony_ci reload = SANE_TRUE; 4173141cc406Sopenharmony_ci break; 4174141cc406Sopenharmony_ci 4175141cc406Sopenharmony_ci default: 4176141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4177141cc406Sopenharmony_ci } 4178141cc406Sopenharmony_ci 4179141cc406Sopenharmony_ci if (reload && info != NULL) 4180141cc406Sopenharmony_ci { 4181141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 4182141cc406Sopenharmony_ci } 4183141cc406Sopenharmony_ci 4184141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4185141cc406Sopenharmony_ci} 4186141cc406Sopenharmony_ci 4187141cc406Sopenharmony_ci/** 4188141cc406Sopenharmony_ci End of setvalue. 4189141cc406Sopenharmony_ci**/ 4190141cc406Sopenharmony_ci 4191141cc406Sopenharmony_ciSANE_Status 4192141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, 4193141cc406Sopenharmony_ci SANE_Int option, 4194141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int * info) 4195141cc406Sopenharmony_ci{ 4196141cc406Sopenharmony_ci if (option < 0 || option >= NUM_OPTIONS) 4197141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4198141cc406Sopenharmony_ci 4199141cc406Sopenharmony_ci if (info != NULL) 4200141cc406Sopenharmony_ci *info = 0; 4201141cc406Sopenharmony_ci 4202141cc406Sopenharmony_ci switch (action) 4203141cc406Sopenharmony_ci { 4204141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 4205141cc406Sopenharmony_ci return (getvalue (handle, option, value)); 4206141cc406Sopenharmony_ci 4207141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 4208141cc406Sopenharmony_ci return (setvalue (handle, option, value, info)); 4209141cc406Sopenharmony_ci default: 4210141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4211141cc406Sopenharmony_ci } 4212141cc406Sopenharmony_ci 4213141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4214141cc406Sopenharmony_ci} 4215141cc406Sopenharmony_ci 4216141cc406Sopenharmony_ci/* 4217141cc406Sopenharmony_ci * sane_get_parameters() 4218141cc406Sopenharmony_ci * 4219141cc406Sopenharmony_ci * This function is part of the SANE API and gets called when the front end 4220141cc406Sopenharmony_ci * requests information aobut the scan configuration (e.g. color depth, mode, 4221141cc406Sopenharmony_ci * bytes and pixels per line, number of lines. This information is returned 4222141cc406Sopenharmony_ci * in the SANE_Parameters structure. 4223141cc406Sopenharmony_ci * 4224141cc406Sopenharmony_ci * Once a scan was started, this routine has to report the correct values, if 4225141cc406Sopenharmony_ci * it is called before the scan is actually started, the values are based on 4226141cc406Sopenharmony_ci * the current settings. 4227141cc406Sopenharmony_ci * 4228141cc406Sopenharmony_ci */ 4229141cc406Sopenharmony_ciSANE_Status 4230141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 4231141cc406Sopenharmony_ci{ 4232141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 4233141cc406Sopenharmony_ci int ndpi; 4234141cc406Sopenharmony_ci int bytes_per_pixel; 4235141cc406Sopenharmony_ci 4236141cc406Sopenharmony_ci DBG (5, "sane_get_parameters()\n"); 4237141cc406Sopenharmony_ci 4238141cc406Sopenharmony_ci /* 4239141cc406Sopenharmony_ci * If sane_start was already called, then just retrieve the parameters 4240141cc406Sopenharmony_ci * from the scanner data structure 4241141cc406Sopenharmony_ci */ 4242141cc406Sopenharmony_ci 4243141cc406Sopenharmony_ci if (!s->eof && s->ptr != NULL) 4244141cc406Sopenharmony_ci { 4245141cc406Sopenharmony_ci DBG (5, "Returning saved params structure\n"); 4246141cc406Sopenharmony_ci if (params != NULL) 4247141cc406Sopenharmony_ci { 4248141cc406Sopenharmony_ci DBG(1, "Restoring parameters from saved parameters\n"); 4249141cc406Sopenharmony_ci *params = s->params; 4250141cc406Sopenharmony_ci } 4251141cc406Sopenharmony_ci 4252141cc406Sopenharmony_ci DBG (3, "Preview = %d\n", s->val[OPT_PREVIEW].w); 4253141cc406Sopenharmony_ci DBG (3, "Resolution = %d\n", s->val[OPT_RESOLUTION].w); 4254141cc406Sopenharmony_ci 4255141cc406Sopenharmony_ci DBG (1, "get para %p %p tlx %f tly %f brx %f bry %f [mm]\n", (void *) s, 4256141cc406Sopenharmony_ci (void *) s->val, SANE_UNFIX (s->val[OPT_TL_X].w), 4257141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_TL_Y].w), SANE_UNFIX (s->val[OPT_BR_X].w), 4258141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_BR_Y].w)); 4259141cc406Sopenharmony_ci 4260141cc406Sopenharmony_ci print_params (s->params); 4261141cc406Sopenharmony_ci 4262141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4263141cc406Sopenharmony_ci } 4264141cc406Sopenharmony_ci 4265141cc406Sopenharmony_ci /* otherwise initialize the params structure and gather the data */ 4266141cc406Sopenharmony_ci 4267141cc406Sopenharmony_ci memset (&s->params, 0, sizeof (SANE_Parameters)); 4268141cc406Sopenharmony_ci 4269141cc406Sopenharmony_ci ndpi = s->val[OPT_RESOLUTION].w; 4270141cc406Sopenharmony_ci 4271141cc406Sopenharmony_ci s->params.pixels_per_line = 4272141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / 25.4 * ndpi + 0.5; 4273141cc406Sopenharmony_ci s->params.lines = 4274141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / 25.4 * ndpi + 0.5; 4275141cc406Sopenharmony_ci 4276141cc406Sopenharmony_ci /* 4277141cc406Sopenharmony_ci * Make sure that the number of lines is correct for color shuffling: 4278141cc406Sopenharmony_ci * The shuffling algorithm produces 2xline_distance lines at the 4279141cc406Sopenharmony_ci * beginning and the same amount at the end of the scan that are not 4280141cc406Sopenharmony_ci * useable. If s->params.lines gets negative, 0 lines are reported 4281141cc406Sopenharmony_ci * back to the frontend. 4282141cc406Sopenharmony_ci */ 4283141cc406Sopenharmony_ci if (s->hw->color_shuffle) 4284141cc406Sopenharmony_ci { 4285141cc406Sopenharmony_ci s->params.lines -= 4 * s->line_distance; 4286141cc406Sopenharmony_ci if (s->params.lines < 0) 4287141cc406Sopenharmony_ci { 4288141cc406Sopenharmony_ci s->params.lines = 0; 4289141cc406Sopenharmony_ci } 4290141cc406Sopenharmony_ci DBG (1, "Adjusted params.lines for color_shuffle by %d to %d\n", 4291141cc406Sopenharmony_ci 4 * s->line_distance, s->params.lines); 4292141cc406Sopenharmony_ci } 4293141cc406Sopenharmony_ci 4294141cc406Sopenharmony_ci DBG (3, "Preview = %d\n", s->val[OPT_PREVIEW].w); 4295141cc406Sopenharmony_ci DBG (3, "Resolution = %d\n", s->val[OPT_RESOLUTION].w); 4296141cc406Sopenharmony_ci 4297141cc406Sopenharmony_ci DBG (1, "get para %p %p tlx %f tly %f brx %f bry %f [mm]\n", (void *) s, 4298141cc406Sopenharmony_ci (void *) s->val, SANE_UNFIX (s->val[OPT_TL_X].w), 4299141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_TL_Y].w), SANE_UNFIX (s->val[OPT_BR_X].w), 4300141cc406Sopenharmony_ci SANE_UNFIX (s->val[OPT_BR_Y].w)); 4301141cc406Sopenharmony_ci 4302141cc406Sopenharmony_ci 4303141cc406Sopenharmony_ci /* 4304141cc406Sopenharmony_ci * Calculate bytes_per_pixel and bytes_per_line for 4305141cc406Sopenharmony_ci * any color depths. 4306141cc406Sopenharmony_ci * 4307141cc406Sopenharmony_ci * The default color depth is stored in mode_params.depth: 4308141cc406Sopenharmony_ci */ 4309141cc406Sopenharmony_ci 4310141cc406Sopenharmony_ci if (mode_params[s->val[OPT_MODE].w].depth == 1) 4311141cc406Sopenharmony_ci { 4312141cc406Sopenharmony_ci s->params.depth = 1; 4313141cc406Sopenharmony_ci } 4314141cc406Sopenharmony_ci else 4315141cc406Sopenharmony_ci { 4316141cc406Sopenharmony_ci s->params.depth = s->val[OPT_BIT_DEPTH].w; 4317141cc406Sopenharmony_ci } 4318141cc406Sopenharmony_ci 4319141cc406Sopenharmony_ci if (s->params.depth > 8) 4320141cc406Sopenharmony_ci { 4321141cc406Sopenharmony_ci s->params.depth = 16; /* 4322141cc406Sopenharmony_ci * The frontends can only handle 8 or 16 bits 4323141cc406Sopenharmony_ci * for gray or color - so if it's more than 8, 4324141cc406Sopenharmony_ci * it gets automatically set to 16. This works 4325141cc406Sopenharmony_ci * as long as EPSON does not come out with a 4326141cc406Sopenharmony_ci * scanner that can handle more than 16 bits 4327141cc406Sopenharmony_ci * per color channel. 4328141cc406Sopenharmony_ci */ 4329141cc406Sopenharmony_ci 4330141cc406Sopenharmony_ci } 4331141cc406Sopenharmony_ci 4332141cc406Sopenharmony_ci bytes_per_pixel = s->params.depth / 8; /* this works because it can only be set to 1, 8 or 16 */ 4333141cc406Sopenharmony_ci if (s->params.depth % 8) /* just in case ... */ 4334141cc406Sopenharmony_ci { 4335141cc406Sopenharmony_ci bytes_per_pixel++; 4336141cc406Sopenharmony_ci } 4337141cc406Sopenharmony_ci 4338141cc406Sopenharmony_ci /* pixels_per_line is rounded to the next 8bit boundary */ 4339141cc406Sopenharmony_ci s->params.pixels_per_line = s->params.pixels_per_line & ~7; 4340141cc406Sopenharmony_ci 4341141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 4342141cc406Sopenharmony_ci 4343141cc406Sopenharmony_ci if (mode_params[s->val[OPT_MODE].w].color) 4344141cc406Sopenharmony_ci { 4345141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RGB; 4346141cc406Sopenharmony_ci s->params.bytes_per_line = 4347141cc406Sopenharmony_ci 3 * s->params.pixels_per_line * bytes_per_pixel; 4348141cc406Sopenharmony_ci } 4349141cc406Sopenharmony_ci else 4350141cc406Sopenharmony_ci { 4351141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 4352141cc406Sopenharmony_ci s->params.bytes_per_line = 4353141cc406Sopenharmony_ci s->params.pixels_per_line * s->params.depth / 8; 4354141cc406Sopenharmony_ci } 4355141cc406Sopenharmony_ci 4356141cc406Sopenharmony_ci if (NULL != params) 4357141cc406Sopenharmony_ci *params = s->params; 4358141cc406Sopenharmony_ci 4359141cc406Sopenharmony_ci print_params (s->params); 4360141cc406Sopenharmony_ci 4361141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4362141cc406Sopenharmony_ci} 4363141cc406Sopenharmony_ci 4364141cc406Sopenharmony_ci/* 4365141cc406Sopenharmony_ci * sane_start() 4366141cc406Sopenharmony_ci * 4367141cc406Sopenharmony_ci * This function is part of the SANE API and gets called from the front end to 4368141cc406Sopenharmony_ci * start the scan process. 4369141cc406Sopenharmony_ci * 4370141cc406Sopenharmony_ci */ 4371141cc406Sopenharmony_ci 4372141cc406Sopenharmony_ciSANE_Status 4373141cc406Sopenharmony_cisane_start (SANE_Handle handle) 4374141cc406Sopenharmony_ci{ 4375141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 4376141cc406Sopenharmony_ci SANE_Status status; 4377141cc406Sopenharmony_ci SANE_Bool button_status; 4378141cc406Sopenharmony_ci const struct mode_param *mparam; 4379141cc406Sopenharmony_ci u_char params[4]; 4380141cc406Sopenharmony_ci int ndpi; 4381141cc406Sopenharmony_ci int left, top; 4382141cc406Sopenharmony_ci int lcount; 4383141cc406Sopenharmony_ci int i, j; /* loop counter */ 4384141cc406Sopenharmony_ci 4385141cc406Sopenharmony_ci DBG (5, "sane_start()\n"); 4386141cc406Sopenharmony_ci 4387141cc406Sopenharmony_ci open_scanner (s); 4388141cc406Sopenharmony_ci 4389141cc406Sopenharmony_ci/* 4390141cc406Sopenharmony_ci * There is some undocumented special behavior with the TPU enable/disable. 4391141cc406Sopenharmony_ci * TPU power ESC e status 4392141cc406Sopenharmony_ci * on 0 NAK 4393141cc406Sopenharmony_ci * on 1 ACK 4394141cc406Sopenharmony_ci * off 0 ACK 4395141cc406Sopenharmony_ci * off 1 NAK 4396141cc406Sopenharmony_ci * 4397141cc406Sopenharmony_ci * It makes no sense to scan with TPU powered on and source flatbed, because 4398141cc406Sopenharmony_ci * light will come from both sides. 4399141cc406Sopenharmony_ci */ 4400141cc406Sopenharmony_ci 4401141cc406Sopenharmony_ci if (s->hw->extension) 4402141cc406Sopenharmony_ci { 4403141cc406Sopenharmony_ci int max_x, max_y; 4404141cc406Sopenharmony_ci 4405141cc406Sopenharmony_ci int extensionCtrl; 4406141cc406Sopenharmony_ci extensionCtrl = (s->hw->use_extension ? 1 : 0); 4407141cc406Sopenharmony_ci if (s->hw->use_extension && (s->val[OPT_ADF_MODE].w == 1)) 4408141cc406Sopenharmony_ci extensionCtrl = 2; 4409141cc406Sopenharmony_ci 4410141cc406Sopenharmony_ci status = control_extension (s, extensionCtrl); 4411141cc406Sopenharmony_ci 4412141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4413141cc406Sopenharmony_ci { 4414141cc406Sopenharmony_ci DBG (1, "You may have to power %s your TPU\n", 4415141cc406Sopenharmony_ci s->hw->use_extension ? "on" : "off"); 4416141cc406Sopenharmony_ci 4417141cc406Sopenharmony_ci DBG (1, "Also you may have to restart the Sane frontend.\n"); 4418141cc406Sopenharmony_ci close_scanner (s); 4419141cc406Sopenharmony_ci return status; 4420141cc406Sopenharmony_ci } 4421141cc406Sopenharmony_ci 4422141cc406Sopenharmony_ci if (s->hw->cmd->request_extended_status != 0) 4423141cc406Sopenharmony_ci { 4424141cc406Sopenharmony_ci status = check_ext_status (s, &max_x, &max_y); 4425141cc406Sopenharmony_ci 4426141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status && SANE_STATUS_DEVICE_BUSY != status) 4427141cc406Sopenharmony_ci { 4428141cc406Sopenharmony_ci close_scanner (s); 4429141cc406Sopenharmony_ci return status; 4430141cc406Sopenharmony_ci } 4431141cc406Sopenharmony_ci } 4432141cc406Sopenharmony_ci 4433141cc406Sopenharmony_ci if (s->hw->ADF && s->hw->use_extension && s->hw->cmd->feed) 4434141cc406Sopenharmony_ci { 4435141cc406Sopenharmony_ci status = feed (s); 4436141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4437141cc406Sopenharmony_ci { 4438141cc406Sopenharmony_ci close_scanner (s); 4439141cc406Sopenharmony_ci return status; 4440141cc406Sopenharmony_ci } 4441141cc406Sopenharmony_ci 4442141cc406Sopenharmony_ci check_ext_status (s, &max_x, &max_y); 4443141cc406Sopenharmony_ci s->hw->adf_max_x = max_x; 4444141cc406Sopenharmony_ci s->hw->adf_max_y = max_y; 4445141cc406Sopenharmony_ci } 4446141cc406Sopenharmony_ci 4447141cc406Sopenharmony_ci 4448141cc406Sopenharmony_ci /* 4449141cc406Sopenharmony_ci * set the focus position according to the extension used: 4450141cc406Sopenharmony_ci * if the TPU is selected, then focus 2.5mm above the glass, 4451141cc406Sopenharmony_ci * otherwise focus on the glass. Scanners that don't support 4452141cc406Sopenharmony_ci * this feature, will just ignore these calls. 4453141cc406Sopenharmony_ci */ 4454141cc406Sopenharmony_ci 4455141cc406Sopenharmony_ci if (s->hw->focusSupport == SANE_TRUE) 4456141cc406Sopenharmony_ci { 4457141cc406Sopenharmony_ci if (s->val[OPT_FOCUS].w == 0) 4458141cc406Sopenharmony_ci { 4459141cc406Sopenharmony_ci DBG (1, "Setting focus to glass surface\n"); 4460141cc406Sopenharmony_ci set_focus_position (s, 0x40); 4461141cc406Sopenharmony_ci } 4462141cc406Sopenharmony_ci else 4463141cc406Sopenharmony_ci { 4464141cc406Sopenharmony_ci DBG (1, "Setting focus to 2.5mm above glass\n"); 4465141cc406Sopenharmony_ci set_focus_position (s, 0x59); 4466141cc406Sopenharmony_ci } 4467141cc406Sopenharmony_ci } 4468141cc406Sopenharmony_ci } 4469141cc406Sopenharmony_ci 4470141cc406Sopenharmony_ci /* use the flatbed size for the max. scansize for the GT-30000 4471141cc406Sopenharmony_ci and similar scanners if the ADF is not enabled */ 4472141cc406Sopenharmony_ci if (s->hw->devtype == 3 && s->hw->use_extension == 0) 4473141cc406Sopenharmony_ci { 4474141cc406Sopenharmony_ci int max_x, max_y; 4475141cc406Sopenharmony_ci 4476141cc406Sopenharmony_ci status = check_ext_status (s, &max_x, &max_y); 4477141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status && SANE_STATUS_DEVICE_BUSY != status) 4478141cc406Sopenharmony_ci { 4479141cc406Sopenharmony_ci close_scanner (s); 4480141cc406Sopenharmony_ci return status; 4481141cc406Sopenharmony_ci } 4482141cc406Sopenharmony_ci 4483141cc406Sopenharmony_ci s->hw->fbf_max_x = max_x; 4484141cc406Sopenharmony_ci s->hw->fbf_max_y = max_y; 4485141cc406Sopenharmony_ci } 4486141cc406Sopenharmony_ci 4487141cc406Sopenharmony_ci 4488141cc406Sopenharmony_ci mparam = mode_params + s->val[OPT_MODE].w; 4489141cc406Sopenharmony_ci DBG (1, "sane_start: Setting data format to %d bits\n", mparam->depth); 4490141cc406Sopenharmony_ci status = set_data_format (s, mparam->depth); 4491141cc406Sopenharmony_ci 4492141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4493141cc406Sopenharmony_ci { 4494141cc406Sopenharmony_ci DBG (1, "sane_start: set_data_format failed: %s\n", 4495141cc406Sopenharmony_ci sane_strstatus (status)); 4496141cc406Sopenharmony_ci return status; 4497141cc406Sopenharmony_ci } 4498141cc406Sopenharmony_ci 4499141cc406Sopenharmony_ci /* 4500141cc406Sopenharmony_ci * The byte sequence mode was introduced in B5, for B[34] we need line sequence mode 4501141cc406Sopenharmony_ci */ 4502141cc406Sopenharmony_ci 4503141cc406Sopenharmony_ci if ((s->hw->cmd->level[0] == 'D' || 4504141cc406Sopenharmony_ci (s->hw->cmd->level[0] == 'B' && s->hw->level >= 5)) && 4505141cc406Sopenharmony_ci mparam->mode_flags == 0x02) 4506141cc406Sopenharmony_ci { 4507141cc406Sopenharmony_ci status = set_color_mode (s, 0x13); 4508141cc406Sopenharmony_ci } 4509141cc406Sopenharmony_ci else 4510141cc406Sopenharmony_ci { 4511141cc406Sopenharmony_ci status = set_color_mode (s, mparam->mode_flags | (mparam->dropout_mask 4512141cc406Sopenharmony_ci & dropout_params[s-> 4513141cc406Sopenharmony_ci val 4514141cc406Sopenharmony_ci [OPT_DROPOUT]. 4515141cc406Sopenharmony_ci w])); 4516141cc406Sopenharmony_ci } 4517141cc406Sopenharmony_ci 4518141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4519141cc406Sopenharmony_ci { 4520141cc406Sopenharmony_ci DBG (1, "sane_start: set_color_mode failed: %s\n", 4521141cc406Sopenharmony_ci sane_strstatus (status)); 4522141cc406Sopenharmony_ci return status; 4523141cc406Sopenharmony_ci } 4524141cc406Sopenharmony_ci 4525141cc406Sopenharmony_ci if (s->hw->cmd->set_halftoning && 4526141cc406Sopenharmony_ci SANE_OPTION_IS_ACTIVE (s->opt[OPT_HALFTONE].cap)) 4527141cc406Sopenharmony_ci { 4528141cc406Sopenharmony_ci status = set_halftoning (s, halftone_params[s->val[OPT_HALFTONE].w]); 4529141cc406Sopenharmony_ci 4530141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4531141cc406Sopenharmony_ci { 4532141cc406Sopenharmony_ci DBG (1, "sane_start: set_halftoning failed: %s\n", 4533141cc406Sopenharmony_ci sane_strstatus (status)); 4534141cc406Sopenharmony_ci return status; 4535141cc406Sopenharmony_ci } 4536141cc406Sopenharmony_ci } 4537141cc406Sopenharmony_ci 4538141cc406Sopenharmony_ci 4539141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_BRIGHTNESS].cap)) 4540141cc406Sopenharmony_ci { 4541141cc406Sopenharmony_ci status = set_bright (s, s->val[OPT_BRIGHTNESS].w); 4542141cc406Sopenharmony_ci 4543141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4544141cc406Sopenharmony_ci { 4545141cc406Sopenharmony_ci DBG (1, "sane_start: set_bright failed: %s\n", sane_strstatus (status)); 4546141cc406Sopenharmony_ci return status; 4547141cc406Sopenharmony_ci } 4548141cc406Sopenharmony_ci } 4549141cc406Sopenharmony_ci 4550141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_MIRROR].cap)) 4551141cc406Sopenharmony_ci { 4552141cc406Sopenharmony_ci status = mirror_image (s, mirror_params[s->val[OPT_MIRROR].w]); 4553141cc406Sopenharmony_ci 4554141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4555141cc406Sopenharmony_ci { 4556141cc406Sopenharmony_ci DBG (1, "sane_start: mirror_image failed: %s\n", 4557141cc406Sopenharmony_ci sane_strstatus (status)); 4558141cc406Sopenharmony_ci return status; 4559141cc406Sopenharmony_ci } 4560141cc406Sopenharmony_ci 4561141cc406Sopenharmony_ci } 4562141cc406Sopenharmony_ci 4563141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_SPEED].cap)) 4564141cc406Sopenharmony_ci { 4565141cc406Sopenharmony_ci 4566141cc406Sopenharmony_ci if (s->val[OPT_PREVIEW].w) 4567141cc406Sopenharmony_ci status = set_speed (s, speed_params[s->val[OPT_PREVIEW_SPEED].w]); 4568141cc406Sopenharmony_ci else 4569141cc406Sopenharmony_ci status = set_speed (s, speed_params[s->val[OPT_SPEED].w]); 4570141cc406Sopenharmony_ci 4571141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4572141cc406Sopenharmony_ci { 4573141cc406Sopenharmony_ci DBG (1, "sane_start: set_speed failed: %s\n", sane_strstatus (status)); 4574141cc406Sopenharmony_ci return status; 4575141cc406Sopenharmony_ci } 4576141cc406Sopenharmony_ci 4577141cc406Sopenharmony_ci } 4578141cc406Sopenharmony_ci 4579141cc406Sopenharmony_ci/* 4580141cc406Sopenharmony_ci * use of speed_params is ok here since they are false and true. 4581141cc406Sopenharmony_ci * NOTE: I think I should throw that "params" stuff as long w is already the value. 4582141cc406Sopenharmony_ci */ 4583141cc406Sopenharmony_ci 4584141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_AAS].cap)) 4585141cc406Sopenharmony_ci { 4586141cc406Sopenharmony_ci status = control_auto_area_segmentation (s, 4587141cc406Sopenharmony_ci speed_params[s->val[OPT_AAS].w]); 4588141cc406Sopenharmony_ci 4589141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4590141cc406Sopenharmony_ci { 4591141cc406Sopenharmony_ci DBG (1, "sane_start: control_auto_area_segmentation failed: %s\n", 4592141cc406Sopenharmony_ci sane_strstatus (status)); 4593141cc406Sopenharmony_ci return status; 4594141cc406Sopenharmony_ci } 4595141cc406Sopenharmony_ci } 4596141cc406Sopenharmony_ci 4597141cc406Sopenharmony_ci s->invert_image = SANE_FALSE; /* default: to not inverting the image */ 4598141cc406Sopenharmony_ci 4599141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_FILM_TYPE].cap)) 4600141cc406Sopenharmony_ci { 4601141cc406Sopenharmony_ci s->invert_image = (s->val[OPT_FILM_TYPE].w == FILM_TYPE_NEGATIVE); 4602141cc406Sopenharmony_ci status = set_film_type (s, film_params[s->val[OPT_FILM_TYPE].w]); 4603141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4604141cc406Sopenharmony_ci { 4605141cc406Sopenharmony_ci DBG (1, "sane_start: set_film_type failed: %s\n", 4606141cc406Sopenharmony_ci sane_strstatus (status)); 4607141cc406Sopenharmony_ci return status; 4608141cc406Sopenharmony_ci } 4609141cc406Sopenharmony_ci } 4610141cc406Sopenharmony_ci 4611141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_BAY].cap)) 4612141cc406Sopenharmony_ci { 4613141cc406Sopenharmony_ci status = set_bay (s, s->val[OPT_BAY].w); 4614141cc406Sopenharmony_ci 4615141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4616141cc406Sopenharmony_ci { 4617141cc406Sopenharmony_ci DBG (1, "sane_start: set_bay: %s\n", sane_strstatus (status)); 4618141cc406Sopenharmony_ci return status; 4619141cc406Sopenharmony_ci } 4620141cc406Sopenharmony_ci } 4621141cc406Sopenharmony_ci 4622141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_SHARPNESS].cap)) 4623141cc406Sopenharmony_ci { 4624141cc406Sopenharmony_ci 4625141cc406Sopenharmony_ci status = set_outline_emphasis (s, s->val[OPT_SHARPNESS].w); 4626141cc406Sopenharmony_ci 4627141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4628141cc406Sopenharmony_ci { 4629141cc406Sopenharmony_ci DBG (1, "sane_start: set_outline_emphasis failed: %s\n", 4630141cc406Sopenharmony_ci sane_strstatus (status)); 4631141cc406Sopenharmony_ci return status; 4632141cc406Sopenharmony_ci } 4633141cc406Sopenharmony_ci } 4634141cc406Sopenharmony_ci 4635141cc406Sopenharmony_ci if (s->hw->cmd->set_gamma && 4636141cc406Sopenharmony_ci SANE_OPTION_IS_ACTIVE (s->opt[OPT_GAMMA_CORRECTION].cap)) 4637141cc406Sopenharmony_ci { 4638141cc406Sopenharmony_ci int val; 4639141cc406Sopenharmony_ci if (s->hw->cmd->level[0] == 'D') 4640141cc406Sopenharmony_ci { 4641141cc406Sopenharmony_ci /* 4642141cc406Sopenharmony_ci * The D1 level has only the two user defined gamma 4643141cc406Sopenharmony_ci * settings. 4644141cc406Sopenharmony_ci */ 4645141cc406Sopenharmony_ci val = gamma_params[s->val[OPT_GAMMA_CORRECTION].w]; 4646141cc406Sopenharmony_ci } 4647141cc406Sopenharmony_ci else 4648141cc406Sopenharmony_ci { 4649141cc406Sopenharmony_ci val = gamma_params[s->val[OPT_GAMMA_CORRECTION].w]; 4650141cc406Sopenharmony_ci 4651141cc406Sopenharmony_ci /* 4652141cc406Sopenharmony_ci * If "Default" is selected then determine the actual value 4653141cc406Sopenharmony_ci * to send to the scanner: If bilevel mode, just send the 4654141cc406Sopenharmony_ci * value from the table (0x01), for grayscale or color mode 4655141cc406Sopenharmony_ci * add one and send 0x02. 4656141cc406Sopenharmony_ci */ 4657141cc406Sopenharmony_ci/* if( s->val[ OPT_GAMMA_CORRECTION].w <= 1) { */ 4658141cc406Sopenharmony_ci if (s->val[OPT_GAMMA_CORRECTION].w == 0) 4659141cc406Sopenharmony_ci { 4660141cc406Sopenharmony_ci val += mparam->depth == 1 ? 0 : 1; 4661141cc406Sopenharmony_ci } 4662141cc406Sopenharmony_ci } 4663141cc406Sopenharmony_ci 4664141cc406Sopenharmony_ci DBG (1, "sane_start: set_gamma( s, 0x%x ).\n", val); 4665141cc406Sopenharmony_ci status = set_gamma (s, val); 4666141cc406Sopenharmony_ci 4667141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4668141cc406Sopenharmony_ci { 4669141cc406Sopenharmony_ci DBG (1, "sane_start: set_gamma failed: %s\n", sane_strstatus (status)); 4670141cc406Sopenharmony_ci return status; 4671141cc406Sopenharmony_ci } 4672141cc406Sopenharmony_ci } 4673141cc406Sopenharmony_ci 4674141cc406Sopenharmony_ci if (s->hw->cmd->set_gamma_table && 4675141cc406Sopenharmony_ci gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w]) 4676141cc406Sopenharmony_ci { /* user defined. */ 4677141cc406Sopenharmony_ci status = set_gamma_table (s); 4678141cc406Sopenharmony_ci 4679141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4680141cc406Sopenharmony_ci { 4681141cc406Sopenharmony_ci DBG (1, "sane_start: set_gamma_table failed: %s\n", 4682141cc406Sopenharmony_ci sane_strstatus (status)); 4683141cc406Sopenharmony_ci return status; 4684141cc406Sopenharmony_ci } 4685141cc406Sopenharmony_ci } 4686141cc406Sopenharmony_ci 4687141cc406Sopenharmony_ci/* 4688141cc406Sopenharmony_ci * TODO: think about if SANE_OPTION_IS_ACTIVE is a good criteria to send commands. 4689141cc406Sopenharmony_ci */ 4690141cc406Sopenharmony_ci 4691141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_COLOR_CORRECTION].cap)) 4692141cc406Sopenharmony_ci { 4693141cc406Sopenharmony_ci int val = color_params[s->val[OPT_COLOR_CORRECTION].w]; 4694141cc406Sopenharmony_ci 4695141cc406Sopenharmony_ci DBG (1, "sane_start: set_color_correction( s, 0x%x )\n", val); 4696141cc406Sopenharmony_ci status = set_color_correction (s, val); 4697141cc406Sopenharmony_ci 4698141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4699141cc406Sopenharmony_ci { 4700141cc406Sopenharmony_ci DBG (1, "sane_start: set_color_correction failed: %s\n", 4701141cc406Sopenharmony_ci sane_strstatus (status)); 4702141cc406Sopenharmony_ci return status; 4703141cc406Sopenharmony_ci } 4704141cc406Sopenharmony_ci } 4705141cc406Sopenharmony_ci if (1 == s->val[OPT_COLOR_CORRECTION].w) 4706141cc406Sopenharmony_ci { /* user defined. */ 4707141cc406Sopenharmony_ci status = set_color_correction_coefficients (s); 4708141cc406Sopenharmony_ci 4709141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4710141cc406Sopenharmony_ci { 4711141cc406Sopenharmony_ci DBG (1, "sane_start: set_color_correction_coefficients failed: %s\n", 4712141cc406Sopenharmony_ci sane_strstatus (status)); 4713141cc406Sopenharmony_ci return status; 4714141cc406Sopenharmony_ci } 4715141cc406Sopenharmony_ci } 4716141cc406Sopenharmony_ci 4717141cc406Sopenharmony_ci 4718141cc406Sopenharmony_ci if (s->hw->cmd->set_threshold != 0 4719141cc406Sopenharmony_ci && SANE_OPTION_IS_ACTIVE (s->opt[OPT_THRESHOLD].cap)) 4720141cc406Sopenharmony_ci { 4721141cc406Sopenharmony_ci status = set_threshold (s, s->val[OPT_THRESHOLD].w); 4722141cc406Sopenharmony_ci 4723141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4724141cc406Sopenharmony_ci { 4725141cc406Sopenharmony_ci DBG (1, "sane_start: set_threshold(%d) failed: %s\n", 4726141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w, sane_strstatus (status)); 4727141cc406Sopenharmony_ci return status; 4728141cc406Sopenharmony_ci } 4729141cc406Sopenharmony_ci } 4730141cc406Sopenharmony_ci 4731141cc406Sopenharmony_ci ndpi = s->val[OPT_RESOLUTION].w; 4732141cc406Sopenharmony_ci 4733141cc406Sopenharmony_ci status = set_resolution (s, ndpi, ndpi); 4734141cc406Sopenharmony_ci 4735141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4736141cc406Sopenharmony_ci { 4737141cc406Sopenharmony_ci DBG (1, "sane_start: set_resolution(%d, %d) failed: %s\n", 4738141cc406Sopenharmony_ci ndpi, ndpi, sane_strstatus (status)); 4739141cc406Sopenharmony_ci return status; 4740141cc406Sopenharmony_ci } 4741141cc406Sopenharmony_ci 4742141cc406Sopenharmony_ci status = sane_get_parameters (handle, NULL); 4743141cc406Sopenharmony_ci 4744141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 4745141cc406Sopenharmony_ci return status; 4746141cc406Sopenharmony_ci 4747141cc406Sopenharmony_ci /* set the zoom */ 4748141cc406Sopenharmony_ci if (s->hw->cmd->set_zoom != 0 4749141cc406Sopenharmony_ci && SANE_OPTION_IS_ACTIVE (s->opt[OPT_ZOOM].cap)) 4750141cc406Sopenharmony_ci { 4751141cc406Sopenharmony_ci status = set_zoom (s, s->val[OPT_ZOOM].w, s->val[OPT_ZOOM].w); 4752141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 4753141cc406Sopenharmony_ci { 4754141cc406Sopenharmony_ci DBG (1, "sane_start: set_zoom(%d) failed: %s\n", 4755141cc406Sopenharmony_ci s->val[OPT_ZOOM].w, sane_strstatus (status)); 4756141cc406Sopenharmony_ci return status; 4757141cc406Sopenharmony_ci } 4758141cc406Sopenharmony_ci } 4759141cc406Sopenharmony_ci 4760141cc406Sopenharmony_ci 4761141cc406Sopenharmony_ci/* 4762141cc406Sopenharmony_ci * Now s->params is initialized. 4763141cc406Sopenharmony_ci */ 4764141cc406Sopenharmony_ci 4765141cc406Sopenharmony_ci 4766141cc406Sopenharmony_ci/* 4767141cc406Sopenharmony_ci * If WAIT_FOR_BUTTON is active, then do just that: Wait until the button is 4768141cc406Sopenharmony_ci * pressed. If the button was already pressed, then we will get the button 4769141cc406Sopenharmony_ci * Pressed event right away. 4770141cc406Sopenharmony_ci */ 4771141cc406Sopenharmony_ci 4772141cc406Sopenharmony_ci if (s->val[OPT_WAIT_FOR_BUTTON].w == SANE_TRUE) 4773141cc406Sopenharmony_ci { 4774141cc406Sopenharmony_ci s->hw->wait_for_button = SANE_TRUE; 4775141cc406Sopenharmony_ci 4776141cc406Sopenharmony_ci while (s->hw->wait_for_button == SANE_TRUE) 4777141cc406Sopenharmony_ci { 4778141cc406Sopenharmony_ci if (s->canceling == SANE_TRUE) 4779141cc406Sopenharmony_ci { 4780141cc406Sopenharmony_ci s->hw->wait_for_button = SANE_FALSE; 4781141cc406Sopenharmony_ci } 4782141cc406Sopenharmony_ci /* get the button status from the scanner */ 4783141cc406Sopenharmony_ci else if (request_push_button_status (s, &button_status) == 4784141cc406Sopenharmony_ci SANE_STATUS_GOOD) 4785141cc406Sopenharmony_ci { 4786141cc406Sopenharmony_ci if (button_status == SANE_TRUE) 4787141cc406Sopenharmony_ci { 4788141cc406Sopenharmony_ci s->hw->wait_for_button = SANE_FALSE; 4789141cc406Sopenharmony_ci } 4790141cc406Sopenharmony_ci else 4791141cc406Sopenharmony_ci { 4792141cc406Sopenharmony_ci sleep (1); 4793141cc406Sopenharmony_ci } 4794141cc406Sopenharmony_ci } 4795141cc406Sopenharmony_ci else 4796141cc406Sopenharmony_ci { 4797141cc406Sopenharmony_ci /* we ran into an error condition, just continue */ 4798141cc406Sopenharmony_ci s->hw->wait_for_button = SANE_FALSE; 4799141cc406Sopenharmony_ci } 4800141cc406Sopenharmony_ci } 4801141cc406Sopenharmony_ci } 4802141cc406Sopenharmony_ci 4803141cc406Sopenharmony_ci 4804141cc406Sopenharmony_ci/* 4805141cc406Sopenharmony_ci * in file:frontend/preview.c 4806141cc406Sopenharmony_ci * 4807141cc406Sopenharmony_ci * The preview strategy is as follows: 4808141cc406Sopenharmony_ci * 4809141cc406Sopenharmony_ci * 1) A preview always acquires an image that covers the entire 4810141cc406Sopenharmony_ci * scan surface. This is necessary so the user can see not 4811141cc406Sopenharmony_ci * only what is, but also what isn't selected. 4812141cc406Sopenharmony_ci */ 4813141cc406Sopenharmony_ci 4814141cc406Sopenharmony_ci left = SANE_UNFIX (s->val[OPT_TL_X].w) / 25.4 * ndpi + 0.5; 4815141cc406Sopenharmony_ci top = SANE_UNFIX (s->val[OPT_TL_Y].w) / 25.4 * ndpi + 0.5; 4816141cc406Sopenharmony_ci 4817141cc406Sopenharmony_ci /* 4818141cc406Sopenharmony_ci * Calculate correction for line_distance in D1 scanner: 4819141cc406Sopenharmony_ci * Start line_distance lines earlier and add line_distance lines at the end 4820141cc406Sopenharmony_ci * 4821141cc406Sopenharmony_ci * Because the actual line_distance is not yet calculated we have to do this 4822141cc406Sopenharmony_ci * first. 4823141cc406Sopenharmony_ci */ 4824141cc406Sopenharmony_ci 4825141cc406Sopenharmony_ci s->hw->color_shuffle = SANE_FALSE; 4826141cc406Sopenharmony_ci s->current_output_line = 0; 4827141cc406Sopenharmony_ci s->lines_written = 0; 4828141cc406Sopenharmony_ci s->color_shuffle_line = 0; 4829141cc406Sopenharmony_ci 4830141cc406Sopenharmony_ci if ((s->hw->optical_res != 0) && (mparam->depth == 8) 4831141cc406Sopenharmony_ci && (mparam->mode_flags != 0)) 4832141cc406Sopenharmony_ci { 4833141cc406Sopenharmony_ci s->line_distance = s->hw->max_line_distance * ndpi / s->hw->optical_res; 4834141cc406Sopenharmony_ci if (s->line_distance != 0) 4835141cc406Sopenharmony_ci { 4836141cc406Sopenharmony_ci s->hw->color_shuffle = SANE_TRUE; 4837141cc406Sopenharmony_ci } 4838141cc406Sopenharmony_ci else 4839141cc406Sopenharmony_ci s->hw->color_shuffle = SANE_FALSE; 4840141cc406Sopenharmony_ci } 4841141cc406Sopenharmony_ci 4842141cc406Sopenharmony_ci/* 4843141cc406Sopenharmony_ci * for debugging purposes: 4844141cc406Sopenharmony_ci */ 4845141cc406Sopenharmony_ci#ifdef FORCE_COLOR_SHUFFLE 4846141cc406Sopenharmony_ci DBG (1, "Test mode: FORCE_COLOR_SHUFFLE = TRUE\n"); 4847141cc406Sopenharmony_ci s->hw->color_shuffle = SANE_TRUE; 4848141cc406Sopenharmony_ci#endif 4849141cc406Sopenharmony_ci 4850141cc406Sopenharmony_ci 4851141cc406Sopenharmony_ci /* 4852141cc406Sopenharmony_ci * Modify the scan area: If the scanner requires color shuffling, then we try to 4853141cc406Sopenharmony_ci * scan more lines to compensate for the lines that will be removed from the scan 4854141cc406Sopenharmony_ci * due to the color shuffling algorithm. 4855141cc406Sopenharmony_ci * At this time we add two times the line distance to the number of scan lines if 4856141cc406Sopenharmony_ci * this is possible - if not, then we try to calculate the number of additional 4857141cc406Sopenharmony_ci * lines according to the selected scan area. 4858141cc406Sopenharmony_ci */ 4859141cc406Sopenharmony_ci if (s->hw->color_shuffle == SANE_TRUE) 4860141cc406Sopenharmony_ci { 4861141cc406Sopenharmony_ci 4862141cc406Sopenharmony_ci /* start the scan 2*line_distance earlier */ 4863141cc406Sopenharmony_ci top -= 2 * s->line_distance; 4864141cc406Sopenharmony_ci if (top < 0) 4865141cc406Sopenharmony_ci { 4866141cc406Sopenharmony_ci top = 0; 4867141cc406Sopenharmony_ci } 4868141cc406Sopenharmony_ci 4869141cc406Sopenharmony_ci /* scan 4*line_distance lines more */ 4870141cc406Sopenharmony_ci s->params.lines += 4 * s->line_distance; 4871141cc406Sopenharmony_ci } 4872141cc406Sopenharmony_ci 4873141cc406Sopenharmony_ci /* 4874141cc406Sopenharmony_ci * If (top + s->params.lines) is larger than the max scan area, reset 4875141cc406Sopenharmony_ci * the number of scan lines: 4876141cc406Sopenharmony_ci */ 4877141cc406Sopenharmony_ci if (SANE_UNFIX (s->val[OPT_BR_Y].w) / 25.4 * ndpi < (s->params.lines + top)) 4878141cc406Sopenharmony_ci { 4879141cc406Sopenharmony_ci s->params.lines = ((int) SANE_UNFIX (s->val[OPT_BR_Y].w) / 4880141cc406Sopenharmony_ci 25.4 * ndpi + 0.5) - top; 4881141cc406Sopenharmony_ci } 4882141cc406Sopenharmony_ci 4883141cc406Sopenharmony_ci 4884141cc406Sopenharmony_ci status = 4885141cc406Sopenharmony_ci set_scan_area (s, left, top, s->params.pixels_per_line, s->params.lines); 4886141cc406Sopenharmony_ci 4887141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4888141cc406Sopenharmony_ci { 4889141cc406Sopenharmony_ci DBG (1, "sane_start: set_scan_area failed: %s\n", 4890141cc406Sopenharmony_ci sane_strstatus (status)); 4891141cc406Sopenharmony_ci return status; 4892141cc406Sopenharmony_ci } 4893141cc406Sopenharmony_ci 4894141cc406Sopenharmony_ci s->block = SANE_FALSE; 4895141cc406Sopenharmony_ci lcount = 1; 4896141cc406Sopenharmony_ci 4897141cc406Sopenharmony_ci /* 4898141cc406Sopenharmony_ci * The set line count commands needs to be sent for certain scanners in 4899141cc406Sopenharmony_ci * color mode. The D1 level requires it, we are however only testing for 4900141cc406Sopenharmony_ci * 'D' and not for the actual numeric level. 4901141cc406Sopenharmony_ci */ 4902141cc406Sopenharmony_ci 4903141cc406Sopenharmony_ci if (((s->hw->cmd->level[0] == 'B') && 4904141cc406Sopenharmony_ci ((s->hw->level >= 5) || ((s->hw->level >= 4) && 4905141cc406Sopenharmony_ci (!mode_params[s->val[OPT_MODE].w].color)))) 4906141cc406Sopenharmony_ci || (s->hw->cmd->level[0] == 'D')) 4907141cc406Sopenharmony_ci { 4908141cc406Sopenharmony_ci s->block = SANE_TRUE; 4909141cc406Sopenharmony_ci lcount = sanei_scsi_max_request_size / s->params.bytes_per_line; 4910141cc406Sopenharmony_ci 4911141cc406Sopenharmony_ci if (lcount >= 255) 4912141cc406Sopenharmony_ci { 4913141cc406Sopenharmony_ci lcount = 255; 4914141cc406Sopenharmony_ci } 4915141cc406Sopenharmony_ci 4916141cc406Sopenharmony_ci if (s->hw->TPU && s->hw->use_extension && lcount > 32) 4917141cc406Sopenharmony_ci { 4918141cc406Sopenharmony_ci lcount = 32; 4919141cc406Sopenharmony_ci } 4920141cc406Sopenharmony_ci 4921141cc406Sopenharmony_ci 4922141cc406Sopenharmony_ci /* 4923141cc406Sopenharmony_ci * The D1 series of scanners only allow an even line number 4924141cc406Sopenharmony_ci * for bi-level scanning. If a bit depth of 1 is selected, then 4925141cc406Sopenharmony_ci * make sure the next lower even number is selected. 4926141cc406Sopenharmony_ci */ 4927141cc406Sopenharmony_ci if (s->hw->cmd->level[0] == 'D') 4928141cc406Sopenharmony_ci { 4929141cc406Sopenharmony_ci if (lcount % 2) 4930141cc406Sopenharmony_ci { 4931141cc406Sopenharmony_ci lcount -= 1; 4932141cc406Sopenharmony_ci } 4933141cc406Sopenharmony_ci } 4934141cc406Sopenharmony_ci 4935141cc406Sopenharmony_ci if (lcount == 0) 4936141cc406Sopenharmony_ci { 4937141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 4938141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 4939141cc406Sopenharmony_ci } 4940141cc406Sopenharmony_ci 4941141cc406Sopenharmony_ci status = set_lcount (s, lcount); 4942141cc406Sopenharmony_ci 4943141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4944141cc406Sopenharmony_ci { 4945141cc406Sopenharmony_ci DBG (1, "sane_start: set_lcount(%d) failed: %s\n", 4946141cc406Sopenharmony_ci lcount, sane_strstatus (status)); 4947141cc406Sopenharmony_ci return status; 4948141cc406Sopenharmony_ci } 4949141cc406Sopenharmony_ci } 4950141cc406Sopenharmony_ci 4951141cc406Sopenharmony_ci if (s->hw->cmd->request_extended_status != 0 4952141cc406Sopenharmony_ci && SANE_TRUE == s->hw->extension) 4953141cc406Sopenharmony_ci { 4954141cc406Sopenharmony_ci u_char result[4]; 4955141cc406Sopenharmony_ci u_char *buf; 4956141cc406Sopenharmony_ci size_t len; 4957141cc406Sopenharmony_ci 4958141cc406Sopenharmony_ci params[0] = ESC; 4959141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_extended_status; 4960141cc406Sopenharmony_ci 4961141cc406Sopenharmony_ci send (s, params, 2, &status); /* send ESC f (request extended status) */ 4962141cc406Sopenharmony_ci 4963141cc406Sopenharmony_ci if (SANE_STATUS_GOOD == status) 4964141cc406Sopenharmony_ci { 4965141cc406Sopenharmony_ci len = 4; /* receive header */ 4966141cc406Sopenharmony_ci 4967141cc406Sopenharmony_ci receive (s, result, len, &status); 4968141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 4969141cc406Sopenharmony_ci return status; 4970141cc406Sopenharmony_ci 4971141cc406Sopenharmony_ci len = result[3] << 8 | result[2]; 4972141cc406Sopenharmony_ci buf = alloca (len); 4973141cc406Sopenharmony_ci 4974141cc406Sopenharmony_ci receive (s, buf, len, &status); /* receive actual status data */ 4975141cc406Sopenharmony_ci 4976141cc406Sopenharmony_ci if (buf[0] & 0x80) 4977141cc406Sopenharmony_ci { 4978141cc406Sopenharmony_ci close_scanner (s); 4979141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4980141cc406Sopenharmony_ci } 4981141cc406Sopenharmony_ci } 4982141cc406Sopenharmony_ci else 4983141cc406Sopenharmony_ci { 4984141cc406Sopenharmony_ci DBG (1, "Extended status flag request failed\n"); 4985141cc406Sopenharmony_ci } 4986141cc406Sopenharmony_ci } 4987141cc406Sopenharmony_ci 4988141cc406Sopenharmony_ci/* 4989141cc406Sopenharmony_ci * for debug purpose 4990141cc406Sopenharmony_ci * check scanner conditions 4991141cc406Sopenharmony_ci */ 4992141cc406Sopenharmony_ci#if 1 4993141cc406Sopenharmony_ci if (s->hw->cmd->request_condition != 0) 4994141cc406Sopenharmony_ci { 4995141cc406Sopenharmony_ci u_char result[4]; 4996141cc406Sopenharmony_ci u_char *buf; 4997141cc406Sopenharmony_ci size_t len; 4998141cc406Sopenharmony_ci 4999141cc406Sopenharmony_ci params[0] = ESC; 5000141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_condition; 5001141cc406Sopenharmony_ci 5002141cc406Sopenharmony_ci send (s, params, 2, &status); /* send request condition */ 5003141cc406Sopenharmony_ci 5004141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5005141cc406Sopenharmony_ci return status; 5006141cc406Sopenharmony_ci 5007141cc406Sopenharmony_ci len = 4; 5008141cc406Sopenharmony_ci receive (s, result, len, &status); 5009141cc406Sopenharmony_ci 5010141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5011141cc406Sopenharmony_ci return status; 5012141cc406Sopenharmony_ci 5013141cc406Sopenharmony_ci len = result[3] << 8 | result[2]; 5014141cc406Sopenharmony_ci buf = alloca (len); 5015141cc406Sopenharmony_ci receive (s, buf, len, &status); 5016141cc406Sopenharmony_ci 5017141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5018141cc406Sopenharmony_ci return status; 5019141cc406Sopenharmony_ci 5020141cc406Sopenharmony_ci#if 0 5021141cc406Sopenharmony_ci DBG (10, "SANE_START: length=%d\n", len); 5022141cc406Sopenharmony_ci for (i = 1; i <= len; i++) 5023141cc406Sopenharmony_ci { 5024141cc406Sopenharmony_ci DBG (10, "SANE_START: %d: %c\n", i, buf[i - 1]); 5025141cc406Sopenharmony_ci } 5026141cc406Sopenharmony_ci#endif 5027141cc406Sopenharmony_ci 5028141cc406Sopenharmony_ci DBG (5, "SANE_START: Color: %d\n", (int) buf[1]); 5029141cc406Sopenharmony_ci DBG (5, "SANE_START: Resolution (x, y): (%d, %d)\n", 5030141cc406Sopenharmony_ci (int) (buf[4] << 8 | buf[3]), (int) (buf[6] << 8 | buf[5])); 5031141cc406Sopenharmony_ci DBG (5, 5032141cc406Sopenharmony_ci "SANE_START: Scan area(pixels) (x0, y0), (x1, y1): (%d, %d), (%d, %d)\n", 5033141cc406Sopenharmony_ci (int) (buf[9] << 8 | buf[8]), (int) (buf[11] << 8 | buf[10]), 5034141cc406Sopenharmony_ci (int) (buf[13] << 8 | buf[12]), (int) (buf[15] << 8 | buf[14])); 5035141cc406Sopenharmony_ci DBG (5, "SANE_START: Data format: %d\n", (int) buf[17]); 5036141cc406Sopenharmony_ci DBG (5, "SANE_START: Halftone: %d\n", (int) buf[19]); 5037141cc406Sopenharmony_ci DBG (5, "SANE_START: Brightness: %d\n", (int) buf[21]); 5038141cc406Sopenharmony_ci DBG (5, "SANE_START: Gamma: %d\n", (int) buf[23]); 5039141cc406Sopenharmony_ci DBG (5, "SANE_START: Zoom (x, y): (%d, %d)\n", (int) buf[26], 5040141cc406Sopenharmony_ci (int) buf[25]); 5041141cc406Sopenharmony_ci DBG (5, "SANE_START: Color correction: %d\n", (int) buf[28]); 5042141cc406Sopenharmony_ci DBG (5, "SANE_START: Sharpness control: %d\n", (int) buf[30]); 5043141cc406Sopenharmony_ci DBG (5, "SANE_START: Scanning mode: %d\n", (int) buf[32]); 5044141cc406Sopenharmony_ci DBG (5, "SANE_START: Mirroring: %d\n", (int) buf[34]); 5045141cc406Sopenharmony_ci DBG (5, "SANE_START: Auto area segmentation: %d\n", (int) buf[36]); 5046141cc406Sopenharmony_ci DBG (5, "SANE_START: Threshold: %d\n", (int) buf[38]); 5047141cc406Sopenharmony_ci DBG (5, "SANE_START: Line counter: %d\n", (int) buf[40]); 5048141cc406Sopenharmony_ci DBG (5, "SANE_START: Option unit control: %d\n", (int) buf[42]); 5049141cc406Sopenharmony_ci DBG (5, "SANE_START: Film type: %d\n", (int) buf[44]); 5050141cc406Sopenharmony_ci } 5051141cc406Sopenharmony_ci#endif 5052141cc406Sopenharmony_ci 5053141cc406Sopenharmony_ci 5054141cc406Sopenharmony_ci /* set the retry count to 0 */ 5055141cc406Sopenharmony_ci s->retry_count = 0; 5056141cc406Sopenharmony_ci 5057141cc406Sopenharmony_ci if (s->hw->color_shuffle == SANE_TRUE) 5058141cc406Sopenharmony_ci { 5059141cc406Sopenharmony_ci 5060141cc406Sopenharmony_ci /* initialize the line buffers */ 5061141cc406Sopenharmony_ci for (i = 0; i < s->line_distance * 2 + 1; i++) 5062141cc406Sopenharmony_ci { 5063141cc406Sopenharmony_ci if (s->line_buffer[i] != NULL) 5064141cc406Sopenharmony_ci free (s->line_buffer[i]); 5065141cc406Sopenharmony_ci 5066141cc406Sopenharmony_ci s->line_buffer[i] = malloc (s->params.bytes_per_line); 5067141cc406Sopenharmony_ci if (s->line_buffer[i] == NULL) 5068141cc406Sopenharmony_ci { 5069141cc406Sopenharmony_ci /* free the memory we've malloced so far */ 5070141cc406Sopenharmony_ci for (j = 0; j < i; j++) 5071141cc406Sopenharmony_ci { 5072141cc406Sopenharmony_ci free (s->line_buffer[j]); 5073141cc406Sopenharmony_ci s->line_buffer[j] = NULL; 5074141cc406Sopenharmony_ci } 5075141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 5076141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 5077141cc406Sopenharmony_ci } 5078141cc406Sopenharmony_ci } 5079141cc406Sopenharmony_ci } 5080141cc406Sopenharmony_ci 5081141cc406Sopenharmony_ci params[0] = ESC; 5082141cc406Sopenharmony_ci params[1] = s->hw->cmd->start_scanning; 5083141cc406Sopenharmony_ci 5084141cc406Sopenharmony_ci send (s, params, 2, &status); 5085141cc406Sopenharmony_ci 5086141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5087141cc406Sopenharmony_ci { 5088141cc406Sopenharmony_ci DBG (1, "sane_start: start failed: %s\n", sane_strstatus (status)); 5089141cc406Sopenharmony_ci return status; 5090141cc406Sopenharmony_ci } 5091141cc406Sopenharmony_ci 5092141cc406Sopenharmony_ci s->eof = SANE_FALSE; 5093141cc406Sopenharmony_ci s->buf = realloc (s->buf, lcount * s->params.bytes_per_line); 5094141cc406Sopenharmony_ci s->ptr = s->end = s->buf; 5095141cc406Sopenharmony_ci s->canceling = SANE_FALSE; 5096141cc406Sopenharmony_ci 5097141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5098141cc406Sopenharmony_ci} /* sane_start */ 5099141cc406Sopenharmony_ci 5100141cc406Sopenharmony_ci/* 5101141cc406Sopenharmony_ci * 5102141cc406Sopenharmony_ci * TODO: clean up the eject and direct cmd mess. 5103141cc406Sopenharmony_ci */ 5104141cc406Sopenharmony_ci 5105141cc406Sopenharmony_ciSANE_Status 5106141cc406Sopenharmony_cisane_auto_eject (Epson_Scanner * s) 5107141cc406Sopenharmony_ci{ 5108141cc406Sopenharmony_ci 5109141cc406Sopenharmony_ci DBG (5, "sane_auto_eject()\n"); 5110141cc406Sopenharmony_ci 5111141cc406Sopenharmony_ci if (s->hw->ADF && s->hw->use_extension && s->val[OPT_AUTO_EJECT].w) 5112141cc406Sopenharmony_ci { /* sequence! */ 5113141cc406Sopenharmony_ci SANE_Status status; 5114141cc406Sopenharmony_ci 5115141cc406Sopenharmony_ci u_char params[1]; 5116141cc406Sopenharmony_ci u_char cmd = s->hw->cmd->eject; 5117141cc406Sopenharmony_ci 5118141cc406Sopenharmony_ci if (!cmd) 5119141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 5120141cc406Sopenharmony_ci 5121141cc406Sopenharmony_ci params[0] = cmd; 5122141cc406Sopenharmony_ci 5123141cc406Sopenharmony_ci send (s, params, 1, &status); 5124141cc406Sopenharmony_ci 5125141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = expect_ack (s))) 5126141cc406Sopenharmony_ci { 5127141cc406Sopenharmony_ci return status; 5128141cc406Sopenharmony_ci } 5129141cc406Sopenharmony_ci } 5130141cc406Sopenharmony_ci 5131141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5132141cc406Sopenharmony_ci} 5133141cc406Sopenharmony_ci 5134141cc406Sopenharmony_ci/* 5135141cc406Sopenharmony_ci * 5136141cc406Sopenharmony_ci * 5137141cc406Sopenharmony_ci */ 5138141cc406Sopenharmony_ci 5139141cc406Sopenharmony_cistatic SANE_Status 5140141cc406Sopenharmony_ciread_data_block (Epson_Scanner * s, EpsonDataRec * result) 5141141cc406Sopenharmony_ci{ 5142141cc406Sopenharmony_ci SANE_Status status; 5143141cc406Sopenharmony_ci u_char param[3]; 5144141cc406Sopenharmony_ci 5145141cc406Sopenharmony_ci receive (s, result, s->block ? 6 : 4, &status); 5146141cc406Sopenharmony_ci 5147141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5148141cc406Sopenharmony_ci return status; 5149141cc406Sopenharmony_ci 5150141cc406Sopenharmony_ci if (STX != result->code) 5151141cc406Sopenharmony_ci { 5152141cc406Sopenharmony_ci DBG (1, "code %02x\n", (int) result->code); 5153141cc406Sopenharmony_ci DBG (1, "error, expected STX\n"); 5154141cc406Sopenharmony_ci 5155141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5156141cc406Sopenharmony_ci } 5157141cc406Sopenharmony_ci 5158141cc406Sopenharmony_ci if (result->status & STATUS_FER) 5159141cc406Sopenharmony_ci { 5160141cc406Sopenharmony_ci int dummy_x, dummy_y; 5161141cc406Sopenharmony_ci 5162141cc406Sopenharmony_ci DBG (1, "fatal error - Status = %02x\n", result->status); 5163141cc406Sopenharmony_ci 5164141cc406Sopenharmony_ci status = check_ext_status (s, &dummy_x, &dummy_y); 5165141cc406Sopenharmony_ci 5166141cc406Sopenharmony_ci /* 5167141cc406Sopenharmony_ci * Hack Alert!!! 5168141cc406Sopenharmony_ci * If the status is SANE_STATUS_DEVICE_BUSY then we need to 5169141cc406Sopenharmony_ci * re-issue the command again. We can assume that the command that 5170141cc406Sopenharmony_ci * caused this problem was ESC G, so in a loop with a sleep 1 we 5171141cc406Sopenharmony_ci * are testing this over and over and over again, until the lamp 5172141cc406Sopenharmony_ci * "thinks" it is ready. 5173141cc406Sopenharmony_ci * 5174141cc406Sopenharmony_ci * TODO: Store the last command and execute what was actually used 5175141cc406Sopenharmony_ci * as the last command. For all situations this error may occur 5176141cc406Sopenharmony_ci * ESC G is very very likely to be the command in question, but 5177141cc406Sopenharmony_ci * we better make sure that this is the case. 5178141cc406Sopenharmony_ci * 5179141cc406Sopenharmony_ci */ 5180141cc406Sopenharmony_ci 5181141cc406Sopenharmony_ci /* 5182141cc406Sopenharmony_ci * let's safe some stack space: If this is not the first go around, 5183141cc406Sopenharmony_ci * then just return the status and let the loop handle this - otherwise 5184141cc406Sopenharmony_ci * we would run this function recursively. 5185141cc406Sopenharmony_ci */ 5186141cc406Sopenharmony_ci 5187141cc406Sopenharmony_ci if ((status == SANE_STATUS_DEVICE_BUSY && s->retry_count > 0) || 5188141cc406Sopenharmony_ci (status == SANE_STATUS_GOOD && s->retry_count > 0)) 5189141cc406Sopenharmony_ci { 5190141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; /* return busy even if we just read OK 5191141cc406Sopenharmony_ci so that the following loop can end 5192141cc406Sopenharmony_ci gracefully */ 5193141cc406Sopenharmony_ci } 5194141cc406Sopenharmony_ci 5195141cc406Sopenharmony_ci while (status == SANE_STATUS_DEVICE_BUSY) 5196141cc406Sopenharmony_ci { 5197141cc406Sopenharmony_ci if (s->retry_count > SANE_EPSON_MAX_RETRIES) 5198141cc406Sopenharmony_ci { 5199141cc406Sopenharmony_ci DBG (1, "Max retry count exceeded (%d)\n", s->retry_count); 5200141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5201141cc406Sopenharmony_ci } 5202141cc406Sopenharmony_ci 5203141cc406Sopenharmony_ci sleep (1); /* wait one second for the next attempt */ 5204141cc406Sopenharmony_ci 5205141cc406Sopenharmony_ci DBG (1, "retrying ESC G - %d\n", ++(s->retry_count)); 5206141cc406Sopenharmony_ci 5207141cc406Sopenharmony_ci param[0] = ESC; 5208141cc406Sopenharmony_ci param[1] = s->hw->cmd->start_scanning; 5209141cc406Sopenharmony_ci 5210141cc406Sopenharmony_ci send (s, param, 2, &status); 5211141cc406Sopenharmony_ci 5212141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5213141cc406Sopenharmony_ci { 5214141cc406Sopenharmony_ci DBG (1, "read_data_block: start failed: %s\n", 5215141cc406Sopenharmony_ci sane_strstatus (status)); 5216141cc406Sopenharmony_ci return status; 5217141cc406Sopenharmony_ci } 5218141cc406Sopenharmony_ci 5219141cc406Sopenharmony_ci status = read_data_block (s, result); 5220141cc406Sopenharmony_ci } 5221141cc406Sopenharmony_ci 5222141cc406Sopenharmony_ci } 5223141cc406Sopenharmony_ci 5224141cc406Sopenharmony_ci return status; 5225141cc406Sopenharmony_ci} 5226141cc406Sopenharmony_ci 5227141cc406Sopenharmony_ci/* 5228141cc406Sopenharmony_ci * 5229141cc406Sopenharmony_ci * 5230141cc406Sopenharmony_ci */ 5231141cc406Sopenharmony_ci 5232141cc406Sopenharmony_ci 5233141cc406Sopenharmony_civoid 5234141cc406Sopenharmony_ciscan_finish (Epson_Scanner * s) 5235141cc406Sopenharmony_ci{ 5236141cc406Sopenharmony_ci SANE_Status status; 5237141cc406Sopenharmony_ci int i, x, y; 5238141cc406Sopenharmony_ci 5239141cc406Sopenharmony_ci DBG (5, "scan_finish()\n"); 5240141cc406Sopenharmony_ci 5241141cc406Sopenharmony_ci free (s->buf); 5242141cc406Sopenharmony_ci s->buf = NULL; 5243141cc406Sopenharmony_ci 5244141cc406Sopenharmony_ci status = check_ext_status (s, &x, &y); 5245141cc406Sopenharmony_ci 5246141cc406Sopenharmony_ci if (SANE_STATUS_NO_DOCS == status && s->hw->ADF && s->hw->use_extension) 5247141cc406Sopenharmony_ci sane_auto_eject (s); 5248141cc406Sopenharmony_ci 5249141cc406Sopenharmony_ci for (i = 0; i < s->line_distance; i++) 5250141cc406Sopenharmony_ci { 5251141cc406Sopenharmony_ci if (s->line_buffer[i] != NULL) 5252141cc406Sopenharmony_ci { 5253141cc406Sopenharmony_ci free (s->line_buffer[i]); 5254141cc406Sopenharmony_ci s->line_buffer[i] = NULL; 5255141cc406Sopenharmony_ci } 5256141cc406Sopenharmony_ci } 5257141cc406Sopenharmony_ci} 5258141cc406Sopenharmony_ci 5259141cc406Sopenharmony_ci#define GET_COLOR(x) ((x.status>>2) & 0x03) 5260141cc406Sopenharmony_ci 5261141cc406Sopenharmony_ciSANE_Status 5262141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, 5263141cc406Sopenharmony_ci SANE_Int * length) 5264141cc406Sopenharmony_ci{ 5265141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 5266141cc406Sopenharmony_ci SANE_Status status; 5267141cc406Sopenharmony_ci int index = 0; 5268141cc406Sopenharmony_ci SANE_Bool reorder = SANE_FALSE; 5269141cc406Sopenharmony_ci SANE_Bool needStrangeReorder = SANE_FALSE; 5270141cc406Sopenharmony_ci 5271141cc406Sopenharmony_ciSTART_READ: 5272141cc406Sopenharmony_ci DBG (5, "sane_read: begin\n"); 5273141cc406Sopenharmony_ci 5274141cc406Sopenharmony_ci if (s->ptr == s->end) 5275141cc406Sopenharmony_ci { 5276141cc406Sopenharmony_ci EpsonDataRec result; 5277141cc406Sopenharmony_ci size_t buf_len; 5278141cc406Sopenharmony_ci 5279141cc406Sopenharmony_ci if ((s->fd != -1) && s->eof) 5280141cc406Sopenharmony_ci { 5281141cc406Sopenharmony_ci if (s->hw->color_shuffle) 5282141cc406Sopenharmony_ci { 5283141cc406Sopenharmony_ci DBG (1, "Written %d lines after color shuffle\n", s->lines_written); 5284141cc406Sopenharmony_ci DBG (1, "Lines requested: %d\n", s->params.lines); 5285141cc406Sopenharmony_ci } 5286141cc406Sopenharmony_ci 5287141cc406Sopenharmony_ci *length = 0; 5288141cc406Sopenharmony_ci scan_finish (s); 5289141cc406Sopenharmony_ci 5290141cc406Sopenharmony_ci return SANE_STATUS_EOF; 5291141cc406Sopenharmony_ci } 5292141cc406Sopenharmony_ci 5293141cc406Sopenharmony_ci 5294141cc406Sopenharmony_ci DBG (5, "sane_read: begin scan1\n"); 5295141cc406Sopenharmony_ci 5296141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = read_data_block (s, &result))) 5297141cc406Sopenharmony_ci { 5298141cc406Sopenharmony_ci *length = 0; 5299141cc406Sopenharmony_ci scan_finish (s); 5300141cc406Sopenharmony_ci return status; 5301141cc406Sopenharmony_ci } 5302141cc406Sopenharmony_ci 5303141cc406Sopenharmony_ci buf_len = result.buf[1] << 8 | result.buf[0]; 5304141cc406Sopenharmony_ci 5305141cc406Sopenharmony_ci DBG (5, "sane_read: buf len = %lu\n", (u_long) buf_len); 5306141cc406Sopenharmony_ci 5307141cc406Sopenharmony_ci if (s->block) 5308141cc406Sopenharmony_ci { 5309141cc406Sopenharmony_ci buf_len *= (result.buf[3] << 8 | result.buf[2]); 5310141cc406Sopenharmony_ci DBG (5, "sane_read: buf len (adjusted) = %lu\n", (u_long) buf_len); 5311141cc406Sopenharmony_ci } 5312141cc406Sopenharmony_ci 5313141cc406Sopenharmony_ci if (!s->block && SANE_FRAME_RGB == s->params.format) 5314141cc406Sopenharmony_ci { 5315141cc406Sopenharmony_ci /* 5316141cc406Sopenharmony_ci * Read color data in line mode 5317141cc406Sopenharmony_ci */ 5318141cc406Sopenharmony_ci 5319141cc406Sopenharmony_ci 5320141cc406Sopenharmony_ci /* 5321141cc406Sopenharmony_ci * read the first color line - the number of bytes to read 5322141cc406Sopenharmony_ci * is already known (from last call to read_data_block() 5323141cc406Sopenharmony_ci * We determine where to write the line from the color information 5324141cc406Sopenharmony_ci * in the data block. At the end we want the order RGB, but the 5325141cc406Sopenharmony_ci * way the data is delivered does not guarantee this - actually it's 5326141cc406Sopenharmony_ci * most likely that the order is GRB if it's not RGB! 5327141cc406Sopenharmony_ci */ 5328141cc406Sopenharmony_ci switch (GET_COLOR (result)) 5329141cc406Sopenharmony_ci { 5330141cc406Sopenharmony_ci case 1: 5331141cc406Sopenharmony_ci index = 1; 5332141cc406Sopenharmony_ci break; 5333141cc406Sopenharmony_ci case 2: 5334141cc406Sopenharmony_ci index = 0; 5335141cc406Sopenharmony_ci break; 5336141cc406Sopenharmony_ci case 3: 5337141cc406Sopenharmony_ci index = 2; 5338141cc406Sopenharmony_ci break; 5339141cc406Sopenharmony_ci } 5340141cc406Sopenharmony_ci 5341141cc406Sopenharmony_ci receive (s, s->buf + index * s->params.pixels_per_line, buf_len, 5342141cc406Sopenharmony_ci &status); 5343141cc406Sopenharmony_ci 5344141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5345141cc406Sopenharmony_ci return status; 5346141cc406Sopenharmony_ci /* 5347141cc406Sopenharmony_ci * send the ACK signal to the scanner in order to make 5348141cc406Sopenharmony_ci * it ready for the next data block. 5349141cc406Sopenharmony_ci */ 5350141cc406Sopenharmony_ci send (s, S_ACK, 1, &status); 5351141cc406Sopenharmony_ci 5352141cc406Sopenharmony_ci /* 5353141cc406Sopenharmony_ci * ... and request the next data block 5354141cc406Sopenharmony_ci */ 5355141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = read_data_block (s, &result))) 5356141cc406Sopenharmony_ci return status; 5357141cc406Sopenharmony_ci 5358141cc406Sopenharmony_ci buf_len = result.buf[1] << 8 | result.buf[0]; 5359141cc406Sopenharmony_ci /* 5360141cc406Sopenharmony_ci * this should never happen, because we are already in 5361141cc406Sopenharmony_ci * line mode, but it does not hurt to check ... 5362141cc406Sopenharmony_ci */ 5363141cc406Sopenharmony_ci if (s->block) 5364141cc406Sopenharmony_ci buf_len *= (result.buf[3] << 8 | result.buf[2]); 5365141cc406Sopenharmony_ci 5366141cc406Sopenharmony_ci DBG (5, "sane_read: buf len2 = %lu\n", (u_long) buf_len); 5367141cc406Sopenharmony_ci 5368141cc406Sopenharmony_ci switch (GET_COLOR (result)) 5369141cc406Sopenharmony_ci { 5370141cc406Sopenharmony_ci case 1: 5371141cc406Sopenharmony_ci index = 1; 5372141cc406Sopenharmony_ci break; 5373141cc406Sopenharmony_ci case 2: 5374141cc406Sopenharmony_ci index = 0; 5375141cc406Sopenharmony_ci break; 5376141cc406Sopenharmony_ci case 3: 5377141cc406Sopenharmony_ci index = 2; 5378141cc406Sopenharmony_ci break; 5379141cc406Sopenharmony_ci } 5380141cc406Sopenharmony_ci 5381141cc406Sopenharmony_ci receive (s, s->buf + index * s->params.pixels_per_line, buf_len, 5382141cc406Sopenharmony_ci &status); 5383141cc406Sopenharmony_ci 5384141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5385141cc406Sopenharmony_ci { 5386141cc406Sopenharmony_ci scan_finish (s); 5387141cc406Sopenharmony_ci *length = 0; 5388141cc406Sopenharmony_ci return status; 5389141cc406Sopenharmony_ci } 5390141cc406Sopenharmony_ci 5391141cc406Sopenharmony_ci send (s, S_ACK, 1, &status); 5392141cc406Sopenharmony_ci 5393141cc406Sopenharmony_ci /* 5394141cc406Sopenharmony_ci * ... and the last data block 5395141cc406Sopenharmony_ci */ 5396141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != (status = read_data_block (s, &result))) 5397141cc406Sopenharmony_ci { 5398141cc406Sopenharmony_ci *length = 0; 5399141cc406Sopenharmony_ci scan_finish (s); 5400141cc406Sopenharmony_ci return status; 5401141cc406Sopenharmony_ci } 5402141cc406Sopenharmony_ci 5403141cc406Sopenharmony_ci buf_len = result.buf[1] << 8 | result.buf[0]; 5404141cc406Sopenharmony_ci 5405141cc406Sopenharmony_ci if (s->block) 5406141cc406Sopenharmony_ci buf_len *= (result.buf[3] << 8 | result.buf[2]); 5407141cc406Sopenharmony_ci 5408141cc406Sopenharmony_ci DBG (5, "sane_read: buf len3 = %lu\n", (u_long) buf_len); 5409141cc406Sopenharmony_ci 5410141cc406Sopenharmony_ci switch (GET_COLOR (result)) 5411141cc406Sopenharmony_ci { 5412141cc406Sopenharmony_ci case 1: 5413141cc406Sopenharmony_ci index = 1; 5414141cc406Sopenharmony_ci break; 5415141cc406Sopenharmony_ci case 2: 5416141cc406Sopenharmony_ci index = 0; 5417141cc406Sopenharmony_ci break; 5418141cc406Sopenharmony_ci case 3: 5419141cc406Sopenharmony_ci index = 2; 5420141cc406Sopenharmony_ci break; 5421141cc406Sopenharmony_ci } 5422141cc406Sopenharmony_ci 5423141cc406Sopenharmony_ci receive (s, s->buf + index * s->params.pixels_per_line, buf_len, 5424141cc406Sopenharmony_ci &status); 5425141cc406Sopenharmony_ci 5426141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5427141cc406Sopenharmony_ci { 5428141cc406Sopenharmony_ci *length = 0; 5429141cc406Sopenharmony_ci scan_finish (s); 5430141cc406Sopenharmony_ci return status; 5431141cc406Sopenharmony_ci } 5432141cc406Sopenharmony_ci } 5433141cc406Sopenharmony_ci else 5434141cc406Sopenharmony_ci { 5435141cc406Sopenharmony_ci /* 5436141cc406Sopenharmony_ci * Read data in block mode 5437141cc406Sopenharmony_ci */ 5438141cc406Sopenharmony_ci 5439141cc406Sopenharmony_ci /* do we have to reorder the data ? */ 5440141cc406Sopenharmony_ci if (GET_COLOR (result) == 0x01) 5441141cc406Sopenharmony_ci { 5442141cc406Sopenharmony_ci reorder = SANE_TRUE; 5443141cc406Sopenharmony_ci } 5444141cc406Sopenharmony_ci 5445141cc406Sopenharmony_ci receive (s, s->buf, buf_len, &status); 5446141cc406Sopenharmony_ci 5447141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 5448141cc406Sopenharmony_ci { 5449141cc406Sopenharmony_ci *length = 0; 5450141cc406Sopenharmony_ci scan_finish (s); 5451141cc406Sopenharmony_ci return status; 5452141cc406Sopenharmony_ci } 5453141cc406Sopenharmony_ci } 5454141cc406Sopenharmony_ci 5455141cc406Sopenharmony_ci if (result.status & STATUS_AREA_END) 5456141cc406Sopenharmony_ci { 5457141cc406Sopenharmony_ci s->eof = SANE_TRUE; 5458141cc406Sopenharmony_ci } 5459141cc406Sopenharmony_ci else 5460141cc406Sopenharmony_ci { 5461141cc406Sopenharmony_ci if (s->canceling) 5462141cc406Sopenharmony_ci { 5463141cc406Sopenharmony_ci send (s, S_CAN, 1, &status); 5464141cc406Sopenharmony_ci expect_ack (s); 5465141cc406Sopenharmony_ci 5466141cc406Sopenharmony_ci *length = 0; 5467141cc406Sopenharmony_ci 5468141cc406Sopenharmony_ci scan_finish (s); 5469141cc406Sopenharmony_ci 5470141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 5471141cc406Sopenharmony_ci } 5472141cc406Sopenharmony_ci else 5473141cc406Sopenharmony_ci send (s, S_ACK, 1, &status); 5474141cc406Sopenharmony_ci } 5475141cc406Sopenharmony_ci 5476141cc406Sopenharmony_ci s->end = s->buf + buf_len; 5477141cc406Sopenharmony_ci s->ptr = s->buf; 5478141cc406Sopenharmony_ci 5479141cc406Sopenharmony_ci /* 5480141cc406Sopenharmony_ci * if we have to re-order the color components (GRB->RGB) we 5481141cc406Sopenharmony_ci * are doing this here: 5482141cc406Sopenharmony_ci */ 5483141cc406Sopenharmony_ci 5484141cc406Sopenharmony_ci /* 5485141cc406Sopenharmony_ci * Some scaners (e.g. the Perfection 1640 and GT-2200) seem 5486141cc406Sopenharmony_ci * to have the R and G channels swapped. 5487141cc406Sopenharmony_ci * The GT-8700 is the Asian version of the Perfection1640. 5488141cc406Sopenharmony_ci * If the scanner name is one of these, and the scan mode is 5489141cc406Sopenharmony_ci * RGB then swap the colors. 5490141cc406Sopenharmony_ci */ 5491141cc406Sopenharmony_ci 5492141cc406Sopenharmony_ci needStrangeReorder = 5493141cc406Sopenharmony_ci (strstr (s->hw->sane.model, "GT-2200") || 5494141cc406Sopenharmony_ci ((strstr (s->hw->sane.model, "1640") && 5495141cc406Sopenharmony_ci strstr (s->hw->sane.model, "Perfection")) || 5496141cc406Sopenharmony_ci strstr (s->hw->sane.model, "GT-8700"))) && 5497141cc406Sopenharmony_ci s->params.format == SANE_FRAME_RGB; 5498141cc406Sopenharmony_ci 5499141cc406Sopenharmony_ci /* 5500141cc406Sopenharmony_ci * Certain Perfection 1650 also need this re-ordering of the two 5501141cc406Sopenharmony_ci * color channels. These scanners are identified by the problem 5502141cc406Sopenharmony_ci * with the half vertical scanning area. When we corrected this, 5503141cc406Sopenharmony_ci * we also set the variable s->hw->need_color_reorder 5504141cc406Sopenharmony_ci */ 5505141cc406Sopenharmony_ci if (s->hw->need_color_reorder) 5506141cc406Sopenharmony_ci { 5507141cc406Sopenharmony_ci needStrangeReorder = SANE_TRUE; 5508141cc406Sopenharmony_ci } 5509141cc406Sopenharmony_ci 5510141cc406Sopenharmony_ci if (needStrangeReorder) 5511141cc406Sopenharmony_ci reorder = SANE_FALSE; /* reordering once is enough */ 5512141cc406Sopenharmony_ci 5513141cc406Sopenharmony_ci if (s->params.format != SANE_FRAME_RGB) 5514141cc406Sopenharmony_ci reorder = SANE_FALSE; /* don't reorder for BW or gray */ 5515141cc406Sopenharmony_ci 5516141cc406Sopenharmony_ci if (reorder) 5517141cc406Sopenharmony_ci { 5518141cc406Sopenharmony_ci SANE_Byte *ptr; 5519141cc406Sopenharmony_ci 5520141cc406Sopenharmony_ci ptr = s->buf; 5521141cc406Sopenharmony_ci while (ptr < s->end) 5522141cc406Sopenharmony_ci { 5523141cc406Sopenharmony_ci if (s->params.depth > 8) 5524141cc406Sopenharmony_ci { 5525141cc406Sopenharmony_ci SANE_Byte tmp; 5526141cc406Sopenharmony_ci 5527141cc406Sopenharmony_ci /* R->G G->R */ 5528141cc406Sopenharmony_ci tmp = ptr[0]; 5529141cc406Sopenharmony_ci ptr[0] = ptr[2]; /* first Byte G */ 5530141cc406Sopenharmony_ci ptr[2] = tmp; /* first Byte R */ 5531141cc406Sopenharmony_ci 5532141cc406Sopenharmony_ci tmp = ptr[1]; 5533141cc406Sopenharmony_ci ptr[1] = ptr[3]; /* second Byte G */ 5534141cc406Sopenharmony_ci ptr[3] = tmp; /* second Byte R */ 5535141cc406Sopenharmony_ci 5536141cc406Sopenharmony_ci ptr += 6; /* go to next pixel */ 5537141cc406Sopenharmony_ci } 5538141cc406Sopenharmony_ci else 5539141cc406Sopenharmony_ci { 5540141cc406Sopenharmony_ci /* R->G G->R */ 5541141cc406Sopenharmony_ci SANE_Byte tmp; 5542141cc406Sopenharmony_ci 5543141cc406Sopenharmony_ci tmp = ptr[0]; 5544141cc406Sopenharmony_ci ptr[0] = ptr[1]; /* G */ 5545141cc406Sopenharmony_ci ptr[1] = tmp; /* R */ 5546141cc406Sopenharmony_ci /* B stays the same */ 5547141cc406Sopenharmony_ci ptr += 3; /* go to next pixel */ 5548141cc406Sopenharmony_ci } 5549141cc406Sopenharmony_ci } 5550141cc406Sopenharmony_ci } 5551141cc406Sopenharmony_ci 5552141cc406Sopenharmony_ci /* 5553141cc406Sopenharmony_ci * Do the color_shuffle if everything else is correct - at this time 5554141cc406Sopenharmony_ci * most of the stuff is hardcoded for the Perfection 610 5555141cc406Sopenharmony_ci */ 5556141cc406Sopenharmony_ci 5557141cc406Sopenharmony_ci if (s->hw->color_shuffle) 5558141cc406Sopenharmony_ci { 5559141cc406Sopenharmony_ci int new_length = 0; 5560141cc406Sopenharmony_ci 5561141cc406Sopenharmony_ci status = color_shuffle (s, &new_length); 5562141cc406Sopenharmony_ci 5563141cc406Sopenharmony_ci /* 5564141cc406Sopenharmony_ci * If no bytes are returned, check if the scanner is already done, if so, 5565141cc406Sopenharmony_ci * we'll probably just return, but if there is more data to process get 5566141cc406Sopenharmony_ci * the next batch. 5567141cc406Sopenharmony_ci */ 5568141cc406Sopenharmony_ci 5569141cc406Sopenharmony_ci if (new_length == 0 && s->end != s->ptr) 5570141cc406Sopenharmony_ci { 5571141cc406Sopenharmony_ci goto START_READ; 5572141cc406Sopenharmony_ci } 5573141cc406Sopenharmony_ci 5574141cc406Sopenharmony_ci s->end = s->buf + new_length; 5575141cc406Sopenharmony_ci s->ptr = s->buf; 5576141cc406Sopenharmony_ci 5577141cc406Sopenharmony_ci } 5578141cc406Sopenharmony_ci 5579141cc406Sopenharmony_ci 5580141cc406Sopenharmony_ci DBG (5, "sane_read: begin scan2\n"); 5581141cc406Sopenharmony_ci } 5582141cc406Sopenharmony_ci 5583141cc406Sopenharmony_ci 5584141cc406Sopenharmony_ci 5585141cc406Sopenharmony_ci /* 5586141cc406Sopenharmony_ci * copy the image data to the data memory area 5587141cc406Sopenharmony_ci */ 5588141cc406Sopenharmony_ci 5589141cc406Sopenharmony_ci if (!s->block && SANE_FRAME_RGB == s->params.format) 5590141cc406Sopenharmony_ci { 5591141cc406Sopenharmony_ci 5592141cc406Sopenharmony_ci max_length /= 3; 5593141cc406Sopenharmony_ci 5594141cc406Sopenharmony_ci if (max_length > s->end - s->ptr) 5595141cc406Sopenharmony_ci max_length = s->end - s->ptr; 5596141cc406Sopenharmony_ci 5597141cc406Sopenharmony_ci *length = 3 * max_length; 5598141cc406Sopenharmony_ci 5599141cc406Sopenharmony_ci if (s->invert_image == SANE_TRUE) 5600141cc406Sopenharmony_ci { 5601141cc406Sopenharmony_ci while (max_length-- != 0) 5602141cc406Sopenharmony_ci { 5603141cc406Sopenharmony_ci /* invert the three values */ 5604141cc406Sopenharmony_ci *data++ = (u_char) ~ (s->ptr[0]); 5605141cc406Sopenharmony_ci *data++ = (u_char) ~ (s->ptr[s->params.pixels_per_line]); 5606141cc406Sopenharmony_ci *data++ = (u_char) ~ (s->ptr[2 * s->params.pixels_per_line]); 5607141cc406Sopenharmony_ci ++s->ptr; 5608141cc406Sopenharmony_ci } 5609141cc406Sopenharmony_ci } 5610141cc406Sopenharmony_ci else 5611141cc406Sopenharmony_ci { 5612141cc406Sopenharmony_ci while (max_length-- != 0) 5613141cc406Sopenharmony_ci { 5614141cc406Sopenharmony_ci *data++ = s->ptr[0]; 5615141cc406Sopenharmony_ci *data++ = s->ptr[s->params.pixels_per_line]; 5616141cc406Sopenharmony_ci *data++ = s->ptr[2 * s->params.pixels_per_line]; 5617141cc406Sopenharmony_ci ++s->ptr; 5618141cc406Sopenharmony_ci } 5619141cc406Sopenharmony_ci } 5620141cc406Sopenharmony_ci } 5621141cc406Sopenharmony_ci else 5622141cc406Sopenharmony_ci { 5623141cc406Sopenharmony_ci if (max_length > s->end - s->ptr) 5624141cc406Sopenharmony_ci max_length = s->end - s->ptr; 5625141cc406Sopenharmony_ci 5626141cc406Sopenharmony_ci *length = max_length; 5627141cc406Sopenharmony_ci 5628141cc406Sopenharmony_ci if (1 == s->params.depth) 5629141cc406Sopenharmony_ci { 5630141cc406Sopenharmony_ci if (s->invert_image == SANE_TRUE) 5631141cc406Sopenharmony_ci { 5632141cc406Sopenharmony_ci while (max_length-- != 0) 5633141cc406Sopenharmony_ci *data++ = *s->ptr++; 5634141cc406Sopenharmony_ci } 5635141cc406Sopenharmony_ci else 5636141cc406Sopenharmony_ci { 5637141cc406Sopenharmony_ci while (max_length-- != 0) 5638141cc406Sopenharmony_ci *data++ = ~*s->ptr++; 5639141cc406Sopenharmony_ci } 5640141cc406Sopenharmony_ci } 5641141cc406Sopenharmony_ci else 5642141cc406Sopenharmony_ci { 5643141cc406Sopenharmony_ci 5644141cc406Sopenharmony_ci if (s->invert_image == SANE_TRUE) 5645141cc406Sopenharmony_ci { 5646141cc406Sopenharmony_ci int i; 5647141cc406Sopenharmony_ci 5648141cc406Sopenharmony_ci for (i = 0; i < max_length; i++) 5649141cc406Sopenharmony_ci { 5650141cc406Sopenharmony_ci data[i] = (u_char) ~ (s->ptr[i]); 5651141cc406Sopenharmony_ci } 5652141cc406Sopenharmony_ci } 5653141cc406Sopenharmony_ci else 5654141cc406Sopenharmony_ci { 5655141cc406Sopenharmony_ci memcpy (data, s->ptr, max_length); 5656141cc406Sopenharmony_ci } 5657141cc406Sopenharmony_ci s->ptr += max_length; 5658141cc406Sopenharmony_ci } 5659141cc406Sopenharmony_ci } 5660141cc406Sopenharmony_ci 5661141cc406Sopenharmony_ci DBG (5, "sane_read: end\n"); 5662141cc406Sopenharmony_ci 5663141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5664141cc406Sopenharmony_ci} 5665141cc406Sopenharmony_ci 5666141cc406Sopenharmony_ci 5667141cc406Sopenharmony_cistatic SANE_Status 5668141cc406Sopenharmony_cicolor_shuffle (SANE_Handle handle, int *new_length) 5669141cc406Sopenharmony_ci{ 5670141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 5671141cc406Sopenharmony_ci SANE_Byte *buf = s->buf; 5672141cc406Sopenharmony_ci int length = s->end - s->buf; 5673141cc406Sopenharmony_ci 5674141cc406Sopenharmony_ci if (s->hw->color_shuffle == SANE_TRUE) 5675141cc406Sopenharmony_ci { 5676141cc406Sopenharmony_ci SANE_Byte *data_ptr; /* ptr to data to process */ 5677141cc406Sopenharmony_ci SANE_Byte *data_end; /* ptr to end of processed data */ 5678141cc406Sopenharmony_ci SANE_Byte *out_data_ptr; /* ptr to memory when writing data */ 5679141cc406Sopenharmony_ci int i; /* loop counter */ 5680141cc406Sopenharmony_ci 5681141cc406Sopenharmony_ci /* 5682141cc406Sopenharmony_ci * It looks like we are dealing with a scanner that has an odd way 5683141cc406Sopenharmony_ci * of dealing with colors... The red and blue scan lines are shifted 5684141cc406Sopenharmony_ci * up or down by a certain number of lines relative to the green line. 5685141cc406Sopenharmony_ci */ 5686141cc406Sopenharmony_ci DBG (5, "sane_read: color_shuffle\n"); 5687141cc406Sopenharmony_ci 5688141cc406Sopenharmony_ci 5689141cc406Sopenharmony_ci /* 5690141cc406Sopenharmony_ci * Initialize the variables we are going to use for the 5691141cc406Sopenharmony_ci * copying of the data. data_ptr is the pointer to 5692141cc406Sopenharmony_ci * the currently worked on scan line. data_end is the 5693141cc406Sopenharmony_ci * end of the data area as calculated from adding *length 5694141cc406Sopenharmony_ci * to the start of data. 5695141cc406Sopenharmony_ci * out_data_ptr is used when writing out the processed data 5696141cc406Sopenharmony_ci * and always points to the beginning of the next line to 5697141cc406Sopenharmony_ci * write. 5698141cc406Sopenharmony_ci */ 5699141cc406Sopenharmony_ci 5700141cc406Sopenharmony_ci data_ptr = out_data_ptr = buf; 5701141cc406Sopenharmony_ci data_end = data_ptr + length; 5702141cc406Sopenharmony_ci 5703141cc406Sopenharmony_ci /* 5704141cc406Sopenharmony_ci * The image data is in *buf, we know that the buffer contains s->end - s->buf ( = length) 5705141cc406Sopenharmony_ci * bytes of data. The width of one line is in s->params.bytes_per_line 5706141cc406Sopenharmony_ci */ 5707141cc406Sopenharmony_ci 5708141cc406Sopenharmony_ci /* 5709141cc406Sopenharmony_ci * The buffer area is supposed to have a number of full scan 5710141cc406Sopenharmony_ci * lines, let's test if this is the case. 5711141cc406Sopenharmony_ci */ 5712141cc406Sopenharmony_ci 5713141cc406Sopenharmony_ci if (length % s->params.bytes_per_line != 0) 5714141cc406Sopenharmony_ci { 5715141cc406Sopenharmony_ci DBG (1, "ERROR in size of buffer: %d / %d\n", 5716141cc406Sopenharmony_ci length, s->params.bytes_per_line); 5717141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5718141cc406Sopenharmony_ci } 5719141cc406Sopenharmony_ci 5720141cc406Sopenharmony_ci while (data_ptr < data_end) 5721141cc406Sopenharmony_ci { 5722141cc406Sopenharmony_ci SANE_Byte *source_ptr, *dest_ptr; 5723141cc406Sopenharmony_ci int loop; 5724141cc406Sopenharmony_ci 5725141cc406Sopenharmony_ci /* copy the green information into the current line */ 5726141cc406Sopenharmony_ci 5727141cc406Sopenharmony_ci source_ptr = data_ptr + 1; 5728141cc406Sopenharmony_ci dest_ptr = s->line_buffer[s->color_shuffle_line] + 1; 5729141cc406Sopenharmony_ci 5730141cc406Sopenharmony_ci for (i = 0; i < s->params.bytes_per_line / 3; i++) 5731141cc406Sopenharmony_ci { 5732141cc406Sopenharmony_ci *dest_ptr = *source_ptr; 5733141cc406Sopenharmony_ci dest_ptr += 3; 5734141cc406Sopenharmony_ci source_ptr += 3; 5735141cc406Sopenharmony_ci } 5736141cc406Sopenharmony_ci 5737141cc406Sopenharmony_ci /* copy the red information n lines back */ 5738141cc406Sopenharmony_ci 5739141cc406Sopenharmony_ci if (s->color_shuffle_line >= s->line_distance) 5740141cc406Sopenharmony_ci { 5741141cc406Sopenharmony_ci source_ptr = data_ptr + 2; 5742141cc406Sopenharmony_ci dest_ptr = 5743141cc406Sopenharmony_ci s->line_buffer[s->color_shuffle_line - s->line_distance] + 2; 5744141cc406Sopenharmony_ci 5745141cc406Sopenharmony_ci/* while (source_ptr < s->line_buffer[s->color_shuffle_line] + s->params.bytes_per_line) */ 5746141cc406Sopenharmony_ci for (loop = 0; loop < s->params.bytes_per_line / 3; loop++) 5747141cc406Sopenharmony_ci 5748141cc406Sopenharmony_ci { 5749141cc406Sopenharmony_ci *dest_ptr = *source_ptr; 5750141cc406Sopenharmony_ci dest_ptr += 3; 5751141cc406Sopenharmony_ci source_ptr += 3; 5752141cc406Sopenharmony_ci } 5753141cc406Sopenharmony_ci } 5754141cc406Sopenharmony_ci 5755141cc406Sopenharmony_ci /* copy the blue information n lines forward */ 5756141cc406Sopenharmony_ci 5757141cc406Sopenharmony_ci source_ptr = data_ptr; 5758141cc406Sopenharmony_ci dest_ptr = s->line_buffer[s->color_shuffle_line + s->line_distance]; 5759141cc406Sopenharmony_ci 5760141cc406Sopenharmony_ci/* while (source_ptr < s->line_buffer[s->color_shuffle_line] + s->params.bytes_per_line) */ 5761141cc406Sopenharmony_ci for (loop = 0; loop < s->params.bytes_per_line / 3; loop++) 5762141cc406Sopenharmony_ci { 5763141cc406Sopenharmony_ci *dest_ptr = *source_ptr; 5764141cc406Sopenharmony_ci dest_ptr += 3; 5765141cc406Sopenharmony_ci source_ptr += 3; 5766141cc406Sopenharmony_ci } 5767141cc406Sopenharmony_ci 5768141cc406Sopenharmony_ci data_ptr += s->params.bytes_per_line; 5769141cc406Sopenharmony_ci 5770141cc406Sopenharmony_ci if (s->color_shuffle_line == s->line_distance) 5771141cc406Sopenharmony_ci { 5772141cc406Sopenharmony_ci /* 5773141cc406Sopenharmony_ci * we just finished the line in line_buffer[0] - write it to the 5774141cc406Sopenharmony_ci * output buffer and continue. 5775141cc406Sopenharmony_ci */ 5776141cc406Sopenharmony_ci 5777141cc406Sopenharmony_ci 5778141cc406Sopenharmony_ci /* 5779141cc406Sopenharmony_ci * The output buffer is still "buf", but because we are 5780141cc406Sopenharmony_ci * only overwriting from the beginning of the memory area 5781141cc406Sopenharmony_ci * we are not interfering with the "still to shuffle" data 5782141cc406Sopenharmony_ci * in the same area. 5783141cc406Sopenharmony_ci */ 5784141cc406Sopenharmony_ci 5785141cc406Sopenharmony_ci /* 5786141cc406Sopenharmony_ci * Strip the first and last n lines and limit to 5787141cc406Sopenharmony_ci */ 5788141cc406Sopenharmony_ci if ((s->current_output_line >= s->line_distance) && 5789141cc406Sopenharmony_ci (s->current_output_line < s->params.lines + s->line_distance)) 5790141cc406Sopenharmony_ci { 5791141cc406Sopenharmony_ci memcpy (out_data_ptr, s->line_buffer[0], s->params.bytes_per_line); 5792141cc406Sopenharmony_ci out_data_ptr += s->params.bytes_per_line; 5793141cc406Sopenharmony_ci 5794141cc406Sopenharmony_ci s->lines_written++; 5795141cc406Sopenharmony_ci } 5796141cc406Sopenharmony_ci 5797141cc406Sopenharmony_ci s->current_output_line++; 5798141cc406Sopenharmony_ci 5799141cc406Sopenharmony_ci 5800141cc406Sopenharmony_ci /* 5801141cc406Sopenharmony_ci * Now remove the 0-entry and move all other 5802141cc406Sopenharmony_ci * lines up by one. There are 2*line_distance + 1 5803141cc406Sopenharmony_ci * buffers, * therefore the loop has to run from 0 5804141cc406Sopenharmony_ci * to * 2*line_distance, and because we want to 5805141cc406Sopenharmony_ci * copy every n+1st entry to n the loop runs 5806141cc406Sopenharmony_ci * from - to 2*line_distance-1! 5807141cc406Sopenharmony_ci */ 5808141cc406Sopenharmony_ci 5809141cc406Sopenharmony_ci free (s->line_buffer[0]); 5810141cc406Sopenharmony_ci 5811141cc406Sopenharmony_ci for (i = 0; i < s->line_distance * 2; i++) 5812141cc406Sopenharmony_ci { 5813141cc406Sopenharmony_ci s->line_buffer[i] = s->line_buffer[i + 1]; 5814141cc406Sopenharmony_ci } 5815141cc406Sopenharmony_ci 5816141cc406Sopenharmony_ci /* 5817141cc406Sopenharmony_ci * and create one new buffer at the end 5818141cc406Sopenharmony_ci */ 5819141cc406Sopenharmony_ci 5820141cc406Sopenharmony_ci s->line_buffer[s->line_distance * 2] = 5821141cc406Sopenharmony_ci malloc (s->params.bytes_per_line); 5822141cc406Sopenharmony_ci if (s->line_buffer[s->line_distance * 2] == NULL) 5823141cc406Sopenharmony_ci { 5824141cc406Sopenharmony_ci int i; 5825141cc406Sopenharmony_ci for (i = 0; i < s->line_distance * 2; i++) 5826141cc406Sopenharmony_ci { 5827141cc406Sopenharmony_ci free (s->line_buffer[i]); 5828141cc406Sopenharmony_ci s->line_buffer[i] = NULL; 5829141cc406Sopenharmony_ci } 5830141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 5831141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 5832141cc406Sopenharmony_ci } 5833141cc406Sopenharmony_ci } 5834141cc406Sopenharmony_ci else 5835141cc406Sopenharmony_ci { 5836141cc406Sopenharmony_ci s->color_shuffle_line++; /* increase the buffer number */ 5837141cc406Sopenharmony_ci } 5838141cc406Sopenharmony_ci } 5839141cc406Sopenharmony_ci 5840141cc406Sopenharmony_ci /* 5841141cc406Sopenharmony_ci * At this time we've used up all the new data from the scanner, some of 5842141cc406Sopenharmony_ci * it is still in the line_buffers, but we are ready to return some of it 5843141cc406Sopenharmony_ci * to the front end software. To do so we have to adjust the size of the 5844141cc406Sopenharmony_ci * data area and the *new_length variable. 5845141cc406Sopenharmony_ci */ 5846141cc406Sopenharmony_ci 5847141cc406Sopenharmony_ci *new_length = out_data_ptr - buf; 5848141cc406Sopenharmony_ci } 5849141cc406Sopenharmony_ci 5850141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5851141cc406Sopenharmony_ci 5852141cc406Sopenharmony_ci} 5853141cc406Sopenharmony_ci 5854141cc406Sopenharmony_ci 5855141cc406Sopenharmony_ci 5856141cc406Sopenharmony_ci 5857141cc406Sopenharmony_ci/* 5858141cc406Sopenharmony_ci * static SANE_Status get_identity_information ( SANE_Handle handle) 5859141cc406Sopenharmony_ci * 5860141cc406Sopenharmony_ci * Request Identity information from scanner and fill in information 5861141cc406Sopenharmony_ci * into dev and/or scanner structures. 5862141cc406Sopenharmony_ci */ 5863141cc406Sopenharmony_cistatic SANE_Status 5864141cc406Sopenharmony_ciget_identity_information (SANE_Handle handle) 5865141cc406Sopenharmony_ci{ 5866141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 5867141cc406Sopenharmony_ci Epson_Device *dev = s->hw; 5868141cc406Sopenharmony_ci EpsonIdent ident; 5869141cc406Sopenharmony_ci u_char param[3]; 5870141cc406Sopenharmony_ci SANE_Status status; 5871141cc406Sopenharmony_ci u_char *buf; 5872141cc406Sopenharmony_ci 5873141cc406Sopenharmony_ci DBG (5, "get_identity_information()\n"); 5874141cc406Sopenharmony_ci 5875141cc406Sopenharmony_ci if (!s->hw->cmd->request_identity) 5876141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5877141cc406Sopenharmony_ci 5878141cc406Sopenharmony_ci 5879141cc406Sopenharmony_ci param[0] = ESC; 5880141cc406Sopenharmony_ci param[1] = s->hw->cmd->request_identity; 5881141cc406Sopenharmony_ci param[2] = '\0'; 5882141cc406Sopenharmony_ci 5883141cc406Sopenharmony_ci if (NULL == (ident = (EpsonIdent) command (s, param, 2, &status))) 5884141cc406Sopenharmony_ci { 5885141cc406Sopenharmony_ci DBG (1, "ident failed\n"); 5886141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5887141cc406Sopenharmony_ci } 5888141cc406Sopenharmony_ci 5889141cc406Sopenharmony_ci DBG (1, "type %3c 0x%02x\n", ident->type, ident->type); 5890141cc406Sopenharmony_ci DBG (1, "level %3c 0x%02x\n", ident->level, ident->level); 5891141cc406Sopenharmony_ci 5892141cc406Sopenharmony_ci { 5893141cc406Sopenharmony_ci char *force = getenv ("SANE_EPSON_CMD_LVL"); 5894141cc406Sopenharmony_ci 5895141cc406Sopenharmony_ci if (force) 5896141cc406Sopenharmony_ci { 5897141cc406Sopenharmony_ci ident->type = force[0]; 5898141cc406Sopenharmony_ci ident->level = force[1]; 5899141cc406Sopenharmony_ci 5900141cc406Sopenharmony_ci DBG (1, "type %3c 0x%02x\n", ident->type, ident->type); 5901141cc406Sopenharmony_ci DBG (1, "level %3c 0x%02x\n", ident->level, ident->level); 5902141cc406Sopenharmony_ci 5903141cc406Sopenharmony_ci DBG (1, "forced\n"); 5904141cc406Sopenharmony_ci } 5905141cc406Sopenharmony_ci } 5906141cc406Sopenharmony_ci 5907141cc406Sopenharmony_ci/* 5908141cc406Sopenharmony_ci * check if option equipment is installed. 5909141cc406Sopenharmony_ci */ 5910141cc406Sopenharmony_ci 5911141cc406Sopenharmony_ci if (ident->status & STATUS_OPTION) 5912141cc406Sopenharmony_ci { 5913141cc406Sopenharmony_ci DBG (1, "option equipment is installed\n"); 5914141cc406Sopenharmony_ci dev->extension = SANE_TRUE; 5915141cc406Sopenharmony_ci } 5916141cc406Sopenharmony_ci else 5917141cc406Sopenharmony_ci { 5918141cc406Sopenharmony_ci DBG (1, "no option equipment installed\n"); 5919141cc406Sopenharmony_ci dev->extension = SANE_FALSE; 5920141cc406Sopenharmony_ci } 5921141cc406Sopenharmony_ci 5922141cc406Sopenharmony_ci dev->TPU = SANE_FALSE; 5923141cc406Sopenharmony_ci dev->ADF = SANE_FALSE; 5924141cc406Sopenharmony_ci 5925141cc406Sopenharmony_ci/* 5926141cc406Sopenharmony_ci * set command type and level. 5927141cc406Sopenharmony_ci */ 5928141cc406Sopenharmony_ci 5929141cc406Sopenharmony_ci { 5930141cc406Sopenharmony_ci int n; 5931141cc406Sopenharmony_ci 5932141cc406Sopenharmony_ci for (n = 0; n < NELEMS (epson_cmd); n++) 5933141cc406Sopenharmony_ci { 5934141cc406Sopenharmony_ci char type_level[3]; 5935141cc406Sopenharmony_ci sprintf(type_level, "%c%c", ident->type, ident->level); 5936141cc406Sopenharmony_ci if (!strncmp (type_level, epson_cmd[n].level, 2)) 5937141cc406Sopenharmony_ci break; 5938141cc406Sopenharmony_ci } 5939141cc406Sopenharmony_ci 5940141cc406Sopenharmony_ci if (n < NELEMS (epson_cmd)) 5941141cc406Sopenharmony_ci { 5942141cc406Sopenharmony_ci dev->cmd = &epson_cmd[n]; 5943141cc406Sopenharmony_ci } 5944141cc406Sopenharmony_ci else 5945141cc406Sopenharmony_ci { 5946141cc406Sopenharmony_ci dev->cmd = &epson_cmd[EPSON_LEVEL_DEFAULT]; 5947141cc406Sopenharmony_ci DBG (1, "Unknown type %c or level %c, using %s\n", 5948141cc406Sopenharmony_ci ident->type, ident->level, dev->cmd->level); 5949141cc406Sopenharmony_ci } 5950141cc406Sopenharmony_ci 5951141cc406Sopenharmony_ci s->hw->level = dev->cmd->level[1] - '0'; 5952141cc406Sopenharmony_ci } /* set command type and level */ 5953141cc406Sopenharmony_ci 5954141cc406Sopenharmony_ci/* 5955141cc406Sopenharmony_ci * Setting available resolutions and xy ranges for sane frontend. 5956141cc406Sopenharmony_ci */ 5957141cc406Sopenharmony_ci 5958141cc406Sopenharmony_ci s->hw->res_list_size = 0; 5959141cc406Sopenharmony_ci s->hw->res_list = 5960141cc406Sopenharmony_ci (SANE_Int *) calloc (s->hw->res_list_size, sizeof (SANE_Int)); 5961141cc406Sopenharmony_ci 5962141cc406Sopenharmony_ci if (NULL == s->hw->res_list) 5963141cc406Sopenharmony_ci { 5964141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 5965141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 5966141cc406Sopenharmony_ci } 5967141cc406Sopenharmony_ci 5968141cc406Sopenharmony_ci { 5969141cc406Sopenharmony_ci int n, k; 5970141cc406Sopenharmony_ci int x = 0, y = 0; 5971141cc406Sopenharmony_ci int count = ident->count2 * 255 + ident->count1; 5972141cc406Sopenharmony_ci 5973141cc406Sopenharmony_ci /* we need to correct for the difference in size between 5974141cc406Sopenharmony_ci the EpsonIdentRec and the EpsonHdrRec */ 5975141cc406Sopenharmony_ci int correction = sizeof (EpsonIdentRec) - sizeof (EpsonHdrRec); 5976141cc406Sopenharmony_ci for (n = (count - correction), buf = ident->buf; n; n -= k, buf += k) 5977141cc406Sopenharmony_ci { 5978141cc406Sopenharmony_ci switch (*buf) 5979141cc406Sopenharmony_ci { 5980141cc406Sopenharmony_ci case 'R': 5981141cc406Sopenharmony_ci { 5982141cc406Sopenharmony_ci int val = buf[2] << 8 | buf[1]; 5983141cc406Sopenharmony_ci 5984141cc406Sopenharmony_ci s->hw->res_list_size++; 5985141cc406Sopenharmony_ci s->hw->res_list = 5986141cc406Sopenharmony_ci (SANE_Int *) realloc (s->hw->res_list, 5987141cc406Sopenharmony_ci s->hw->res_list_size * sizeof (SANE_Int)); 5988141cc406Sopenharmony_ci 5989141cc406Sopenharmony_ci if (NULL == s->hw->res_list) 5990141cc406Sopenharmony_ci { 5991141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 5992141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 5993141cc406Sopenharmony_ci } 5994141cc406Sopenharmony_ci 5995141cc406Sopenharmony_ci s->hw->res_list[s->hw->res_list_size - 1] = (SANE_Int) val; 5996141cc406Sopenharmony_ci 5997141cc406Sopenharmony_ci DBG (1, "resolution (dpi): %d\n", val); 5998141cc406Sopenharmony_ci k = 3; 5999141cc406Sopenharmony_ci continue; 6000141cc406Sopenharmony_ci } 6001141cc406Sopenharmony_ci case 'A': 6002141cc406Sopenharmony_ci { 6003141cc406Sopenharmony_ci x = buf[2] << 8 | buf[1]; 6004141cc406Sopenharmony_ci y = buf[4] << 8 | buf[3]; 6005141cc406Sopenharmony_ci 6006141cc406Sopenharmony_ci DBG (1, "maximum scan area: x %d y %d\n", x, y); 6007141cc406Sopenharmony_ci k = 5; 6008141cc406Sopenharmony_ci 6009141cc406Sopenharmony_ci /* 6010141cc406Sopenharmony_ci * Check for Perfection 4990 photo/GT-X800 scanner. 6011141cc406Sopenharmony_ci * This scanner only report 3200 dpi back. 6012141cc406Sopenharmony_ci * The scanner physically supports 4800 dpi. 6013141cc406Sopenharmony_ci * This is simulated here... 6014141cc406Sopenharmony_ci * Further details read: 6015141cc406Sopenharmony_ci * EPSON Programming guide for EPSON Color Image Scanner Perfection 4990 6016141cc406Sopenharmony_ci */ 6017141cc406Sopenharmony_ci if (s->hw->cmd->request_extended_status != 0) 6018141cc406Sopenharmony_ci { 6019141cc406Sopenharmony_ci u_char *buf; 6020141cc406Sopenharmony_ci u_char params[2]; 6021141cc406Sopenharmony_ci EpsonHdr head; 6022141cc406Sopenharmony_ci 6023141cc406Sopenharmony_ci params[0] = ESC; 6024141cc406Sopenharmony_ci params[1] = s->hw->cmd->request_extended_status; 6025141cc406Sopenharmony_ci 6026141cc406Sopenharmony_ci if (NULL != (head = (EpsonHdr) command (s, params, 2, &status))) 6027141cc406Sopenharmony_ci { 6028141cc406Sopenharmony_ci buf = &head->buf[0x1A]; 6029141cc406Sopenharmony_ci DBG (1, "product name %x %x %x %x %x %x %x %x \n", buf[0], buf[1],buf[2],buf[3],buf[4], buf[5],buf[6], buf[7] ); 6030141cc406Sopenharmony_ci if (strncmp((char *) buf,"GT-X800",7) == 0) 6031141cc406Sopenharmony_ci { 6032141cc406Sopenharmony_ci int val = 0x12 << 8 | 0xC0; 6033141cc406Sopenharmony_ci 6034141cc406Sopenharmony_ci s->hw->res_list_size++; 6035141cc406Sopenharmony_ci s->hw->res_list = 6036141cc406Sopenharmony_ci (SANE_Int *) realloc (s->hw->res_list, 6037141cc406Sopenharmony_ci s->hw->res_list_size * sizeof (SANE_Int)); 6038141cc406Sopenharmony_ci 6039141cc406Sopenharmony_ci if (NULL == s->hw->res_list) 6040141cc406Sopenharmony_ci { 6041141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 6042141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6043141cc406Sopenharmony_ci } 6044141cc406Sopenharmony_ci 6045141cc406Sopenharmony_ci s->hw->res_list[s->hw->res_list_size - 1] = (SANE_Int) val; 6046141cc406Sopenharmony_ci x = (x/32)*48; 6047141cc406Sopenharmony_ci y = (y/32)*48; 6048141cc406Sopenharmony_ci 6049141cc406Sopenharmony_ci DBG (1, "resolution (dpi): %d\n", val); 6050141cc406Sopenharmony_ci DBG (1, "maximum scan area GT-X800: x %d y %d\n", x, y); 6051141cc406Sopenharmony_ci } 6052141cc406Sopenharmony_ci } 6053141cc406Sopenharmony_ci } 6054141cc406Sopenharmony_ci 6055141cc406Sopenharmony_ci continue; 6056141cc406Sopenharmony_ci } 6057141cc406Sopenharmony_ci default: 6058141cc406Sopenharmony_ci break; 6059141cc406Sopenharmony_ci } /* case */ 6060141cc406Sopenharmony_ci 6061141cc406Sopenharmony_ci break; 6062141cc406Sopenharmony_ci } /* for */ 6063141cc406Sopenharmony_ci 6064141cc406Sopenharmony_ci dev->dpi_range.min = s->hw->res_list[0]; 6065141cc406Sopenharmony_ci dev->dpi_range.max = s->hw->res_list[s->hw->res_list_size - 1]; 6066141cc406Sopenharmony_ci dev->dpi_range.quant = 0; 6067141cc406Sopenharmony_ci 6068141cc406Sopenharmony_ci dev->fbf_x_range.min = 0; 6069141cc406Sopenharmony_ci dev->fbf_x_range.max = SANE_FIX (x * 25.4 / dev->dpi_range.max); 6070141cc406Sopenharmony_ci dev->fbf_x_range.quant = 0; 6071141cc406Sopenharmony_ci 6072141cc406Sopenharmony_ci dev->fbf_y_range.min = 0; 6073141cc406Sopenharmony_ci dev->fbf_y_range.max = SANE_FIX (y * 25.4 / dev->dpi_range.max); 6074141cc406Sopenharmony_ci dev->fbf_y_range.quant = 0; 6075141cc406Sopenharmony_ci 6076141cc406Sopenharmony_ci DBG (5, "fbf tlx %f tly %f brx %f bry %f [mm]\n", 6077141cc406Sopenharmony_ci SANE_UNFIX (dev->fbf_x_range.min), SANE_UNFIX (dev->fbf_y_range.min), 6078141cc406Sopenharmony_ci SANE_UNFIX (dev->fbf_x_range.max), 6079141cc406Sopenharmony_ci SANE_UNFIX (dev->fbf_y_range.max)); 6080141cc406Sopenharmony_ci 6081141cc406Sopenharmony_ci } 6082141cc406Sopenharmony_ci 6083141cc406Sopenharmony_ci /* 6084141cc406Sopenharmony_ci * Copy the resolution list to the resolution_list array so that the frontend can 6085141cc406Sopenharmony_ci * display the correct values 6086141cc406Sopenharmony_ci */ 6087141cc406Sopenharmony_ci 6088141cc406Sopenharmony_ci s->hw->resolution_list = 6089141cc406Sopenharmony_ci malloc ((s->hw->res_list_size + 1) * sizeof (SANE_Word)); 6090141cc406Sopenharmony_ci 6091141cc406Sopenharmony_ci if (s->hw->resolution_list == NULL) 6092141cc406Sopenharmony_ci { 6093141cc406Sopenharmony_ci DBG (1, "out of memory (line %d)\n", __LINE__); 6094141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6095141cc406Sopenharmony_ci } 6096141cc406Sopenharmony_ci *(s->hw->resolution_list) = s->hw->res_list_size; 6097141cc406Sopenharmony_ci memcpy (&(s->hw->resolution_list[1]), s->hw->res_list, 6098141cc406Sopenharmony_ci s->hw->res_list_size * sizeof (SANE_Word)); 6099141cc406Sopenharmony_ci 6100141cc406Sopenharmony_ci /* filter the resolution list */ 6101141cc406Sopenharmony_ci /* the option is not yet initialized, for now just set it to false */ 6102141cc406Sopenharmony_ci s->val[OPT_LIMIT_RESOLUTION].w = SANE_FALSE; 6103141cc406Sopenharmony_ci filter_resolution_list (s); 6104141cc406Sopenharmony_ci 6105141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6106141cc406Sopenharmony_ci 6107141cc406Sopenharmony_ci} /* request identity */ 6108141cc406Sopenharmony_ci 6109141cc406Sopenharmony_ci 6110141cc406Sopenharmony_ci/* 6111141cc406Sopenharmony_ci * static SANE_Status get_identity2_information ( SANE_Handle handle) 6112141cc406Sopenharmony_ci * 6113141cc406Sopenharmony_ci * Request Identity2 information from scanner and fill in information 6114141cc406Sopenharmony_ci * into dev and/or scanner structures. 6115141cc406Sopenharmony_ci */ 6116141cc406Sopenharmony_cistatic SANE_Status 6117141cc406Sopenharmony_ciget_identity2_information (SANE_Handle handle) 6118141cc406Sopenharmony_ci{ 6119141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 6120141cc406Sopenharmony_ci SANE_Status status; 6121141cc406Sopenharmony_ci int len; 6122141cc406Sopenharmony_ci u_char param[3]; 6123141cc406Sopenharmony_ci u_char result[4]; 6124141cc406Sopenharmony_ci u_char *buf; 6125141cc406Sopenharmony_ci 6126141cc406Sopenharmony_ci DBG (5, "get_identity2_information()\n"); 6127141cc406Sopenharmony_ci 6128141cc406Sopenharmony_ci if (s->hw->cmd->request_identity2 == 0) 6129141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 6130141cc406Sopenharmony_ci 6131141cc406Sopenharmony_ci param[0] = ESC; 6132141cc406Sopenharmony_ci param[1] = s->hw->cmd->request_identity2; 6133141cc406Sopenharmony_ci param[2] = '\0'; 6134141cc406Sopenharmony_ci 6135141cc406Sopenharmony_ci send (s, param, 2, &status); 6136141cc406Sopenharmony_ci 6137141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 6138141cc406Sopenharmony_ci return status; 6139141cc406Sopenharmony_ci 6140141cc406Sopenharmony_ci len = 4; /* receive header */ 6141141cc406Sopenharmony_ci 6142141cc406Sopenharmony_ci receive (s, result, len, &status); 6143141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 6144141cc406Sopenharmony_ci return status; 6145141cc406Sopenharmony_ci 6146141cc406Sopenharmony_ci len = result[3] << 8 | result[2]; 6147141cc406Sopenharmony_ci buf = alloca (len); 6148141cc406Sopenharmony_ci 6149141cc406Sopenharmony_ci receive (s, buf, len, &status); /* receive actual status data */ 6150141cc406Sopenharmony_ci 6151141cc406Sopenharmony_ci /* the first two bytes of the buffer contain the optical resolution */ 6152141cc406Sopenharmony_ci s->hw->optical_res = buf[1] << 8 | buf[0]; 6153141cc406Sopenharmony_ci 6154141cc406Sopenharmony_ci /* 6155141cc406Sopenharmony_ci * the 4th and 5th byte contain the line distance. Both values have to 6156141cc406Sopenharmony_ci * be identical, otherwise this software can not handle this scanner. 6157141cc406Sopenharmony_ci */ 6158141cc406Sopenharmony_ci if (buf[4] != buf[5]) 6159141cc406Sopenharmony_ci { 6160141cc406Sopenharmony_ci close_scanner (s); 6161141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 6162141cc406Sopenharmony_ci } 6163141cc406Sopenharmony_ci s->hw->max_line_distance = buf[4]; 6164141cc406Sopenharmony_ci 6165141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6166141cc406Sopenharmony_ci} 6167141cc406Sopenharmony_ci 6168141cc406Sopenharmony_ci/* 6169141cc406Sopenharmony_ci * void sane_cancel(SANE_Handle handle) 6170141cc406Sopenharmony_ci * 6171141cc406Sopenharmony_ci * Set the cancel flag to true. The next time the backend requests data 6172141cc406Sopenharmony_ci * from the scanner the CAN message will be sent. 6173141cc406Sopenharmony_ci */ 6174141cc406Sopenharmony_ci 6175141cc406Sopenharmony_civoid 6176141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 6177141cc406Sopenharmony_ci{ 6178141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 6179141cc406Sopenharmony_ci 6180141cc406Sopenharmony_ci /* 6181141cc406Sopenharmony_ci * If the s->ptr pointer is not NULL, then a scan operation 6182141cc406Sopenharmony_ci * was started and if s->eof is FALSE, it was not finished. 6183141cc406Sopenharmony_ci */ 6184141cc406Sopenharmony_ci 6185141cc406Sopenharmony_ci if (s->buf != NULL) 6186141cc406Sopenharmony_ci { 6187141cc406Sopenharmony_ci u_char *dummy; 6188141cc406Sopenharmony_ci int len; 6189141cc406Sopenharmony_ci 6190141cc406Sopenharmony_ci /* malloc one line */ 6191141cc406Sopenharmony_ci dummy = malloc (s->params.bytes_per_line); 6192141cc406Sopenharmony_ci if (dummy == NULL) 6193141cc406Sopenharmony_ci { 6194141cc406Sopenharmony_ci DBG (1, "Out of memory\n"); 6195141cc406Sopenharmony_ci return; 6196141cc406Sopenharmony_ci } 6197141cc406Sopenharmony_ci else 6198141cc406Sopenharmony_ci { 6199141cc406Sopenharmony_ci 6200141cc406Sopenharmony_ci /* there is still data to read from the scanner */ 6201141cc406Sopenharmony_ci 6202141cc406Sopenharmony_ci s->canceling = SANE_TRUE; 6203141cc406Sopenharmony_ci 6204141cc406Sopenharmony_ci while (!s->eof && 6205141cc406Sopenharmony_ci SANE_STATUS_CANCELLED != sane_read (s, dummy, 6206141cc406Sopenharmony_ci s->params.bytes_per_line, 6207141cc406Sopenharmony_ci &len)) 6208141cc406Sopenharmony_ci { 6209141cc406Sopenharmony_ci /* empty body, the while condition does the processing */ 6210141cc406Sopenharmony_ci } 6211141cc406Sopenharmony_ci free (dummy); 6212141cc406Sopenharmony_ci } 6213141cc406Sopenharmony_ci 6214141cc406Sopenharmony_ci } 6215141cc406Sopenharmony_ci} 6216141cc406Sopenharmony_ci 6217141cc406Sopenharmony_ci 6218141cc406Sopenharmony_cistatic SANE_Status 6219141cc406Sopenharmony_cirequest_focus_position (SANE_Handle handle, u_char * position) 6220141cc406Sopenharmony_ci{ 6221141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 6222141cc406Sopenharmony_ci SANE_Status status; 6223141cc406Sopenharmony_ci int len; 6224141cc406Sopenharmony_ci u_char param[3]; 6225141cc406Sopenharmony_ci u_char result[4]; 6226141cc406Sopenharmony_ci u_char *buf; 6227141cc406Sopenharmony_ci 6228141cc406Sopenharmony_ci DBG (5, "request_focus_position()\n"); 6229141cc406Sopenharmony_ci 6230141cc406Sopenharmony_ci if (s->hw->cmd->request_focus_position == 0) 6231141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 6232141cc406Sopenharmony_ci 6233141cc406Sopenharmony_ci param[0] = ESC; 6234141cc406Sopenharmony_ci param[1] = s->hw->cmd->request_focus_position; 6235141cc406Sopenharmony_ci param[2] = '\0'; 6236141cc406Sopenharmony_ci 6237141cc406Sopenharmony_ci send (s, param, 2, &status); 6238141cc406Sopenharmony_ci 6239141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 6240141cc406Sopenharmony_ci return status; 6241141cc406Sopenharmony_ci 6242141cc406Sopenharmony_ci len = 4; /* receive header */ 6243141cc406Sopenharmony_ci 6244141cc406Sopenharmony_ci receive (s, result, len, &status); 6245141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 6246141cc406Sopenharmony_ci return status; 6247141cc406Sopenharmony_ci 6248141cc406Sopenharmony_ci len = result[3] << 8 | result[2]; 6249141cc406Sopenharmony_ci buf = alloca (len); 6250141cc406Sopenharmony_ci 6251141cc406Sopenharmony_ci receive (s, buf, len, &status); /* receive actual status data */ 6252141cc406Sopenharmony_ci 6253141cc406Sopenharmony_ci *position = buf[1]; 6254141cc406Sopenharmony_ci DBG (1, "Focus position = 0x%x\n", buf[1]); 6255141cc406Sopenharmony_ci 6256141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6257141cc406Sopenharmony_ci} 6258141cc406Sopenharmony_ci 6259141cc406Sopenharmony_ci 6260141cc406Sopenharmony_ci/* 6261141cc406Sopenharmony_ci * Request the push button status 6262141cc406Sopenharmony_ci * returns SANE_TRUE if the button was pressed 6263141cc406Sopenharmony_ci * and SANE_FALSE if the button was not pressed 6264141cc406Sopenharmony_ci * it also returns SANE_TRUE in case of an error. 6265141cc406Sopenharmony_ci * This is necessary so that a process that waits for 6266141cc406Sopenharmony_ci * the button does not block indefinitely. 6267141cc406Sopenharmony_ci */ 6268141cc406Sopenharmony_cistatic SANE_Bool 6269141cc406Sopenharmony_cirequest_push_button_status (SANE_Handle handle, SANE_Bool * theButtonStatus) 6270141cc406Sopenharmony_ci{ 6271141cc406Sopenharmony_ci Epson_Scanner *s = (Epson_Scanner *) handle; 6272141cc406Sopenharmony_ci SANE_Status status; 6273141cc406Sopenharmony_ci int len; 6274141cc406Sopenharmony_ci u_char param[3]; 6275141cc406Sopenharmony_ci u_char result[4]; 6276141cc406Sopenharmony_ci u_char *buf; 6277141cc406Sopenharmony_ci 6278141cc406Sopenharmony_ci DBG (5, "request_push_button_status()\n"); 6279141cc406Sopenharmony_ci 6280141cc406Sopenharmony_ci if (s->hw->cmd->request_push_button_status == 0) 6281141cc406Sopenharmony_ci { 6282141cc406Sopenharmony_ci DBG (1, "push button status unsupported\n"); 6283141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 6284141cc406Sopenharmony_ci } 6285141cc406Sopenharmony_ci 6286141cc406Sopenharmony_ci param[0] = ESC; 6287141cc406Sopenharmony_ci param[1] = s->hw->cmd->request_push_button_status; 6288141cc406Sopenharmony_ci param[2] = '\0'; 6289141cc406Sopenharmony_ci 6290141cc406Sopenharmony_ci send (s, param, 2, &status); 6291141cc406Sopenharmony_ci 6292141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 6293141cc406Sopenharmony_ci { 6294141cc406Sopenharmony_ci DBG (1, "error sending command\n"); 6295141cc406Sopenharmony_ci return status; 6296141cc406Sopenharmony_ci } 6297141cc406Sopenharmony_ci 6298141cc406Sopenharmony_ci len = 4; /* receive header */ 6299141cc406Sopenharmony_ci 6300141cc406Sopenharmony_ci receive (s, result, len, &status); 6301141cc406Sopenharmony_ci if (SANE_STATUS_GOOD != status) 6302141cc406Sopenharmony_ci return status; 6303141cc406Sopenharmony_ci 6304141cc406Sopenharmony_ci len = result[3] << 8 | result[2]; /* this should be 1 for scanners with one button */ 6305141cc406Sopenharmony_ci buf = alloca (len); 6306141cc406Sopenharmony_ci 6307141cc406Sopenharmony_ci receive (s, buf, len, &status); /* receive actual status data */ 6308141cc406Sopenharmony_ci 6309141cc406Sopenharmony_ci DBG (1, "Push button status = %d\n", buf[0] & 0x01); 6310141cc406Sopenharmony_ci *theButtonStatus = ((buf[0] & 0x01) != 0); 6311141cc406Sopenharmony_ci 6312141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 6313141cc406Sopenharmony_ci} 6314141cc406Sopenharmony_ci 6315141cc406Sopenharmony_ci 6316141cc406Sopenharmony_ci 6317141cc406Sopenharmony_cistatic void 6318141cc406Sopenharmony_cifilter_resolution_list (Epson_Scanner * s) 6319141cc406Sopenharmony_ci{ 6320141cc406Sopenharmony_ci /* re-create the list */ 6321141cc406Sopenharmony_ci 6322141cc406Sopenharmony_ci if (s->val[OPT_LIMIT_RESOLUTION].w == SANE_TRUE) 6323141cc406Sopenharmony_ci { 6324141cc406Sopenharmony_ci /* copy the short list */ 6325141cc406Sopenharmony_ci 6326141cc406Sopenharmony_ci /* filter out all values that are not 300 or 400 dpi based */ 6327141cc406Sopenharmony_ci int i; 6328141cc406Sopenharmony_ci 6329141cc406Sopenharmony_ci int new_size = 0; 6330141cc406Sopenharmony_ci SANE_Bool is_correct_resolution = SANE_FALSE; 6331141cc406Sopenharmony_ci 6332141cc406Sopenharmony_ci for (i = 1; i <= s->hw->res_list_size; i++) 6333141cc406Sopenharmony_ci { 6334141cc406Sopenharmony_ci SANE_Word res; 6335141cc406Sopenharmony_ci res = s->hw->res_list[i]; 6336141cc406Sopenharmony_ci if ((res < 100) || (0 == (res % 300)) || (0 == (res % 400))) 6337141cc406Sopenharmony_ci { 6338141cc406Sopenharmony_ci /* add the value */ 6339141cc406Sopenharmony_ci new_size++; 6340141cc406Sopenharmony_ci 6341141cc406Sopenharmony_ci s->hw->resolution_list[new_size] = s->hw->res_list[i]; 6342141cc406Sopenharmony_ci 6343141cc406Sopenharmony_ci /* check for a valid current resolution */ 6344141cc406Sopenharmony_ci if (res == s->val[OPT_RESOLUTION].w) 6345141cc406Sopenharmony_ci { 6346141cc406Sopenharmony_ci is_correct_resolution = SANE_TRUE; 6347141cc406Sopenharmony_ci } 6348141cc406Sopenharmony_ci } 6349141cc406Sopenharmony_ci } 6350141cc406Sopenharmony_ci s->hw->resolution_list[0] = new_size; 6351141cc406Sopenharmony_ci 6352141cc406Sopenharmony_ci if (is_correct_resolution == SANE_FALSE) 6353141cc406Sopenharmony_ci { 6354141cc406Sopenharmony_ci for (i = 1; i <= new_size; i++) 6355141cc406Sopenharmony_ci { 6356141cc406Sopenharmony_ci if (s->val[OPT_RESOLUTION].w < s->hw->resolution_list[i]) 6357141cc406Sopenharmony_ci { 6358141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = s->hw->resolution_list[i]; 6359141cc406Sopenharmony_ci i = new_size + 1; 6360141cc406Sopenharmony_ci } 6361141cc406Sopenharmony_ci } 6362141cc406Sopenharmony_ci } 6363141cc406Sopenharmony_ci 6364141cc406Sopenharmony_ci } 6365141cc406Sopenharmony_ci else 6366141cc406Sopenharmony_ci { 6367141cc406Sopenharmony_ci /* copy the full list */ 6368141cc406Sopenharmony_ci s->hw->resolution_list[0] = s->hw->res_list_size; 6369141cc406Sopenharmony_ci memcpy (&(s->hw->resolution_list[1]), s->hw->res_list, 6370141cc406Sopenharmony_ci s->hw->res_list_size * sizeof (SANE_Word)); 6371141cc406Sopenharmony_ci } 6372141cc406Sopenharmony_ci} 6373141cc406Sopenharmony_ci 6374141cc406Sopenharmony_ci/**********************************************************************************/ 6375141cc406Sopenharmony_ci 6376141cc406Sopenharmony_ci/* 6377141cc406Sopenharmony_ci * SANE_Status sane_set_io_mode() 6378141cc406Sopenharmony_ci * 6379141cc406Sopenharmony_ci * not supported - for asynchronous I/O 6380141cc406Sopenharmony_ci */ 6381141cc406Sopenharmony_ci 6382141cc406Sopenharmony_ciSANE_Status 6383141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 6384141cc406Sopenharmony_ci{ 6385141cc406Sopenharmony_ci /* get rid of compiler warning */ 6386141cc406Sopenharmony_ci (void) handle; 6387141cc406Sopenharmony_ci (void) non_blocking; 6388141cc406Sopenharmony_ci 6389141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 6390141cc406Sopenharmony_ci} 6391141cc406Sopenharmony_ci 6392141cc406Sopenharmony_ci/* 6393141cc406Sopenharmony_ci * SANE_Status sane_get_select_fd() 6394141cc406Sopenharmony_ci * 6395141cc406Sopenharmony_ci * not supported - for asynchronous I/O 6396141cc406Sopenharmony_ci */ 6397141cc406Sopenharmony_ci 6398141cc406Sopenharmony_ciSANE_Status 6399141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 6400141cc406Sopenharmony_ci{ 6401141cc406Sopenharmony_ci /* get rid of compiler warnings */ 6402141cc406Sopenharmony_ci (void) handle; 6403141cc406Sopenharmony_ci (void) fd; 6404141cc406Sopenharmony_ci 6405141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 6406141cc406Sopenharmony_ci} 6407141cc406Sopenharmony_ci 6408141cc406Sopenharmony_ci/* 6409141cc406Sopenharmony_civim:ts=2:sw=2:cindent: 6410141cc406Sopenharmony_ci*/ 6411