1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci This file is part of the SANE package. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 19141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 22141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 23141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 24141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 25141cc406Sopenharmony_ci account of linking the SANE library code into it. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 28141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 29141cc406Sopenharmony_ci License. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 32141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 33141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 36141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 37141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci This file implements a SANE backend for Fujitsu ScanParner 15C 40141cc406Sopenharmony_ci flatbed/ADF scanners. It was derived from the COOLSCAN driver. 41141cc406Sopenharmony_ci Written by Randolph Bentson <bentson@holmsjoen.com> */ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* 44141cc406Sopenharmony_ci * Revision 1.17 2008/11/26 21:21:30 kitno-guest 45141cc406Sopenharmony_ci * * backend/ *.[ch]: nearly every backend used V_MAJOR 46141cc406Sopenharmony_ci * instead of SANE_CURRENT_MAJOR in sane_init() 47141cc406Sopenharmony_ci * * backend/snapscan.c: remove EXPECTED_VERSION check 48141cc406Sopenharmony_ci * since new SANE standard is forward compatible 49141cc406Sopenharmony_ci * 50141cc406Sopenharmony_ci * Revision 1.16 2008-07-26 03:53:44 kitno-guest 51141cc406Sopenharmony_ci * separate x-resolution from resolution, and update all backends that use 52141cc406Sopenharmony_ci * it, to prevent ui change 53141cc406Sopenharmony_ci * 54141cc406Sopenharmony_ci * Revision 1.15 2007-11-18 10:59:18 ellert-guest 55141cc406Sopenharmony_ci * Fix handling of valid "negative" PIDs 56141cc406Sopenharmony_ci * 57141cc406Sopenharmony_ci * Revision 1.14 2007-10-26 14:56:38 jblache 58141cc406Sopenharmony_ci * OPT_NUM_OPTS must be of type SANE_TYPE_INT. 59141cc406Sopenharmony_ci * 60141cc406Sopenharmony_ci * Revision 1.13 2006/03/29 20:48:50 hmg-guest 61141cc406Sopenharmony_ci * Fixed ADF support. Patch from Andreas Degert <ad@papyrus-gmbh.de>. 62141cc406Sopenharmony_ci * 63141cc406Sopenharmony_ci * Revision 1.12 2005/10/01 17:06:25 hmg-guest 64141cc406Sopenharmony_ci * Fixed some warnings (bug #302290). 65141cc406Sopenharmony_ci * 66141cc406Sopenharmony_ci * Revision 1.11 2005/07/15 18:12:49 hmg-guest 67141cc406Sopenharmony_ci * Better 4->8 bit depth expansion algorithm (from Mattias Ellert 68141cc406Sopenharmony_ci * <mattias.ellert@tsl.uu.se>). 69141cc406Sopenharmony_ci * 70141cc406Sopenharmony_ci * Revision 1.10 2004/10/06 15:59:40 hmg-guest 71141cc406Sopenharmony_ci * Don't eject medium twice after each page. 72141cc406Sopenharmony_ci * 73141cc406Sopenharmony_ci * Revision 1.9 2004/06/20 00:34:10 ellert-guest 74141cc406Sopenharmony_ci * Missed one... 75141cc406Sopenharmony_ci * 76141cc406Sopenharmony_ci * Revision 1.8 2004/05/29 10:27:47 hmg-guest 77141cc406Sopenharmony_ci * Fixed the fix of the sanei_thread fix (from Mattias Ellert). 78141cc406Sopenharmony_ci * 79141cc406Sopenharmony_ci * Revision 1.7 2004/05/28 18:52:53 hmg-guest 80141cc406Sopenharmony_ci * Fixed sanei_thread fix (bug #300634, by Mattias Ellert). 81141cc406Sopenharmony_ci * 82141cc406Sopenharmony_ci * Revision 1.6 2004/05/23 17:28:56 hmg-guest 83141cc406Sopenharmony_ci * Use sanei_thread instead of fork() in the unmaintained backends. 84141cc406Sopenharmony_ci * Patches from Mattias Ellert (bugs: 300635, 300634, 300633, 300629). 85141cc406Sopenharmony_ci * 86141cc406Sopenharmony_ci * Revision 1.5 2003/12/27 17:48:38 hmg-guest 87141cc406Sopenharmony_ci * Silenced some compilation warnings. 88141cc406Sopenharmony_ci * 89141cc406Sopenharmony_ci * Revision 1.4 2001/05/31 18:01:39 hmg 90141cc406Sopenharmony_ci * Fixed config_line[len-1] bug which could generate an access 91141cc406Sopenharmony_ci * violation if len==0. 92141cc406Sopenharmony_ci * Henning Meier-Geinitz <henning@meier-geinitz.de> 93141cc406Sopenharmony_ci * 94141cc406Sopenharmony_ci * Revision 1.3 2000/08/12 15:09:38 pere 95141cc406Sopenharmony_ci * Merge devel (v1.0.3) into head branch. 96141cc406Sopenharmony_ci * 97141cc406Sopenharmony_ci * Revision 1.1.2.6 2000/07/30 11:16:06 hmg 98141cc406Sopenharmony_ci * 2000-07-30 Henning Meier-Geinitz <hmg@gmx.de> 99141cc406Sopenharmony_ci * 100141cc406Sopenharmony_ci * * backend/mustek.*: Update to Mustek backend 1.0-95. Changed from 101141cc406Sopenharmony_ci * wait() to waitpid() and removed unused code. 102141cc406Sopenharmony_ci * * configure configure.in backend/m3096g.c backend/sp15c.c: Reverted 103141cc406Sopenharmony_ci * the V_REV patch. V_REV should not be used in backends. 104141cc406Sopenharmony_ci * 105141cc406Sopenharmony_ci * Revision 1.1.2.5 2000/07/29 21:38:13 hmg 106141cc406Sopenharmony_ci * 2000-07-29 Henning Meier-Geinitz <hmg@gmx.de> 107141cc406Sopenharmony_ci * 108141cc406Sopenharmony_ci * * backend/sp15.c backend/m3096g.c: Replace fgets with 109141cc406Sopenharmony_ci * sanei_config_read, return V_REV as part of version_code string 110141cc406Sopenharmony_ci * (patch from Randolph Bentson). 111141cc406Sopenharmony_ci * 112141cc406Sopenharmony_ci * Revision 1.1.2.4 2000/07/25 21:47:46 hmg 113141cc406Sopenharmony_ci * 2000-07-25 Henning Meier-Geinitz <hmg@gmx.de> 114141cc406Sopenharmony_ci * 115141cc406Sopenharmony_ci * * backend/snapscan.c: Use DBG(0, ...) instead of fprintf (stderr, ...). 116141cc406Sopenharmony_ci * * backend/abaton.c backend/agfafocus.c backend/apple.c backend/dc210.c 117141cc406Sopenharmony_ci * backend/dll.c backend/dmc.c backend/microtek2.c backend/pint.c 118141cc406Sopenharmony_ci * backend/qcam.c backend/ricoh.c backend/s9036.c backend/snapscan.c 119141cc406Sopenharmony_ci * backend/tamarack.c: Use sanei_config_read instead of fgets. 120141cc406Sopenharmony_ci * * backend/dc210.c backend/microtek.c backend/pnm.c: Added 121141cc406Sopenharmony_ci * #include "../include/sane/config.h". 122141cc406Sopenharmony_ci * * backend/dc25.c backend/m3096.c backend/sp15.c 123141cc406Sopenharmony_ci * backend/st400.c: Moved #include "../include/sane/config.h" to the beginning. 124141cc406Sopenharmony_ci * * AUTHORS: Changed agfa to agfafocus. 125141cc406Sopenharmony_ci * 126141cc406Sopenharmony_ci * Revision 1.1.2.3 2000/03/14 17:47:12 abel 127141cc406Sopenharmony_ci * new version of the Sharp backend added. 128141cc406Sopenharmony_ci * 129141cc406Sopenharmony_ci * Revision 1.1.2.2 2000/01/26 03:51:48 pere 130141cc406Sopenharmony_ci * Updated backends sp15c (v1.12) and m3096g (v1.11). 131141cc406Sopenharmony_ci * 132141cc406Sopenharmony_ci * Revision 1.12 2000/01/25 16:23:13 bentson 133141cc406Sopenharmony_ci * tab expansion; add one debug message 134141cc406Sopenharmony_ci * 135141cc406Sopenharmony_ci * Revision 1.11 2000/01/05 05:21:37 bentson 136141cc406Sopenharmony_ci * indent to barfable GNU style 137141cc406Sopenharmony_ci * 138141cc406Sopenharmony_ci * Revision 1.10 1999/12/06 17:36:55 bentson 139141cc406Sopenharmony_ci * show default value for scan size at the start 140141cc406Sopenharmony_ci * 141141cc406Sopenharmony_ci * Revision 1.9 1999/12/04 00:30:35 bentson 142141cc406Sopenharmony_ci * fold in 1.8.1.x versions 143141cc406Sopenharmony_ci * 144141cc406Sopenharmony_ci * Revision 1.8.1.2 1999/12/04 00:19:43 bentson 145141cc406Sopenharmony_ci * bunch of changes to complete MEDIA CHECK use 146141cc406Sopenharmony_ci * 147141cc406Sopenharmony_ci * Revision 1.8.1.1 1999/12/03 20:44:56 bentson 148141cc406Sopenharmony_ci * trial changes to use MEDIA CHECK command 149141cc406Sopenharmony_ci * 150141cc406Sopenharmony_ci * Revision 1.8 1999/12/03 18:30:56 bentson 151141cc406Sopenharmony_ci * cosmetic changes 152141cc406Sopenharmony_ci * 153141cc406Sopenharmony_ci * Revision 1.7 1999/11/24 20:09:25 bentson 154141cc406Sopenharmony_ci * fold in 1.6.1.x changes 155141cc406Sopenharmony_ci * 156141cc406Sopenharmony_ci * Revision 1.6.1.3 1999/11/24 15:56:48 bentson 157141cc406Sopenharmony_ci * remove some debugging; final :-) fix to option constraint processing 158141cc406Sopenharmony_ci * 159141cc406Sopenharmony_ci * Revision 1.6.1.2 1999/11/24 15:37:42 bentson 160141cc406Sopenharmony_ci * more constraint debugging 161141cc406Sopenharmony_ci * 162141cc406Sopenharmony_ci * Revision 1.6.1.1 1999/11/24 14:35:24 bentson 163141cc406Sopenharmony_ci * fix some of the constraint handling 164141cc406Sopenharmony_ci * 165141cc406Sopenharmony_ci * Revision 1.6 1999/11/23 18:48:27 bentson 166141cc406Sopenharmony_ci * add constraint checking and enforcement 167141cc406Sopenharmony_ci * 168141cc406Sopenharmony_ci * Revision 1.5 1999/11/23 08:26:03 bentson 169141cc406Sopenharmony_ci * basic color seems to work 170141cc406Sopenharmony_ci * 171141cc406Sopenharmony_ci * Revision 1.4 1999/11/23 06:41:26 bentson 172141cc406Sopenharmony_ci * 4-bit Grayscale works; now working on color 173141cc406Sopenharmony_ci * 174141cc406Sopenharmony_ci * Revision 1.3 1999/11/22 18:15:07 bentson 175141cc406Sopenharmony_ci * more work on color support 176141cc406Sopenharmony_ci * 177141cc406Sopenharmony_ci * Revision 1.2 1999/11/19 17:30:54 bentson 178141cc406Sopenharmony_ci * enhance control (works with xscanimage) 179141cc406Sopenharmony_ci * 180141cc406Sopenharmony_ci * Revision 1.1 1999/11/19 15:09:08 bentson 181141cc406Sopenharmony_ci * cribbed from m3096g 182141cc406Sopenharmony_ci * 183141cc406Sopenharmony_ci */ 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci/* SANE-FLOW-DIAGRAM 186141cc406Sopenharmony_ci 187141cc406Sopenharmony_ci - sane_init() : initialize backend, attach scanners 188141cc406Sopenharmony_ci . - sane_get_devices() : query list of scanner-devices 189141cc406Sopenharmony_ci . - sane_open() : open a particular scanner-device 190141cc406Sopenharmony_ci . . - sane_set_io_mode : set blocking-mode 191141cc406Sopenharmony_ci . . - sane_get_select_fd : get scanner-fd 192141cc406Sopenharmony_ci . . - sane_get_option_descriptor() : get option information 193141cc406Sopenharmony_ci . . - sane_control_option() : change option values 194141cc406Sopenharmony_ci . . 195141cc406Sopenharmony_ci . . - sane_start() : start image acquisition 196141cc406Sopenharmony_ci . . - sane_get_parameters() : returns actual scan-parameters 197141cc406Sopenharmony_ci . . - sane_read() : read image-data (from pipe) 198141cc406Sopenharmony_ci . . 199141cc406Sopenharmony_ci . . - sane_cancel() : cancel operation 200141cc406Sopenharmony_ci . - sane_close() : close opened scanner-device 201141cc406Sopenharmony_ci - sane_exit() : terminate use of backend 202141cc406Sopenharmony_ci */ 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 205141cc406Sopenharmony_ci 206141cc406Sopenharmony_ci#include "../include/sane/config.h" 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci#include <errno.h> 209141cc406Sopenharmony_ci#include <fcntl.h> 210141cc406Sopenharmony_ci#include <limits.h> 211141cc406Sopenharmony_ci#include <signal.h> 212141cc406Sopenharmony_ci#include <stdio.h> 213141cc406Sopenharmony_ci#include <stdlib.h> 214141cc406Sopenharmony_ci#include <string.h> 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_ci#include <sys/types.h> 217141cc406Sopenharmony_ci#include <unistd.h> 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 220141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 221141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 222141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 223141cc406Sopenharmony_ci#include "../include/sane/sanei_thread.h" 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci#include "sp15c-scsi.h" 226141cc406Sopenharmony_ci#include "sp15c.h" 227141cc406Sopenharmony_ci 228141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_cistatic const char negativeStr[] = "Negative"; 231141cc406Sopenharmony_cistatic const char positiveStr[] = "Positive"; 232141cc406Sopenharmony_cistatic SANE_String_Const type_list[] = 233141cc406Sopenharmony_ci{positiveStr, negativeStr, 0}; 234141cc406Sopenharmony_ci 235141cc406Sopenharmony_cistatic SANE_String_Const source_list[] = 236141cc406Sopenharmony_ci{"ADF", "FB", NULL}; 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_cistatic const SANE_Int resolution_list[] = 239141cc406Sopenharmony_ci{11, 0, 60, 75, 80, 100, 120, 150, 200, 240, 300, 600}; 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_cistatic const SANE_Int x_res_list[] = 242141cc406Sopenharmony_ci{11, 0, 60, 75, 80, 100, 120, 150, 200, 240, 300, 600}; 243141cc406Sopenharmony_ci 244141cc406Sopenharmony_cistatic const SANE_Int y_res_list[] = 245141cc406Sopenharmony_ci{11, 0, 60, 75, 80, 100, 120, 150, 200, 240, 300, 600}; 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_cistatic const char lineStr[] = SANE_VALUE_SCAN_MODE_LINEART; 248141cc406Sopenharmony_cistatic const char halfStr[] = SANE_VALUE_SCAN_MODE_HALFTONE; 249141cc406Sopenharmony_cistatic const char gray4Str[] = "4-bit Gray"; 250141cc406Sopenharmony_cistatic const char gray8Str[] = "8-bit Gray"; 251141cc406Sopenharmony_cistatic const char colorStr[] = SANE_VALUE_SCAN_MODE_COLOR; 252141cc406Sopenharmony_cistatic SANE_String_Const scan_mode_list[] = 253141cc406Sopenharmony_ci{lineStr, halfStr, gray4Str, gray8Str, colorStr, NULL}; 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci/* how do the following work? */ 256141cc406Sopenharmony_cistatic const SANE_Range brightness_range = 257141cc406Sopenharmony_ci{0, 255, 32}; 258141cc406Sopenharmony_cistatic const SANE_Range threshold_range = 259141cc406Sopenharmony_ci{0, 255, 4}; 260141cc406Sopenharmony_cistatic const SANE_Range x_range = 261141cc406Sopenharmony_ci{0, SANE_FIX (216), 1}; 262141cc406Sopenharmony_cistatic const SANE_Range y_range_fb = 263141cc406Sopenharmony_ci{0, SANE_FIX (295), 1}; 264141cc406Sopenharmony_cistatic const SANE_Range y_range_adf = 265141cc406Sopenharmony_ci{0, SANE_FIX (356), 1}; 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci/* ################# externally visible routines ################{ */ 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ciSANE_Status /* looks like frontend ignores results */ 271141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 272141cc406Sopenharmony_ci{ 273141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 274141cc406Sopenharmony_ci size_t len; 275141cc406Sopenharmony_ci FILE *fp; 276141cc406Sopenharmony_ci (void) authorize; /* silence compilation warnings */ 277141cc406Sopenharmony_ci 278141cc406Sopenharmony_ci DBG_INIT (); 279141cc406Sopenharmony_ci DBG (10, "sane_init\n"); 280141cc406Sopenharmony_ci 281141cc406Sopenharmony_ci sanei_thread_init (); 282141cc406Sopenharmony_ci 283141cc406Sopenharmony_ci if (version_code) 284141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 285141cc406Sopenharmony_ci fp = sanei_config_open (SP15C_CONFIG_FILE); 286141cc406Sopenharmony_ci if (!fp) 287141cc406Sopenharmony_ci { 288141cc406Sopenharmony_ci attach_scanner ("/dev/scanner", 0); /* no config-file: /dev/scanner */ 289141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 290141cc406Sopenharmony_ci } 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 293141cc406Sopenharmony_ci { 294141cc406Sopenharmony_ci if (dev_name[0] == '#') 295141cc406Sopenharmony_ci continue; 296141cc406Sopenharmony_ci len = strlen (dev_name); 297141cc406Sopenharmony_ci if (!len) 298141cc406Sopenharmony_ci continue; 299141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 300141cc406Sopenharmony_ci } 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci fclose (fp); 303141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 304141cc406Sopenharmony_ci} /* sane_init */ 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ciSANE_Status 308141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 309141cc406Sopenharmony_ci{ 310141cc406Sopenharmony_ci struct sp15c *dev; 311141cc406Sopenharmony_ci int i; 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci (void) local_only; /* silence compilation warnings */ 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci DBG (10, "sane_get_devices\n"); 316141cc406Sopenharmony_ci 317141cc406Sopenharmony_ci if (devlist) 318141cc406Sopenharmony_ci free (devlist); 319141cc406Sopenharmony_ci devlist = calloc (num_devices + 1, sizeof (devlist[0])); 320141cc406Sopenharmony_ci if (!devlist) 321141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 322141cc406Sopenharmony_ci 323141cc406Sopenharmony_ci for (dev = first_dev, i = 0; i < num_devices; dev = dev->next) 324141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 325141cc406Sopenharmony_ci devlist[i++] = 0; 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci *device_list = devlist; 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 330141cc406Sopenharmony_ci} /* sane_get_devices */ 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ciSANE_Status 334141cc406Sopenharmony_cisane_open (SANE_String_Const name, SANE_Handle * handle) 335141cc406Sopenharmony_ci{ 336141cc406Sopenharmony_ci struct sp15c *dev = first_dev; 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci (void) name; /* silence compilation warnings */ 339141cc406Sopenharmony_ci /* Strange, name is not used? */ 340141cc406Sopenharmony_ci 341141cc406Sopenharmony_ci DBG (10, "sane_open\n"); 342141cc406Sopenharmony_ci 343141cc406Sopenharmony_ci if (!dev) 344141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci init_options (dev); 347141cc406Sopenharmony_ci *handle = dev; 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci dev->use_adf = SANE_TRUE; 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci dev->x_res = 200; 352141cc406Sopenharmony_ci dev->y_res = 200; 353141cc406Sopenharmony_ci dev->tl_x = 0; 354141cc406Sopenharmony_ci dev->tl_y = 0; 355141cc406Sopenharmony_ci dev->br_x = 1200 * 17 / 2; 356141cc406Sopenharmony_ci dev->br_y = 1200 * 11; 357141cc406Sopenharmony_ci dev->brightness = 128; 358141cc406Sopenharmony_ci dev->threshold = 128; 359141cc406Sopenharmony_ci dev->contrast = 128; 360141cc406Sopenharmony_ci dev->composition = WD_comp_LA; 361141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; 362141cc406Sopenharmony_ci dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_DETECT 363141cc406Sopenharmony_ci | SANE_CAP_SOFT_SELECT; 364141cc406Sopenharmony_ci dev->bitsperpixel = 1; 365141cc406Sopenharmony_ci dev->halftone = 0; 366141cc406Sopenharmony_ci dev->rif = 0; 367141cc406Sopenharmony_ci dev->bitorder = 0; 368141cc406Sopenharmony_ci dev->compress_type = 0; 369141cc406Sopenharmony_ci dev->compress_arg = 0; 370141cc406Sopenharmony_ci dev->vendor_id_code = 0; 371141cc406Sopenharmony_ci dev->outline = 0; 372141cc406Sopenharmony_ci dev->emphasis = 0; 373141cc406Sopenharmony_ci dev->auto_sep = 0; 374141cc406Sopenharmony_ci dev->mirroring = 0; 375141cc406Sopenharmony_ci dev->var_rate_dyn_thresh = 0; 376141cc406Sopenharmony_ci dev->white_level_follow = 0; 377141cc406Sopenharmony_ci dev->paper_size = 0x87; 378141cc406Sopenharmony_ci dev->paper_width_X = 1200 * 17 / 2; 379141cc406Sopenharmony_ci dev->paper_length_Y = 1200 * 11; 380141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint.range = &y_range_adf; 381141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint.range = &y_range_adf; 382141cc406Sopenharmony_ci adjust_width (dev, 0); 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 385141cc406Sopenharmony_ci} /* sane_open */ 386141cc406Sopenharmony_ci 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ciSANE_Status 389141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) 390141cc406Sopenharmony_ci{ 391141cc406Sopenharmony_ci (void) h; 392141cc406Sopenharmony_ci (void) non_blocking; /* silence compilation warnings */ 393141cc406Sopenharmony_ci 394141cc406Sopenharmony_ci DBG (10, "sane_set_io_mode\n"); 395141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 396141cc406Sopenharmony_ci} /* sane_set_io_mode */ 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ciSANE_Status 400141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle h, SANE_Int * fdp) 401141cc406Sopenharmony_ci{ 402141cc406Sopenharmony_ci (void) h; 403141cc406Sopenharmony_ci (void) fdp; /* silence compilation warnings */ 404141cc406Sopenharmony_ci 405141cc406Sopenharmony_ci DBG (10, "sane_get_select_fd\n"); 406141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 407141cc406Sopenharmony_ci} /* sane_get_select_fd */ 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 411141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 412141cc406Sopenharmony_ci{ 413141cc406Sopenharmony_ci struct sp15c *scanner = handle; 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci DBG (10, "sane_get_option_descriptor: \"%s\"\n", 416141cc406Sopenharmony_ci scanner->opt[option].name); 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 419141cc406Sopenharmony_ci return 0; 420141cc406Sopenharmony_ci return &scanner->opt[option]; 421141cc406Sopenharmony_ci} /* sane_get_option_descriptor */ 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_ci 424141cc406Sopenharmony_ciSANE_Status 425141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 426141cc406Sopenharmony_ci SANE_Action action, void *val, 427141cc406Sopenharmony_ci SANE_Int * info) 428141cc406Sopenharmony_ci{ 429141cc406Sopenharmony_ci struct sp15c *scanner = handle; 430141cc406Sopenharmony_ci SANE_Status status; 431141cc406Sopenharmony_ci SANE_Word cap; 432141cc406Sopenharmony_ci 433141cc406Sopenharmony_ci if (info) 434141cc406Sopenharmony_ci *info = 0; 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci if (scanner->scanning == SANE_TRUE) 437141cc406Sopenharmony_ci { 438141cc406Sopenharmony_ci DBG (5, "sane_control_option: device busy\n"); 439141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 440141cc406Sopenharmony_ci } 441141cc406Sopenharmony_ci 442141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) 443141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci cap = scanner->opt[option].cap; 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 448141cc406Sopenharmony_ci { 449141cc406Sopenharmony_ci DBG (10, "sane_control_option: get value \"%s\"\n", 450141cc406Sopenharmony_ci scanner->opt[option].name); 451141cc406Sopenharmony_ci DBG (11, "\tcap = %d\n", cap); 452141cc406Sopenharmony_ci 453141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 454141cc406Sopenharmony_ci { 455141cc406Sopenharmony_ci DBG (10, "\tinactive\n"); 456141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 457141cc406Sopenharmony_ci } 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci switch (option) 460141cc406Sopenharmony_ci { 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci case OPT_NUM_OPTS: 463141cc406Sopenharmony_ci *(SANE_Word *) val = NUM_OPTIONS; 464141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_ci case OPT_SOURCE: 467141cc406Sopenharmony_ci if (scanner->use_adf == SANE_TRUE) 468141cc406Sopenharmony_ci { 469141cc406Sopenharmony_ci strcpy (val, "ADF"); 470141cc406Sopenharmony_ci } 471141cc406Sopenharmony_ci else 472141cc406Sopenharmony_ci { 473141cc406Sopenharmony_ci strcpy (val, "FB"); 474141cc406Sopenharmony_ci } 475141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 476141cc406Sopenharmony_ci 477141cc406Sopenharmony_ci case OPT_MODE: 478141cc406Sopenharmony_ci switch (scanner->composition) 479141cc406Sopenharmony_ci { 480141cc406Sopenharmony_ci case WD_comp_LA: 481141cc406Sopenharmony_ci strcpy (val, lineStr); 482141cc406Sopenharmony_ci break; 483141cc406Sopenharmony_ci case WD_comp_HT: 484141cc406Sopenharmony_ci strcpy (val, halfStr); 485141cc406Sopenharmony_ci break; 486141cc406Sopenharmony_ci case WD_comp_G4: 487141cc406Sopenharmony_ci strcpy (val, gray4Str); 488141cc406Sopenharmony_ci break; 489141cc406Sopenharmony_ci case WD_comp_G8: 490141cc406Sopenharmony_ci strcpy (val, gray8Str); 491141cc406Sopenharmony_ci break; 492141cc406Sopenharmony_ci case WD_comp_MC: 493141cc406Sopenharmony_ci strcpy (val, colorStr); 494141cc406Sopenharmony_ci break; 495141cc406Sopenharmony_ci default: 496141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 497141cc406Sopenharmony_ci } 498141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci case OPT_TYPE: 501141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 502141cc406Sopenharmony_ci 503141cc406Sopenharmony_ci case OPT_PRESCAN: 504141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 505141cc406Sopenharmony_ci 506141cc406Sopenharmony_ci case OPT_X_RES: 507141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->x_res; 508141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci case OPT_Y_RES: 511141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->y_res; 512141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci case OPT_PREVIEW_RES: 515141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci case OPT_TL_X: 518141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_x)); 519141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci case OPT_TL_Y: 522141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_y)); 523141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci case OPT_BR_X: 526141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_x)); 527141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci case OPT_BR_Y: 530141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_y)); 531141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ci case OPT_AVERAGING: 534141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 537141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->brightness; 538141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci case OPT_THRESHOLD: 541141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->threshold; 542141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 543141cc406Sopenharmony_ci 544141cc406Sopenharmony_ci case OPT_PREVIEW: 545141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 546141cc406Sopenharmony_ci 547141cc406Sopenharmony_ci } 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci } 550141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 551141cc406Sopenharmony_ci { 552141cc406Sopenharmony_ci DBG (10, "sane_control_option: set value \"%s\"\n", 553141cc406Sopenharmony_ci scanner->opt[option].name); 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 556141cc406Sopenharmony_ci { 557141cc406Sopenharmony_ci DBG (10, "\tinactive\n"); 558141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 559141cc406Sopenharmony_ci } 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 562141cc406Sopenharmony_ci { 563141cc406Sopenharmony_ci DBG (10, "\tnot settable\n"); 564141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 565141cc406Sopenharmony_ci } 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci status = sanei_constrain_value (scanner->opt + option, val, info); 568141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 569141cc406Sopenharmony_ci { 570141cc406Sopenharmony_ci DBG (10, "\tbad value\n"); 571141cc406Sopenharmony_ci return status; 572141cc406Sopenharmony_ci } 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci switch (option) 575141cc406Sopenharmony_ci { 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci case OPT_NUM_OPTS: 578141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 579141cc406Sopenharmony_ci 580141cc406Sopenharmony_ci case OPT_SOURCE: 581141cc406Sopenharmony_ci if (strcmp (val, "ADF") == 0) 582141cc406Sopenharmony_ci { 583141cc406Sopenharmony_ci if (scanner->use_adf == SANE_TRUE) 584141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 585141cc406Sopenharmony_ci scanner->use_adf = SANE_TRUE; 586141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].constraint.range = &y_range_adf; 587141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].constraint.range = &y_range_adf; 588141cc406Sopenharmony_ci apply_constraints (scanner, OPT_TL_Y, &scanner->tl_y, info); 589141cc406Sopenharmony_ci apply_constraints (scanner, OPT_BR_Y, &scanner->br_y, info); 590141cc406Sopenharmony_ci } 591141cc406Sopenharmony_ci else if (strcmp (val, "FB") == 0) 592141cc406Sopenharmony_ci { 593141cc406Sopenharmony_ci if (scanner->use_adf == SANE_FALSE) 594141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 595141cc406Sopenharmony_ci scanner->use_adf = SANE_FALSE; 596141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].constraint.range = &y_range_fb; 597141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].constraint.range = &y_range_fb; 598141cc406Sopenharmony_ci apply_constraints (scanner, OPT_TL_Y, &scanner->tl_y, info); 599141cc406Sopenharmony_ci apply_constraints (scanner, OPT_BR_Y, &scanner->br_y, info); 600141cc406Sopenharmony_ci } 601141cc406Sopenharmony_ci else 602141cc406Sopenharmony_ci { 603141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 604141cc406Sopenharmony_ci } 605141cc406Sopenharmony_ci if (info) 606141cc406Sopenharmony_ci { 607141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 608141cc406Sopenharmony_ci } 609141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci case OPT_MODE: 612141cc406Sopenharmony_ci if (strcmp (val, lineStr) == 0) 613141cc406Sopenharmony_ci { 614141cc406Sopenharmony_ci if (scanner->composition == WD_comp_LA) 615141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 616141cc406Sopenharmony_ci scanner->composition = WD_comp_LA; 617141cc406Sopenharmony_ci scanner->bitsperpixel = 1; 618141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; 619141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_DETECT 620141cc406Sopenharmony_ci | SANE_CAP_SOFT_SELECT; 621141cc406Sopenharmony_ci scanner->vendor_id_code = 0; 622141cc406Sopenharmony_ci } 623141cc406Sopenharmony_ci else if (strcmp (val, halfStr) == 0) 624141cc406Sopenharmony_ci { 625141cc406Sopenharmony_ci if (scanner->composition == WD_comp_HT) 626141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 627141cc406Sopenharmony_ci scanner->composition = WD_comp_HT; 628141cc406Sopenharmony_ci scanner->bitsperpixel = 1; 629141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_DETECT 630141cc406Sopenharmony_ci | SANE_CAP_SOFT_SELECT; 631141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; 632141cc406Sopenharmony_ci scanner->vendor_id_code = 0; 633141cc406Sopenharmony_ci } 634141cc406Sopenharmony_ci else if (strcmp (val, gray4Str) == 0) 635141cc406Sopenharmony_ci { 636141cc406Sopenharmony_ci if (scanner->composition == WD_comp_G4) 637141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 638141cc406Sopenharmony_ci scanner->composition = WD_comp_G4; 639141cc406Sopenharmony_ci scanner->bitsperpixel = 4; 640141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; 641141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; 642141cc406Sopenharmony_ci scanner->vendor_id_code = 0; 643141cc406Sopenharmony_ci } 644141cc406Sopenharmony_ci else if (strcmp (val, gray8Str) == 0) 645141cc406Sopenharmony_ci { 646141cc406Sopenharmony_ci if (scanner->composition == WD_comp_G8) 647141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 648141cc406Sopenharmony_ci scanner->composition = WD_comp_G8; 649141cc406Sopenharmony_ci scanner->bitsperpixel = 8; 650141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; 651141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; 652141cc406Sopenharmony_ci scanner->vendor_id_code = 0; 653141cc406Sopenharmony_ci } 654141cc406Sopenharmony_ci else if (strcmp (val, colorStr) == 0) 655141cc406Sopenharmony_ci { 656141cc406Sopenharmony_ci if (scanner->composition == WD_comp_MC) 657141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 658141cc406Sopenharmony_ci scanner->composition = WD_comp_MC; 659141cc406Sopenharmony_ci scanner->bitsperpixel = 8; 660141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; 661141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; 662141cc406Sopenharmony_ci scanner->vendor_id_code = 0xff; 663141cc406Sopenharmony_ci } 664141cc406Sopenharmony_ci else 665141cc406Sopenharmony_ci { 666141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 667141cc406Sopenharmony_ci } 668141cc406Sopenharmony_ci if (info) 669141cc406Sopenharmony_ci { 670141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 671141cc406Sopenharmony_ci } 672141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 673141cc406Sopenharmony_ci 674141cc406Sopenharmony_ci case OPT_TYPE: 675141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci case OPT_PRESCAN: 678141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci case OPT_X_RES: 681141cc406Sopenharmony_ci scanner->x_res = (*(SANE_Word *) val); 682141cc406Sopenharmony_ci adjust_width (scanner, info); 683141cc406Sopenharmony_ci if (info) 684141cc406Sopenharmony_ci { 685141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 686141cc406Sopenharmony_ci } 687141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci case OPT_Y_RES: 690141cc406Sopenharmony_ci scanner->y_res = (*(SANE_Word *) val); 691141cc406Sopenharmony_ci if (info) 692141cc406Sopenharmony_ci { 693141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 694141cc406Sopenharmony_ci } 695141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_ci case OPT_PREVIEW_RES: 698141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci case OPT_TL_X: 701141cc406Sopenharmony_ci scanner->tl_x = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 702141cc406Sopenharmony_ci adjust_width (scanner, info); 703141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_x)); 704141cc406Sopenharmony_ci if (info) 705141cc406Sopenharmony_ci { 706141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; 707141cc406Sopenharmony_ci } 708141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci case OPT_TL_Y: 711141cc406Sopenharmony_ci scanner->tl_y = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 712141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_y)); 713141cc406Sopenharmony_ci if (info) 714141cc406Sopenharmony_ci { 715141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; 716141cc406Sopenharmony_ci } 717141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 718141cc406Sopenharmony_ci 719141cc406Sopenharmony_ci case OPT_BR_X: 720141cc406Sopenharmony_ci scanner->br_x = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 721141cc406Sopenharmony_ci adjust_width (scanner, info); 722141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_x)); 723141cc406Sopenharmony_ci if (info) 724141cc406Sopenharmony_ci { 725141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; 726141cc406Sopenharmony_ci } 727141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 728141cc406Sopenharmony_ci 729141cc406Sopenharmony_ci case OPT_BR_Y: 730141cc406Sopenharmony_ci scanner->br_y = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 731141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_y)); 732141cc406Sopenharmony_ci if (info) 733141cc406Sopenharmony_ci { 734141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; 735141cc406Sopenharmony_ci } 736141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_ci case OPT_AVERAGING: 739141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 742141cc406Sopenharmony_ci scanner->brightness = *(SANE_Word *) val; 743141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 744141cc406Sopenharmony_ci 745141cc406Sopenharmony_ci case OPT_THRESHOLD: 746141cc406Sopenharmony_ci scanner->threshold = *(SANE_Word *) val; 747141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci } /* switch */ 750141cc406Sopenharmony_ci } /* else */ 751141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 752141cc406Sopenharmony_ci} /* sane_control_option */ 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_ciSANE_Status 756141cc406Sopenharmony_cisane_start (SANE_Handle handle) 757141cc406Sopenharmony_ci{ 758141cc406Sopenharmony_ci struct sp15c *scanner = handle; 759141cc406Sopenharmony_ci int fds[2]; 760141cc406Sopenharmony_ci int ret; 761141cc406Sopenharmony_ci 762141cc406Sopenharmony_ci DBG (10, "sane_start\n"); 763141cc406Sopenharmony_ci if (scanner->scanning == SANE_TRUE) 764141cc406Sopenharmony_ci { 765141cc406Sopenharmony_ci DBG (5, "sane_start: device busy\n"); 766141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 767141cc406Sopenharmony_ci } 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci if (scanner->sfd < 0) 770141cc406Sopenharmony_ci { /* first call */ 771141cc406Sopenharmony_ci if (sanei_scsi_open (scanner->sane.name, &(scanner->sfd), 772141cc406Sopenharmony_ci sense_handler, 0) != SANE_STATUS_GOOD) 773141cc406Sopenharmony_ci { 774141cc406Sopenharmony_ci DBG (1, "sane_start: open of %s failed:\n", 775141cc406Sopenharmony_ci scanner->sane.name); 776141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 777141cc406Sopenharmony_ci } 778141cc406Sopenharmony_ci } 779141cc406Sopenharmony_ci scanner->scanning = SANE_TRUE; 780141cc406Sopenharmony_ci 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci if ((ret = sp15c_check_values (scanner)) != 0) 783141cc406Sopenharmony_ci { /* Verify values */ 784141cc406Sopenharmony_ci DBG (1, "sane_start: ERROR: invalid scan-values\n"); 785141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 786141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 787141cc406Sopenharmony_ci scanner->sfd = -1; 788141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 789141cc406Sopenharmony_ci } 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_ci if ((ret = sp15c_grab_scanner (scanner))) 792141cc406Sopenharmony_ci { 793141cc406Sopenharmony_ci DBG (5, "sane_start: unable to reserve scanner\n"); 794141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 795141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 796141cc406Sopenharmony_ci scanner->sfd = -1; 797141cc406Sopenharmony_ci return ret; 798141cc406Sopenharmony_ci } 799141cc406Sopenharmony_ci 800141cc406Sopenharmony_ci if ((ret = sp15c_set_window_param (scanner, 0))) 801141cc406Sopenharmony_ci { 802141cc406Sopenharmony_ci DBG (5, "sane_start: ERROR: failed to set window\n"); 803141cc406Sopenharmony_ci sp15c_free_scanner (scanner); 804141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 805141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 806141cc406Sopenharmony_ci scanner->sfd = -1; 807141cc406Sopenharmony_ci return ret; 808141cc406Sopenharmony_ci } 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci /* Since the SET WINDOW can specify the use of the ADF, and since the 811141cc406Sopenharmony_ci ScanPartner 15C automatically pre-loads sheets from the ADF, it 812141cc406Sopenharmony_ci is only necessary to see if any paper is available. The OEM 813141cc406Sopenharmony_ci Manual offers the OBJECT POSITION command, but it causes the 814141cc406Sopenharmony_ci carrier unit into a "homing" cycle. The undocumented MEDIA CHECK 815141cc406Sopenharmony_ci command avoids the "homing" cycle. (Note the SET WINDOW command 816141cc406Sopenharmony_ci had to use the color scanning vendor unique parameters, regardless 817141cc406Sopenharmony_ci of scanning mode, so that it could invoke the ADF.) */ 818141cc406Sopenharmony_ci if (scanner->use_adf == SANE_TRUE 819141cc406Sopenharmony_ci && (ret = sp15c_media_check (scanner))) 820141cc406Sopenharmony_ci { 821141cc406Sopenharmony_ci DBG (5, "sane_start: WARNING: ADF empty\n"); 822141cc406Sopenharmony_ci sp15c_free_scanner (scanner); 823141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 824141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 825141cc406Sopenharmony_ci scanner->sfd = -1; 826141cc406Sopenharmony_ci return ret; 827141cc406Sopenharmony_ci } 828141cc406Sopenharmony_ci 829141cc406Sopenharmony_ci swap_res (scanner); 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci DBG (10, "\tbytes per line = %d\n", bytes_per_line (scanner)); 832141cc406Sopenharmony_ci DBG (10, "\tpixels_per_line = %d\n", pixels_per_line (scanner)); 833141cc406Sopenharmony_ci DBG (10, "\tlines = %d\n", lines_per_scan (scanner)); 834141cc406Sopenharmony_ci DBG (10, "\tbrightness (halftone) = %d\n", scanner->brightness); 835141cc406Sopenharmony_ci DBG (10, "\tthreshold (line art) = %d\n", scanner->threshold); 836141cc406Sopenharmony_ci 837141cc406Sopenharmony_ci if (scanner->composition == WD_comp_MC 838141cc406Sopenharmony_ci && (ret = sp15c_start_scan (scanner))) 839141cc406Sopenharmony_ci { 840141cc406Sopenharmony_ci DBG (5, "sane_start: start_scan failed\n"); 841141cc406Sopenharmony_ci sp15c_free_scanner (scanner); 842141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 843141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 844141cc406Sopenharmony_ci scanner->sfd = -1; 845141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 846141cc406Sopenharmony_ci } 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */ 849141cc406Sopenharmony_ci if (pipe (fds) < 0) 850141cc406Sopenharmony_ci { 851141cc406Sopenharmony_ci DBG (1, "ERROR: could not create pipe\n"); 852141cc406Sopenharmony_ci swap_res (scanner); 853141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 854141cc406Sopenharmony_ci sp15c_free_scanner (scanner); 855141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 856141cc406Sopenharmony_ci scanner->sfd = -1; 857141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 858141cc406Sopenharmony_ci } 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci scanner->pipe = fds[0]; 861141cc406Sopenharmony_ci scanner->reader_pipe = fds[1]; 862141cc406Sopenharmony_ci scanner->reader_pid = sanei_thread_begin (reader_process, (void *) scanner); 863141cc406Sopenharmony_ci 864141cc406Sopenharmony_ci if (sanei_thread_is_forked ()) 865141cc406Sopenharmony_ci close (scanner->reader_pipe); 866141cc406Sopenharmony_ci 867141cc406Sopenharmony_ci DBG (10, "sane_start: ok\n"); 868141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 869141cc406Sopenharmony_ci} /* sane_start */ 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_ci 872141cc406Sopenharmony_ciSANE_Status 873141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 874141cc406Sopenharmony_ci{ 875141cc406Sopenharmony_ci struct sp15c *scanner = handle; 876141cc406Sopenharmony_ci 877141cc406Sopenharmony_ci DBG (10, "sane_get_parameters\n"); 878141cc406Sopenharmony_ci if (scanner->composition == WD_comp_MC) 879141cc406Sopenharmony_ci { 880141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; 881141cc406Sopenharmony_ci params->depth = 8; 882141cc406Sopenharmony_ci } 883141cc406Sopenharmony_ci else if (scanner->composition == WD_comp_LA 884141cc406Sopenharmony_ci || scanner->composition == WD_comp_HT) 885141cc406Sopenharmony_ci { 886141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 887141cc406Sopenharmony_ci params->depth = 1; 888141cc406Sopenharmony_ci } 889141cc406Sopenharmony_ci else 890141cc406Sopenharmony_ci { 891141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 892141cc406Sopenharmony_ci params->depth = 8; 893141cc406Sopenharmony_ci } 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ci params->pixels_per_line = pixels_per_line (scanner); 896141cc406Sopenharmony_ci params->lines = lines_per_scan (scanner); 897141cc406Sopenharmony_ci params->bytes_per_line = bytes_per_line (scanner); 898141cc406Sopenharmony_ci params->last_frame = 1; 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci DBG (10, "\tdepth %d\n", params->depth); 901141cc406Sopenharmony_ci DBG (10, "\tlines %d\n", params->lines); 902141cc406Sopenharmony_ci DBG (10, "\tpixels_per_line %d\n", params->pixels_per_line); 903141cc406Sopenharmony_ci DBG (10, "\tbytes_per_line %d\n", params->bytes_per_line); 904141cc406Sopenharmony_ci/*************************/ 905141cc406Sopenharmony_ci DBG (10, "\tlength %d\n", scanner->br_y - scanner->tl_y); 906141cc406Sopenharmony_ci DBG (10, "\t(nom.) width %d\n", scanner->br_x - scanner->tl_x); 907141cc406Sopenharmony_ci DBG (10, "\tx res %d\n", scanner->x_res); 908141cc406Sopenharmony_ci DBG (10, "\ty res %d\n", scanner->y_res); 909141cc406Sopenharmony_ci/*************************/ 910141cc406Sopenharmony_ci 911141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 912141cc406Sopenharmony_ci} /* sane_get_parameters */ 913141cc406Sopenharmony_ci 914141cc406Sopenharmony_ci 915141cc406Sopenharmony_ciSANE_Status 916141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, 917141cc406Sopenharmony_ci SANE_Int max_len, SANE_Int * len) 918141cc406Sopenharmony_ci{ 919141cc406Sopenharmony_ci struct sp15c *scanner = handle; 920141cc406Sopenharmony_ci ssize_t nread; 921141cc406Sopenharmony_ci 922141cc406Sopenharmony_ci DBG (10, "sane_read\n"); 923141cc406Sopenharmony_ci *len = 0; 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci nread = read (scanner->pipe, buf, max_len); 926141cc406Sopenharmony_ci DBG (10, "sane_read: read %ld bytes of %ld\n", 927141cc406Sopenharmony_ci (long) nread, (long) max_len); 928141cc406Sopenharmony_ci 929141cc406Sopenharmony_ci if (scanner->scanning == SANE_FALSE) 930141cc406Sopenharmony_ci { 931141cc406Sopenharmony_ci /* PREDICATE WAS (!(scanner->scanning)) */ 932141cc406Sopenharmony_ci return do_cancel (scanner); 933141cc406Sopenharmony_ci } 934141cc406Sopenharmony_ci 935141cc406Sopenharmony_ci if (nread < 0) 936141cc406Sopenharmony_ci { 937141cc406Sopenharmony_ci if (errno == EAGAIN) 938141cc406Sopenharmony_ci { 939141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 940141cc406Sopenharmony_ci } 941141cc406Sopenharmony_ci else 942141cc406Sopenharmony_ci { 943141cc406Sopenharmony_ci do_cancel (scanner); 944141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 945141cc406Sopenharmony_ci } 946141cc406Sopenharmony_ci } 947141cc406Sopenharmony_ci 948141cc406Sopenharmony_ci *len = nread; 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci if (nread == 0) 951141cc406Sopenharmony_ci return do_eof (scanner); /* close pipe */ 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 954141cc406Sopenharmony_ci} /* sane_read */ 955141cc406Sopenharmony_ci 956141cc406Sopenharmony_ci 957141cc406Sopenharmony_civoid 958141cc406Sopenharmony_cisane_cancel (SANE_Handle h) 959141cc406Sopenharmony_ci{ 960141cc406Sopenharmony_ci DBG (10, "sane_cancel\n"); 961141cc406Sopenharmony_ci do_cancel ((struct sp15c *) h); 962141cc406Sopenharmony_ci} /* sane_cancel */ 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_civoid 966141cc406Sopenharmony_cisane_close (SANE_Handle handle) 967141cc406Sopenharmony_ci{ 968141cc406Sopenharmony_ci DBG (10, "sane_close\n"); 969141cc406Sopenharmony_ci if (((struct sp15c *) handle)->scanning == SANE_TRUE) 970141cc406Sopenharmony_ci do_cancel (handle); 971141cc406Sopenharmony_ci} /* sane_close */ 972141cc406Sopenharmony_ci 973141cc406Sopenharmony_ci 974141cc406Sopenharmony_civoid 975141cc406Sopenharmony_cisane_exit (void) 976141cc406Sopenharmony_ci{ 977141cc406Sopenharmony_ci struct sp15c *dev, *next; 978141cc406Sopenharmony_ci 979141cc406Sopenharmony_ci DBG (10, "sane_exit\n"); 980141cc406Sopenharmony_ci 981141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 982141cc406Sopenharmony_ci { 983141cc406Sopenharmony_ci next = dev->next; 984141cc406Sopenharmony_ci free (dev->devicename); 985141cc406Sopenharmony_ci free (dev->buffer); 986141cc406Sopenharmony_ci free (dev); 987141cc406Sopenharmony_ci } 988141cc406Sopenharmony_ci 989141cc406Sopenharmony_ci if (devlist) 990141cc406Sopenharmony_ci free (devlist); 991141cc406Sopenharmony_ci} /* sane_exit */ 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci/* }################ internal (support) routines ################{ */ 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_cistatic SANE_Status 996141cc406Sopenharmony_ciattach_scanner (const char *devicename, struct sp15c **devp) 997141cc406Sopenharmony_ci{ 998141cc406Sopenharmony_ci struct sp15c *dev; 999141cc406Sopenharmony_ci int sfd; 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci DBG (15, "attach_scanner: %s\n", devicename); 1002141cc406Sopenharmony_ci 1003141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1004141cc406Sopenharmony_ci { 1005141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 1006141cc406Sopenharmony_ci { 1007141cc406Sopenharmony_ci if (devp) 1008141cc406Sopenharmony_ci { 1009141cc406Sopenharmony_ci *devp = dev; 1010141cc406Sopenharmony_ci } 1011141cc406Sopenharmony_ci DBG (5, "attach_scanner: scanner already attached (is ok)!\n"); 1012141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1013141cc406Sopenharmony_ci } 1014141cc406Sopenharmony_ci } 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci DBG (15, "attach_scanner: opening %s\n", devicename); 1017141cc406Sopenharmony_ci if (sanei_scsi_open (devicename, &sfd, sense_handler, 0) != 0) 1018141cc406Sopenharmony_ci { 1019141cc406Sopenharmony_ci DBG (5, "attach_scanner: open failed\n"); 1020141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1021141cc406Sopenharmony_ci } 1022141cc406Sopenharmony_ci 1023141cc406Sopenharmony_ci if (NULL == (dev = malloc (sizeof (*dev)))) 1024141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci dev->row_bufsize = (sanei_scsi_max_request_size < (64 * 1024)) 1027141cc406Sopenharmony_ci ? sanei_scsi_max_request_size 1028141cc406Sopenharmony_ci : 64 * 1024; 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci if ((dev->buffer = malloc (dev->row_bufsize)) == NULL) 1031141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ci dev->devicename = strdup (devicename); 1034141cc406Sopenharmony_ci dev->sfd = sfd; 1035141cc406Sopenharmony_ci 1036141cc406Sopenharmony_ci if (sp15c_identify_scanner (dev) != 0) 1037141cc406Sopenharmony_ci { 1038141cc406Sopenharmony_ci DBG (5, "attach_scanner: scanner-identification failed\n"); 1039141cc406Sopenharmony_ci sanei_scsi_close (dev->sfd); 1040141cc406Sopenharmony_ci free (dev->buffer); 1041141cc406Sopenharmony_ci free (dev); 1042141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1043141cc406Sopenharmony_ci } 1044141cc406Sopenharmony_ci 1045141cc406Sopenharmony_ci#if 0 1046141cc406Sopenharmony_ci /* Get MUD (via mode_sense), internal info (via get_internal_info), and 1047141cc406Sopenharmony_ci * initialize values */ 1048141cc406Sopenharmony_ci coolscan_initialize_values (dev); 1049141cc406Sopenharmony_ci#endif 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci /* Why? */ 1052141cc406Sopenharmony_ci sanei_scsi_close (dev->sfd); 1053141cc406Sopenharmony_ci dev->sfd = -1; 1054141cc406Sopenharmony_ci 1055141cc406Sopenharmony_ci dev->sane.name = dev->devicename; 1056141cc406Sopenharmony_ci dev->sane.vendor = dev->vendor; 1057141cc406Sopenharmony_ci dev->sane.model = dev->product; 1058141cc406Sopenharmony_ci dev->sane.type = "flatbed/ADF scanner"; 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci ++num_devices; 1061141cc406Sopenharmony_ci dev->next = first_dev; 1062141cc406Sopenharmony_ci first_dev = dev; 1063141cc406Sopenharmony_ci 1064141cc406Sopenharmony_ci if (devp) 1065141cc406Sopenharmony_ci { 1066141cc406Sopenharmony_ci *devp = dev; 1067141cc406Sopenharmony_ci } 1068141cc406Sopenharmony_ci 1069141cc406Sopenharmony_ci DBG (15, "attach_scanner: done\n"); 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1072141cc406Sopenharmony_ci} /* attach_scanner */ 1073141cc406Sopenharmony_ci 1074141cc406Sopenharmony_cistatic SANE_Status 1075141cc406Sopenharmony_ciattach_one (const char *name) 1076141cc406Sopenharmony_ci{ 1077141cc406Sopenharmony_ci return attach_scanner (name, 0); 1078141cc406Sopenharmony_ci} /* attach_one */ 1079141cc406Sopenharmony_ci 1080141cc406Sopenharmony_cistatic SANE_Status 1081141cc406Sopenharmony_cisense_handler (int scsi_fd, u_char * result, void *arg) 1082141cc406Sopenharmony_ci{ 1083141cc406Sopenharmony_ci (void) scsi_fd; 1084141cc406Sopenharmony_ci (void) arg; /* silence compilation warnings */ 1085141cc406Sopenharmony_ci 1086141cc406Sopenharmony_ci return request_sense_parse (result); 1087141cc406Sopenharmony_ci} /* sense_handler */ 1088141cc406Sopenharmony_ci 1089141cc406Sopenharmony_cistatic int 1090141cc406Sopenharmony_cirequest_sense_parse (u_char * sensed_data) 1091141cc406Sopenharmony_ci{ 1092141cc406Sopenharmony_ci unsigned int ret, sense, asc, ascq; 1093141cc406Sopenharmony_ci sense = get_RS_sense_key (sensed_data); 1094141cc406Sopenharmony_ci asc = get_RS_ASC (sensed_data); 1095141cc406Sopenharmony_ci ascq = get_RS_ASCQ (sensed_data); 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci ret = SANE_STATUS_IO_ERROR; 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci switch (sense) 1100141cc406Sopenharmony_ci { 1101141cc406Sopenharmony_ci case 0x0: /* No Sense */ 1102141cc406Sopenharmony_ci DBG (5, "\t%d/%d/%d: Scanner ready\n", sense, asc, ascq); 1103141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1104141cc406Sopenharmony_ci 1105141cc406Sopenharmony_ci case 0x2: /* Not Ready */ 1106141cc406Sopenharmony_ci if ((0x00 == asc) && (0x00 == ascq)) 1107141cc406Sopenharmony_ci { 1108141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Not Ready \n", sense, asc, ascq); 1109141cc406Sopenharmony_ci } 1110141cc406Sopenharmony_ci else 1111141cc406Sopenharmony_ci { 1112141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 1113141cc406Sopenharmony_ci } 1114141cc406Sopenharmony_ci break; 1115141cc406Sopenharmony_ci 1116141cc406Sopenharmony_ci case 0x3: /* Medium Error */ 1117141cc406Sopenharmony_ci if ((0x80 == asc) && (0x01 == ascq)) 1118141cc406Sopenharmony_ci { 1119141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Jam \n", sense, asc, ascq); 1120141cc406Sopenharmony_ci ret = SANE_STATUS_JAMMED; 1121141cc406Sopenharmony_ci } 1122141cc406Sopenharmony_ci else if ((0x80 == asc) && (0x02 == ascq)) 1123141cc406Sopenharmony_ci { 1124141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: ADF cover open \n", sense, asc, ascq); 1125141cc406Sopenharmony_ci ret = SANE_STATUS_COVER_OPEN; 1126141cc406Sopenharmony_ci } 1127141cc406Sopenharmony_ci else if ((0x80 == asc) && (0x03 == ascq)) 1128141cc406Sopenharmony_ci { 1129141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: ADF empty \n", sense, asc, ascq); 1130141cc406Sopenharmony_ci ret = SANE_STATUS_NO_DOCS; 1131141cc406Sopenharmony_ci } 1132141cc406Sopenharmony_ci else 1133141cc406Sopenharmony_ci { 1134141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 1135141cc406Sopenharmony_ci } 1136141cc406Sopenharmony_ci break; 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci case 0x4: /* Hardware Error */ 1139141cc406Sopenharmony_ci if ((0x80 == asc) && (0x01 == ascq)) 1140141cc406Sopenharmony_ci { 1141141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: FB motor fuse \n", sense, asc, ascq); 1142141cc406Sopenharmony_ci } 1143141cc406Sopenharmony_ci else if ((0x80 == asc) && (0x02 == ascq)) 1144141cc406Sopenharmony_ci { 1145141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: heater fuse \n", sense, asc, ascq); 1146141cc406Sopenharmony_ci } 1147141cc406Sopenharmony_ci else if ((0x80 == asc) && (0x04 == ascq)) 1148141cc406Sopenharmony_ci { 1149141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: ADF motor fuse \n", sense, asc, ascq); 1150141cc406Sopenharmony_ci } 1151141cc406Sopenharmony_ci else if ((0x80 == asc) && (0x05 == ascq)) 1152141cc406Sopenharmony_ci { 1153141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: mechanical alarm \n", sense, asc, ascq); 1154141cc406Sopenharmony_ci } 1155141cc406Sopenharmony_ci else if ((0x80 == asc) && (0x06 == ascq)) 1156141cc406Sopenharmony_ci { 1157141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: optical alarm \n", sense, asc, ascq); 1158141cc406Sopenharmony_ci } 1159141cc406Sopenharmony_ci else if ((0x44 == asc) && (0x00 == ascq)) 1160141cc406Sopenharmony_ci { 1161141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: abnormal internal target \n", sense, asc, ascq); 1162141cc406Sopenharmony_ci } 1163141cc406Sopenharmony_ci else if ((0x47 == asc) && (0x00 == ascq)) 1164141cc406Sopenharmony_ci { 1165141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: SCSI parity error \n", sense, asc, ascq); 1166141cc406Sopenharmony_ci } 1167141cc406Sopenharmony_ci else 1168141cc406Sopenharmony_ci { 1169141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 1170141cc406Sopenharmony_ci } 1171141cc406Sopenharmony_ci break; 1172141cc406Sopenharmony_ci 1173141cc406Sopenharmony_ci case 0x5: /* Illegal Request */ 1174141cc406Sopenharmony_ci if ((0x20 == asc) && (0x00 == ascq)) 1175141cc406Sopenharmony_ci { 1176141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid command \n", sense, asc, ascq); 1177141cc406Sopenharmony_ci ret = SANE_STATUS_INVAL; 1178141cc406Sopenharmony_ci } 1179141cc406Sopenharmony_ci else if ((0x24 == asc) && (0x00 == ascq)) 1180141cc406Sopenharmony_ci { 1181141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid field in CDB \n", sense, asc, ascq); 1182141cc406Sopenharmony_ci ret = SANE_STATUS_INVAL; 1183141cc406Sopenharmony_ci } 1184141cc406Sopenharmony_ci else if ((0x25 == asc) && (0x00 == ascq)) 1185141cc406Sopenharmony_ci { 1186141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Unsupported logical unit \n", sense, asc, ascq); 1187141cc406Sopenharmony_ci ret = SANE_STATUS_UNSUPPORTED; 1188141cc406Sopenharmony_ci } 1189141cc406Sopenharmony_ci else if ((0x26 == asc) && (0x00 == ascq)) 1190141cc406Sopenharmony_ci { 1191141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid field in parm list \n", sense, asc, ascq); 1192141cc406Sopenharmony_ci ret = SANE_STATUS_INVAL; 1193141cc406Sopenharmony_ci } 1194141cc406Sopenharmony_ci else if ((0x2C == asc) && (0x02 == ascq)) 1195141cc406Sopenharmony_ci { 1196141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: wrong window combination \n", sense, asc, ascq); 1197141cc406Sopenharmony_ci ret = SANE_STATUS_INVAL; 1198141cc406Sopenharmony_ci } 1199141cc406Sopenharmony_ci else 1200141cc406Sopenharmony_ci { 1201141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 1202141cc406Sopenharmony_ci } 1203141cc406Sopenharmony_ci break; 1204141cc406Sopenharmony_ci 1205141cc406Sopenharmony_ci case 0x6: /* Unit Attention */ 1206141cc406Sopenharmony_ci if ((0x00 == asc) && (0x00 == ascq)) 1207141cc406Sopenharmony_ci { 1208141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: UNIT ATTENTION \n", sense, asc, ascq); 1209141cc406Sopenharmony_ci } 1210141cc406Sopenharmony_ci else 1211141cc406Sopenharmony_ci { 1212141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 1213141cc406Sopenharmony_ci } 1214141cc406Sopenharmony_ci break; 1215141cc406Sopenharmony_ci 1216141cc406Sopenharmony_ci case 0xb: /* Aborted Command */ 1217141cc406Sopenharmony_ci if ((0x43 == asc) && (0x00 == ascq)) 1218141cc406Sopenharmony_ci { 1219141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Message error \n", sense, asc, ascq); 1220141cc406Sopenharmony_ci } 1221141cc406Sopenharmony_ci else if ((0x80 == asc) && (0x01 == ascq)) 1222141cc406Sopenharmony_ci { 1223141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Image transfer error \n", sense, asc, ascq); 1224141cc406Sopenharmony_ci } 1225141cc406Sopenharmony_ci else 1226141cc406Sopenharmony_ci { 1227141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 1228141cc406Sopenharmony_ci } 1229141cc406Sopenharmony_ci break; 1230141cc406Sopenharmony_ci 1231141cc406Sopenharmony_ci default: 1232141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 1233141cc406Sopenharmony_ci } 1234141cc406Sopenharmony_ci return ret; 1235141cc406Sopenharmony_ci} /* request_sense_parse */ 1236141cc406Sopenharmony_ci 1237141cc406Sopenharmony_cistatic SANE_Status 1238141cc406Sopenharmony_cisp15c_identify_scanner (struct sp15c *s) 1239141cc406Sopenharmony_ci{ 1240141cc406Sopenharmony_ci char vendor[9]; 1241141cc406Sopenharmony_ci char product[0x11]; 1242141cc406Sopenharmony_ci char version[5]; 1243141cc406Sopenharmony_ci char *pp; 1244141cc406Sopenharmony_ci SANE_Status ret; 1245141cc406Sopenharmony_ci 1246141cc406Sopenharmony_ci DBG (10, "identify_scanner\n"); 1247141cc406Sopenharmony_ci 1248141cc406Sopenharmony_ci vendor[8] = product[0x10] = version[4] = 0; 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci if ((ret = sp15c_do_inquiry (s))) 1251141cc406Sopenharmony_ci { 1252141cc406Sopenharmony_ci DBG (5, "identify_scanner: inquiry failed\n"); 1253141cc406Sopenharmony_ci return ret; 1254141cc406Sopenharmony_ci } 1255141cc406Sopenharmony_ci if (get_IN_periph_devtype (s->buffer) != IN_periph_devtype_scanner) 1256141cc406Sopenharmony_ci { 1257141cc406Sopenharmony_ci DBG (5, "identify_scanner: not a scanner\n"); 1258141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1259141cc406Sopenharmony_ci } 1260141cc406Sopenharmony_ci 1261141cc406Sopenharmony_ci get_IN_vendor ((char *) s->buffer, vendor); 1262141cc406Sopenharmony_ci get_IN_product ((char *)s->buffer, product); 1263141cc406Sopenharmony_ci get_IN_version ((char *)s->buffer, version); 1264141cc406Sopenharmony_ci 1265141cc406Sopenharmony_ci if (strncmp ("FCPA ", vendor, 8)) 1266141cc406Sopenharmony_ci { 1267141cc406Sopenharmony_ci DBG (5, "identify_scanner: \"%s\" isn't a Fujitsu product\n", vendor); 1268141cc406Sopenharmony_ci return 1; 1269141cc406Sopenharmony_ci } 1270141cc406Sopenharmony_ci 1271141cc406Sopenharmony_ci pp = &vendor[8]; 1272141cc406Sopenharmony_ci vendor[8] = ' '; 1273141cc406Sopenharmony_ci while (*pp == ' ') 1274141cc406Sopenharmony_ci { 1275141cc406Sopenharmony_ci *pp-- = '\0'; 1276141cc406Sopenharmony_ci } 1277141cc406Sopenharmony_ci 1278141cc406Sopenharmony_ci pp = &product[0x10]; 1279141cc406Sopenharmony_ci product[0x10] = ' '; 1280141cc406Sopenharmony_ci while (*(pp - 1) == ' ') 1281141cc406Sopenharmony_ci { 1282141cc406Sopenharmony_ci *pp-- = '\0'; 1283141cc406Sopenharmony_ci } /* leave one blank at the end! */ 1284141cc406Sopenharmony_ci 1285141cc406Sopenharmony_ci pp = &version[4]; 1286141cc406Sopenharmony_ci version[4] = ' '; 1287141cc406Sopenharmony_ci while (*pp == ' ') 1288141cc406Sopenharmony_ci { 1289141cc406Sopenharmony_ci *pp-- = '\0'; 1290141cc406Sopenharmony_ci } 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci if (get_IN_adf (s->buffer)) 1293141cc406Sopenharmony_ci { 1294141cc406Sopenharmony_ci s->autofeeder = 1; 1295141cc406Sopenharmony_ci } 1296141cc406Sopenharmony_ci else 1297141cc406Sopenharmony_ci { 1298141cc406Sopenharmony_ci s->autofeeder = 0; 1299141cc406Sopenharmony_ci } 1300141cc406Sopenharmony_ci 1301141cc406Sopenharmony_ci DBG (10, "Found %s scanner %s version %s on device %s %x/%x/%x\n", 1302141cc406Sopenharmony_ci vendor, product, version, s->devicename, 1303141cc406Sopenharmony_ci s->autofeeder, get_IN_color_mode (s->buffer), 1304141cc406Sopenharmony_ci get_IN_color_seq (s->buffer)); 1305141cc406Sopenharmony_ci 1306141cc406Sopenharmony_ci vendor[8] = '\0'; 1307141cc406Sopenharmony_ci product[16] = '\0'; 1308141cc406Sopenharmony_ci version[4] = '\0'; 1309141cc406Sopenharmony_ci 1310141cc406Sopenharmony_ci strncpy (s->vendor, vendor, 9); 1311141cc406Sopenharmony_ci strncpy (s->product, product, 17); 1312141cc406Sopenharmony_ci strncpy (s->version, version, 5); 1313141cc406Sopenharmony_ci 1314141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1315141cc406Sopenharmony_ci} /* sp15c_identify_scanner */ 1316141cc406Sopenharmony_ci 1317141cc406Sopenharmony_cistatic SANE_Status 1318141cc406Sopenharmony_cisp15c_do_inquiry (struct sp15c *s) 1319141cc406Sopenharmony_ci{ 1320141cc406Sopenharmony_ci static SANE_Status ret; 1321141cc406Sopenharmony_ci 1322141cc406Sopenharmony_ci DBG (10, "do_inquiry\n"); 1323141cc406Sopenharmony_ci 1324141cc406Sopenharmony_ci memset (s->buffer, '\0', 256); /* clear buffer */ 1325141cc406Sopenharmony_ci set_IN_return_size (inquiryB.cmd, 96); 1326141cc406Sopenharmony_ci 1327141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, inquiryB.cmd, inquiryB.size, s->buffer, 96); 1328141cc406Sopenharmony_ci return ret; 1329141cc406Sopenharmony_ci} /* sp15c_do_inquiry */ 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_cistatic SANE_Status 1332141cc406Sopenharmony_cido_scsi_cmd (int fd, unsigned char *cmd, int cmd_len, unsigned char *out, size_t out_len) 1333141cc406Sopenharmony_ci{ 1334141cc406Sopenharmony_ci SANE_Status ret; 1335141cc406Sopenharmony_ci size_t ol = out_len; 1336141cc406Sopenharmony_ci 1337141cc406Sopenharmony_ci hexdump (20, "<cmd<", cmd, cmd_len); 1338141cc406Sopenharmony_ci 1339141cc406Sopenharmony_ci ret = sanei_scsi_cmd (fd, cmd, cmd_len, out, &ol); 1340141cc406Sopenharmony_ci if ((out_len != 0) && (out_len != ol)) 1341141cc406Sopenharmony_ci { 1342141cc406Sopenharmony_ci DBG (1, "sanei_scsi_cmd: asked %lu bytes, got %lu\n", 1343141cc406Sopenharmony_ci (u_long) out_len, (u_long) ol); 1344141cc406Sopenharmony_ci } 1345141cc406Sopenharmony_ci if (ret) 1346141cc406Sopenharmony_ci { 1347141cc406Sopenharmony_ci DBG (1, "sanei_scsi_cmd: returning 0x%08x\n", ret); 1348141cc406Sopenharmony_ci } 1349141cc406Sopenharmony_ci DBG (10, "sanei_scsi_cmd: returning %lu bytes:\n", (u_long) ol); 1350141cc406Sopenharmony_ci if (out != NULL && out_len != 0) 1351141cc406Sopenharmony_ci hexdump (15, ">rslt>", out, (out_len > 0x60) ? 0x60 : out_len); 1352141cc406Sopenharmony_ci 1353141cc406Sopenharmony_ci return ret; 1354141cc406Sopenharmony_ci} /* do_scsi_cmd */ 1355141cc406Sopenharmony_ci 1356141cc406Sopenharmony_cistatic void 1357141cc406Sopenharmony_cihexdump (int level, char *comment, unsigned char *p, int l) 1358141cc406Sopenharmony_ci{ 1359141cc406Sopenharmony_ci int i; 1360141cc406Sopenharmony_ci char line[128]; 1361141cc406Sopenharmony_ci char *ptr; 1362141cc406Sopenharmony_ci 1363141cc406Sopenharmony_ci DBG (level, "%s\n", comment); 1364141cc406Sopenharmony_ci ptr = line; 1365141cc406Sopenharmony_ci for (i = 0; i < l; i++, p++) 1366141cc406Sopenharmony_ci { 1367141cc406Sopenharmony_ci if ((i % 16) == 0) 1368141cc406Sopenharmony_ci { 1369141cc406Sopenharmony_ci if (ptr != line) 1370141cc406Sopenharmony_ci { 1371141cc406Sopenharmony_ci *ptr = '\0'; 1372141cc406Sopenharmony_ci DBG (level, "%s\n", line); 1373141cc406Sopenharmony_ci ptr = line; 1374141cc406Sopenharmony_ci } 1375141cc406Sopenharmony_ci sprintf (ptr, "%3.3d:", i); 1376141cc406Sopenharmony_ci ptr += 4; 1377141cc406Sopenharmony_ci } 1378141cc406Sopenharmony_ci sprintf (ptr, " %2.2x", *p); 1379141cc406Sopenharmony_ci ptr += 3; 1380141cc406Sopenharmony_ci } 1381141cc406Sopenharmony_ci *ptr = '\0'; 1382141cc406Sopenharmony_ci DBG (level, "%s\n", line); 1383141cc406Sopenharmony_ci} /* hexdump */ 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_cistatic SANE_Status 1386141cc406Sopenharmony_ciinit_options (struct sp15c *scanner) 1387141cc406Sopenharmony_ci{ 1388141cc406Sopenharmony_ci int i; 1389141cc406Sopenharmony_ci 1390141cc406Sopenharmony_ci DBG (10, "init_options\n"); 1391141cc406Sopenharmony_ci 1392141cc406Sopenharmony_ci memset (scanner->opt, 0, sizeof (scanner->opt)); 1393141cc406Sopenharmony_ci 1394141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 1395141cc406Sopenharmony_ci { 1396141cc406Sopenharmony_ci scanner->opt[i].size = sizeof (SANE_Word); 1397141cc406Sopenharmony_ci scanner->opt[i].cap = SANE_CAP_INACTIVE; 1398141cc406Sopenharmony_ci } 1399141cc406Sopenharmony_ci 1400141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 1401141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 1402141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 1403141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 1404141cc406Sopenharmony_ci 1405141cc406Sopenharmony_ci/************** "Mode" group: **************/ 1406141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].title = "Scan Mode"; 1407141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].desc = ""; 1408141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 1409141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1410141cc406Sopenharmony_ci 1411141cc406Sopenharmony_ci /* source */ 1412141cc406Sopenharmony_ci 1413141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 1414141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 1415141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 1416141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].type = SANE_TYPE_STRING; 1417141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].size = max_string_size (source_list); 1418141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1419141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].constraint.string_list = source_list; 1420141cc406Sopenharmony_ci if (scanner->autofeeder) 1421141cc406Sopenharmony_ci { 1422141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT 1423141cc406Sopenharmony_ci | SANE_CAP_SOFT_DETECT; 1424141cc406Sopenharmony_ci } 1425141cc406Sopenharmony_ci 1426141cc406Sopenharmony_ci /* scan mode */ 1427141cc406Sopenharmony_ci scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 1428141cc406Sopenharmony_ci scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 1429141cc406Sopenharmony_ci scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 1430141cc406Sopenharmony_ci scanner->opt[OPT_MODE].type = SANE_TYPE_STRING; 1431141cc406Sopenharmony_ci scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list); 1432141cc406Sopenharmony_ci scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1433141cc406Sopenharmony_ci scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list; 1434141cc406Sopenharmony_ci scanner->opt[OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci /* negative */ 1437141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].name = "type"; 1438141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].title = "Film type"; 1439141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].desc = "positive or negative image"; 1440141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].type = SANE_TYPE_STRING; 1441141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].size = max_string_size (type_list); 1442141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1443141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].constraint.string_list = type_list; 1444141cc406Sopenharmony_ci 1445141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].name = "prescan"; 1446141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].title = "Prescan"; 1447141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].desc = "Perform a prescan during preview"; 1448141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].type = SANE_TYPE_BOOL; 1449141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].unit = SANE_UNIT_NONE; 1450141cc406Sopenharmony_ci 1451141cc406Sopenharmony_ci /* resolution */ 1452141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].name = SANE_NAME_SCAN_RESOLUTION; 1453141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].title = SANE_TITLE_SCAN_X_RESOLUTION; 1454141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].desc = SANE_DESC_SCAN_X_RESOLUTION; 1455141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].type = SANE_TYPE_INT; 1456141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].unit = SANE_UNIT_DPI; 1457141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].constraint_type = SANE_CONSTRAINT_WORD_LIST; 1458141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].constraint.word_list = x_res_list; 1459141cc406Sopenharmony_ci scanner->opt[OPT_X_RES].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].name = SANE_NAME_SCAN_Y_RESOLUTION; 1462141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].title = SANE_TITLE_SCAN_Y_RESOLUTION; 1463141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].desc = SANE_DESC_SCAN_Y_RESOLUTION; 1464141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].type = SANE_TYPE_INT; 1465141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].unit = SANE_UNIT_DPI; 1466141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].constraint_type = SANE_CONSTRAINT_WORD_LIST; 1467141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].constraint.word_list = y_res_list; 1468141cc406Sopenharmony_ci scanner->opt[OPT_Y_RES].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RES].name = "preview-resolution"; 1471141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RES].title = "Preview resolution"; 1472141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RES].desc = SANE_DESC_SCAN_RESOLUTION; 1473141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RES].type = SANE_TYPE_INT; 1474141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RES].unit = SANE_UNIT_DPI; 1475141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RES].constraint_type = SANE_CONSTRAINT_WORD_LIST; 1476141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RES].constraint.word_list = resolution_list; 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_ci/************** "Geometry" group: **************/ 1479141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; 1480141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].desc = ""; 1481141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 1482141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci /* top-left x */ 1485141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 1486141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 1487141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 1488141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 1489141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM; 1490141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 1491141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].constraint.range = &x_range; 1492141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1493141cc406Sopenharmony_ci 1494141cc406Sopenharmony_ci /* top-left y */ 1495141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 1496141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 1497141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 1498141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 1499141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 1500141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1501141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].constraint.range = &y_range_fb; 1502141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci /* bottom-right x */ 1505141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 1506141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 1507141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 1508141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 1509141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM; 1510141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 1511141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].constraint.range = &x_range; 1512141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1513141cc406Sopenharmony_ci 1514141cc406Sopenharmony_ci /* bottom-right y */ 1515141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 1516141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 1517141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 1518141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 1519141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 1520141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1521141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].constraint.range = &y_range_fb; 1522141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci 1525141cc406Sopenharmony_ci /* ------------------------------ */ 1526141cc406Sopenharmony_ci 1527141cc406Sopenharmony_ci/************** "Enhancement" group: **************/ 1528141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; 1529141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 1530141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 1531141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1532141cc406Sopenharmony_ci 1533141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].name = "averaging"; 1534141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].title = "Averaging"; 1535141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].desc = "Averaging"; 1536141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].type = SANE_TYPE_BOOL; 1537141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].unit = SANE_UNIT_NONE; 1538141cc406Sopenharmony_ci 1539141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 1540141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 1541141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 1542141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 1543141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 1544141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 1545141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range; 1546141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_DETECT; 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 1549141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 1550141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 1551141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 1552141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 1553141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 1554141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].constraint.range = &threshold_range; 1555141cc406Sopenharmony_ci scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_DETECT; 1556141cc406Sopenharmony_ci 1557141cc406Sopenharmony_ci /* ------------------------------ */ 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci/************** "Advanced" group: **************/ 1560141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced"; 1561141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].desc = ""; 1562141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; 1563141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1564141cc406Sopenharmony_ci 1565141cc406Sopenharmony_ci /* preview */ 1566141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 1567141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 1568141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 1569141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 1570141cc406Sopenharmony_ci 1571141cc406Sopenharmony_ci DBG (10, "init_options:ok\n"); 1572141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1573141cc406Sopenharmony_ci} /* init_options */ 1574141cc406Sopenharmony_ci 1575141cc406Sopenharmony_cistatic int 1576141cc406Sopenharmony_cisp15c_check_values (struct sp15c *s) 1577141cc406Sopenharmony_ci{ 1578141cc406Sopenharmony_ci if (s->use_adf == SANE_TRUE && s->autofeeder == 0) 1579141cc406Sopenharmony_ci { 1580141cc406Sopenharmony_ci DBG (1, "sp15c_check_values: %s\n", 1581141cc406Sopenharmony_ci "ERROR: ADF-MODE NOT SUPPORTED BY SCANNER, ABORTING"); 1582141cc406Sopenharmony_ci return (1); 1583141cc406Sopenharmony_ci } 1584141cc406Sopenharmony_ci return (0); 1585141cc406Sopenharmony_ci} /* sp15c_check_values */ 1586141cc406Sopenharmony_ci 1587141cc406Sopenharmony_ci/* sp15c_free_scanner should go through the following sequence: 1588141cc406Sopenharmony_ci * OBJECT POSITION DISCHARGE 1589141cc406Sopenharmony_ci * GOOD 1590141cc406Sopenharmony_ci * RELEASE UNIT 1591141cc406Sopenharmony_ci * GOOD 1592141cc406Sopenharmony_ci */ 1593141cc406Sopenharmony_cistatic int 1594141cc406Sopenharmony_cisp15c_free_scanner (struct sp15c *s) 1595141cc406Sopenharmony_ci{ 1596141cc406Sopenharmony_ci int ret; 1597141cc406Sopenharmony_ci DBG (10, "sp15c_free_scanner\n"); 1598141cc406Sopenharmony_ci#if 0 1599141cc406Sopenharmony_ci /* hmg: reports from several people show that this code ejects two pages 1600141cc406Sopenharmony_ci instead of one. So I've commented it out for now. */ 1601141cc406Sopenharmony_ci ret = sp15c_object_discharge (s); 1602141cc406Sopenharmony_ci if (ret) 1603141cc406Sopenharmony_ci return ret; 1604141cc406Sopenharmony_ci#endif 1605141cc406Sopenharmony_ci 1606141cc406Sopenharmony_ci wait_scanner (s); 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, release_unitB.cmd, release_unitB.size, NULL, 0); 1609141cc406Sopenharmony_ci if (ret) 1610141cc406Sopenharmony_ci return ret; 1611141cc406Sopenharmony_ci 1612141cc406Sopenharmony_ci DBG (10, "sp15c_free_scanner: ok\n"); 1613141cc406Sopenharmony_ci return ret; 1614141cc406Sopenharmony_ci} /* sp15c_free_scanner */ 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci/* sp15c_grab_scanner should go through the following command sequence: 1617141cc406Sopenharmony_ci * TEST UNIT READY 1618141cc406Sopenharmony_ci * CHECK CONDITION \ 1619141cc406Sopenharmony_ci * REQUEST SENSE > These should be handled automagically by 1620141cc406Sopenharmony_ci * UNIT ATTENTION / the kernel if they happen (powerup/reset) 1621141cc406Sopenharmony_ci * TEST UNIT READY 1622141cc406Sopenharmony_ci * GOOD 1623141cc406Sopenharmony_ci * RESERVE UNIT 1624141cc406Sopenharmony_ci * GOOD 1625141cc406Sopenharmony_ci * 1626141cc406Sopenharmony_ci * It is then responsible for installing appropriate signal handlers 1627141cc406Sopenharmony_ci * to call emergency_give_scanner() if user aborts. 1628141cc406Sopenharmony_ci */ 1629141cc406Sopenharmony_ci 1630141cc406Sopenharmony_cistatic int 1631141cc406Sopenharmony_cisp15c_grab_scanner (struct sp15c *s) 1632141cc406Sopenharmony_ci{ 1633141cc406Sopenharmony_ci int ret; 1634141cc406Sopenharmony_ci 1635141cc406Sopenharmony_ci DBG (10, "sp15c_grab_scanner\n"); 1636141cc406Sopenharmony_ci wait_scanner (s); 1637141cc406Sopenharmony_ci 1638141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, reserve_unitB.cmd, reserve_unitB.size, NULL, 0); 1639141cc406Sopenharmony_ci if (ret) 1640141cc406Sopenharmony_ci return ret; 1641141cc406Sopenharmony_ci 1642141cc406Sopenharmony_ci DBG (10, "sp15c_grab_scanner: ok\n"); 1643141cc406Sopenharmony_ci return 0; 1644141cc406Sopenharmony_ci} /* sp15c_grab_scanner */ 1645141cc406Sopenharmony_ci 1646141cc406Sopenharmony_ci/* 1647141cc406Sopenharmony_ci * wait_scanner spins until TEST_UNIT_READY returns 0 (GOOD) 1648141cc406Sopenharmony_ci * returns 0 on success, 1649141cc406Sopenharmony_ci * returns -1 on error or timeout 1650141cc406Sopenharmony_ci */ 1651141cc406Sopenharmony_cistatic int 1652141cc406Sopenharmony_ciwait_scanner (struct sp15c *s) 1653141cc406Sopenharmony_ci{ 1654141cc406Sopenharmony_ci int ret = -1; 1655141cc406Sopenharmony_ci int cnt = 0; 1656141cc406Sopenharmony_ci 1657141cc406Sopenharmony_ci DBG (10, "wait_scanner\n"); 1658141cc406Sopenharmony_ci 1659141cc406Sopenharmony_ci while (ret != 0) 1660141cc406Sopenharmony_ci { 1661141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, test_unit_readyB.cmd, 1662141cc406Sopenharmony_ci test_unit_readyB.size, 0, 0); 1663141cc406Sopenharmony_ci if (ret == SANE_STATUS_DEVICE_BUSY) 1664141cc406Sopenharmony_ci { 1665141cc406Sopenharmony_ci usleep (50000); /* wait 0.05 seconds */ 1666141cc406Sopenharmony_ci /* 20 sec. max (prescan takes up to 15 sec.) */ 1667141cc406Sopenharmony_ci if (cnt++ > 400) 1668141cc406Sopenharmony_ci { 1669141cc406Sopenharmony_ci DBG (1, "wait_scanner: scanner does NOT get ready\n"); 1670141cc406Sopenharmony_ci return -1; 1671141cc406Sopenharmony_ci } 1672141cc406Sopenharmony_ci } 1673141cc406Sopenharmony_ci else if (ret == SANE_STATUS_GOOD) 1674141cc406Sopenharmony_ci { 1675141cc406Sopenharmony_ci DBG (10, "wait_scanner: ok\n"); 1676141cc406Sopenharmony_ci return ret; 1677141cc406Sopenharmony_ci } 1678141cc406Sopenharmony_ci else 1679141cc406Sopenharmony_ci { 1680141cc406Sopenharmony_ci DBG (1, "wait_scanner: unit ready failed (%s)\n", 1681141cc406Sopenharmony_ci sane_strstatus (ret)); 1682141cc406Sopenharmony_ci } 1683141cc406Sopenharmony_ci } 1684141cc406Sopenharmony_ci DBG (10, "wait_scanner: ok\n"); 1685141cc406Sopenharmony_ci return 0; 1686141cc406Sopenharmony_ci} /* wait_scanner */ 1687141cc406Sopenharmony_ci 1688141cc406Sopenharmony_ci/* As noted above, this command has been supplanted by the 1689141cc406Sopenharmony_ci MEDIA CHECK command. Nevertheless, it's still available 1690141cc406Sopenharmony_ci here in case some future need is discovered. */ 1691141cc406Sopenharmony_cistatic int 1692141cc406Sopenharmony_cisp15c_object_position (struct sp15c *s) 1693141cc406Sopenharmony_ci{ 1694141cc406Sopenharmony_ci int ret; 1695141cc406Sopenharmony_ci DBG (10, "sp15c_object_position\n"); 1696141cc406Sopenharmony_ci if (s->use_adf != SANE_TRUE) 1697141cc406Sopenharmony_ci { 1698141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1699141cc406Sopenharmony_ci } 1700141cc406Sopenharmony_ci if (s->autofeeder == 0) 1701141cc406Sopenharmony_ci { 1702141cc406Sopenharmony_ci DBG (10, "sp15c_object_position: Autofeeder not present.\n"); 1703141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1704141cc406Sopenharmony_ci } 1705141cc406Sopenharmony_ci memcpy (s->buffer, object_positionB.cmd, object_positionB.size); 1706141cc406Sopenharmony_ci set_OP_autofeed (s->buffer, OP_Feed); 1707141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, s->buffer, 1708141cc406Sopenharmony_ci object_positionB.size, NULL, 0); 1709141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1710141cc406Sopenharmony_ci { 1711141cc406Sopenharmony_ci return ret; 1712141cc406Sopenharmony_ci } 1713141cc406Sopenharmony_ci wait_scanner (s); 1714141cc406Sopenharmony_ci DBG (10, "sp15c_object_position: ok\n"); 1715141cc406Sopenharmony_ci return ret; 1716141cc406Sopenharmony_ci} /* sp15c_object_position */ 1717141cc406Sopenharmony_ci 1718141cc406Sopenharmony_cistatic int 1719141cc406Sopenharmony_cisp15c_media_check (struct sp15c *s) 1720141cc406Sopenharmony_ci{ 1721141cc406Sopenharmony_ci static SANE_Status ret; 1722141cc406Sopenharmony_ci DBG (10, "sp15c_media_check\n"); 1723141cc406Sopenharmony_ci if (s->use_adf != SANE_TRUE) 1724141cc406Sopenharmony_ci { 1725141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1726141cc406Sopenharmony_ci } 1727141cc406Sopenharmony_ci if (s->autofeeder == 0) 1728141cc406Sopenharmony_ci { 1729141cc406Sopenharmony_ci DBG (10, "sp15c_media_check: Autofeeder not present.\n"); 1730141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1731141cc406Sopenharmony_ci } 1732141cc406Sopenharmony_ci 1733141cc406Sopenharmony_ci memset (s->buffer, '\0', 256); /* clear buffer */ 1734141cc406Sopenharmony_ci set_MC_return_size (media_checkB.cmd, 1); 1735141cc406Sopenharmony_ci 1736141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, media_checkB.cmd, media_checkB.size, s->buffer, 1); 1737141cc406Sopenharmony_ci 1738141cc406Sopenharmony_ci if (ret != SANE_STATUS_GOOD) 1739141cc406Sopenharmony_ci { 1740141cc406Sopenharmony_ci return ret; 1741141cc406Sopenharmony_ci } 1742141cc406Sopenharmony_ci wait_scanner (s); 1743141cc406Sopenharmony_ci 1744141cc406Sopenharmony_ci if (get_MC_adf_status (s->buffer) == MC_ADF_OK) 1745141cc406Sopenharmony_ci { 1746141cc406Sopenharmony_ci DBG (10, "sp15c_media_check: ok\n"); 1747141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1748141cc406Sopenharmony_ci } 1749141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 1750141cc406Sopenharmony_ci 1751141cc406Sopenharmony_ci} /* sp15c_media_check */ 1752141cc406Sopenharmony_ci 1753141cc406Sopenharmony_cistatic SANE_Status 1754141cc406Sopenharmony_cido_cancel (struct sp15c *scanner) 1755141cc406Sopenharmony_ci{ 1756141cc406Sopenharmony_ci DBG (10, "do_cancel\n"); 1757141cc406Sopenharmony_ci swap_res (scanner); 1758141cc406Sopenharmony_ci 1759141cc406Sopenharmony_ci do_eof (scanner); /* close pipe and reposition scanner */ 1760141cc406Sopenharmony_ci 1761141cc406Sopenharmony_ci if (sanei_thread_is_valid (scanner->reader_pid)) 1762141cc406Sopenharmony_ci { 1763141cc406Sopenharmony_ci int exit_status; 1764141cc406Sopenharmony_ci DBG (10, "do_cancel: kill reader_process\n"); 1765141cc406Sopenharmony_ci /* ensure child knows it's time to stop: */ 1766141cc406Sopenharmony_ci sanei_thread_kill (scanner->reader_pid); 1767141cc406Sopenharmony_ci DBG (50, "wait for scanner to stop\n"); 1768141cc406Sopenharmony_ci sanei_thread_waitpid (scanner->reader_pid, &exit_status); 1769141cc406Sopenharmony_ci sanei_thread_invalidate (scanner->reader_pid); 1770141cc406Sopenharmony_ci } 1771141cc406Sopenharmony_ci 1772141cc406Sopenharmony_ci if (scanner->sfd >= 0) 1773141cc406Sopenharmony_ci { 1774141cc406Sopenharmony_ci sp15c_free_scanner (scanner); 1775141cc406Sopenharmony_ci DBG (10, "do_cancel: close filedescriptor\n"); 1776141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 1777141cc406Sopenharmony_ci scanner->sfd = -1; 1778141cc406Sopenharmony_ci } 1779141cc406Sopenharmony_ci 1780141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1781141cc406Sopenharmony_ci} /* do_cancel */ 1782141cc406Sopenharmony_ci 1783141cc406Sopenharmony_cistatic void 1784141cc406Sopenharmony_ciswap_res (struct sp15c *s) 1785141cc406Sopenharmony_ci{ 1786141cc406Sopenharmony_ci (void) s; /* silence compilation warnings */ 1787141cc406Sopenharmony_ci 1788141cc406Sopenharmony_ci /* for the time being, do nothing */ 1789141cc406Sopenharmony_ci} /* swap_res */ 1790141cc406Sopenharmony_ci 1791141cc406Sopenharmony_cistatic int 1792141cc406Sopenharmony_cisp15c_object_discharge (struct sp15c *s) 1793141cc406Sopenharmony_ci{ 1794141cc406Sopenharmony_ci int ret; 1795141cc406Sopenharmony_ci 1796141cc406Sopenharmony_ci DBG (10, "sp15c_object_discharge\n"); 1797141cc406Sopenharmony_ci if (s->use_adf != SANE_TRUE) 1798141cc406Sopenharmony_ci { 1799141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1800141cc406Sopenharmony_ci } 1801141cc406Sopenharmony_ci 1802141cc406Sopenharmony_ci memcpy (s->buffer, object_positionB.cmd, object_positionB.size); 1803141cc406Sopenharmony_ci set_OP_autofeed (s->buffer, OP_Discharge); 1804141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, s->buffer, 1805141cc406Sopenharmony_ci object_positionB.size, NULL, 0); 1806141cc406Sopenharmony_ci wait_scanner (s); 1807141cc406Sopenharmony_ci DBG (10, "sp15c_object_discharge: ok\n"); 1808141cc406Sopenharmony_ci return ret; 1809141cc406Sopenharmony_ci} /* sp15c_object_discharge */ 1810141cc406Sopenharmony_ci 1811141cc406Sopenharmony_cistatic int 1812141cc406Sopenharmony_cisp15c_set_window_param (struct sp15c *s, int prescan) 1813141cc406Sopenharmony_ci{ 1814141cc406Sopenharmony_ci unsigned char buffer_r[WDB_size_max]; 1815141cc406Sopenharmony_ci int ret; 1816141cc406Sopenharmony_ci int active_buffer_size; 1817141cc406Sopenharmony_ci 1818141cc406Sopenharmony_ci (void) prescan; /* silence compilation warnings */ 1819141cc406Sopenharmony_ci 1820141cc406Sopenharmony_ci wait_scanner (s); 1821141cc406Sopenharmony_ci DBG (10, "set_window_param\n"); 1822141cc406Sopenharmony_ci memset (buffer_r, '\0', WDB_size_max); /* clear buffer */ 1823141cc406Sopenharmony_ci memcpy (buffer_r, window_descriptor_blockB.cmd, 1824141cc406Sopenharmony_ci window_descriptor_blockB.size); /* copy preset data */ 1825141cc406Sopenharmony_ci 1826141cc406Sopenharmony_ci set_WD_wid (buffer_r, WD_wid_all); /* window identifier */ 1827141cc406Sopenharmony_ci 1828141cc406Sopenharmony_ci set_WD_Xres (buffer_r, s->x_res); /* x resolution in dpi */ 1829141cc406Sopenharmony_ci set_WD_Yres (buffer_r, s->y_res); /* y resolution in dpi */ 1830141cc406Sopenharmony_ci 1831141cc406Sopenharmony_ci set_WD_ULX (buffer_r, s->tl_x); /* top left x */ 1832141cc406Sopenharmony_ci set_WD_ULY (buffer_r, s->tl_y); /* top left y */ 1833141cc406Sopenharmony_ci 1834141cc406Sopenharmony_ci set_WD_width (buffer_r, s->br_x - s->tl_x); 1835141cc406Sopenharmony_ci set_WD_length (buffer_r, s->br_y - s->tl_y); 1836141cc406Sopenharmony_ci 1837141cc406Sopenharmony_ci set_WD_brightness (buffer_r, s->brightness); 1838141cc406Sopenharmony_ci set_WD_threshold (buffer_r, s->threshold); 1839141cc406Sopenharmony_ci set_WD_contrast (buffer_r, s->contrast); 1840141cc406Sopenharmony_ci set_WD_bitsperpixel (buffer_r, s->bitsperpixel); 1841141cc406Sopenharmony_ci set_WD_rif (buffer_r, s->rif); 1842141cc406Sopenharmony_ci set_WD_pad (buffer_r, 0x3); 1843141cc406Sopenharmony_ci set_WD_halftone (buffer_r, s->halftone); 1844141cc406Sopenharmony_ci set_WD_bitorder (buffer_r, s->bitorder); 1845141cc406Sopenharmony_ci set_WD_compress_type (buffer_r, s->compress_type); 1846141cc406Sopenharmony_ci set_WD_compress_arg (buffer_r, s->compress_arg); 1847141cc406Sopenharmony_ci set_WD_composition (buffer_r, s->composition); /* may be overridden below */ 1848141cc406Sopenharmony_ci set_WD_vendor_id_code (buffer_r, 0xff); 1849141cc406Sopenharmony_ci set_WD_adf (buffer_r, s->use_adf == SANE_TRUE ? 1 : 0); 1850141cc406Sopenharmony_ci set_WD_source (buffer_r, 1); 1851141cc406Sopenharmony_ci set_WD_highlight_color (buffer_r, 0xff); 1852141cc406Sopenharmony_ci set_WD_shadow_value (buffer_r, 0x00); 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci switch (s->composition) 1855141cc406Sopenharmony_ci { 1856141cc406Sopenharmony_ci case WD_comp_LA: 1857141cc406Sopenharmony_ci case WD_comp_HT: 1858141cc406Sopenharmony_ci set_WD_line_width (buffer_r, ((s->br_x - s->tl_x) * s->x_res / 1200) / 8); 1859141cc406Sopenharmony_ci set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); 1860141cc406Sopenharmony_ci goto b_and_w; 1861141cc406Sopenharmony_ci case WD_comp_G4: 1862141cc406Sopenharmony_ci set_WD_line_width (buffer_r, ((s->br_x - s->tl_x) * s->x_res / 1200) / 2); 1863141cc406Sopenharmony_ci set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); 1864141cc406Sopenharmony_ci goto grayscale; 1865141cc406Sopenharmony_ci case WD_comp_G8: 1866141cc406Sopenharmony_ci set_WD_line_width (buffer_r, (s->br_x - s->tl_x) * s->x_res / 1200); 1867141cc406Sopenharmony_ci set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); 1868141cc406Sopenharmony_ci grayscale: 1869141cc406Sopenharmony_ci set_WD_composition (buffer_r, WD_comp_GS); 1870141cc406Sopenharmony_ci b_and_w: 1871141cc406Sopenharmony_ci set_WD_color (buffer_r, WD_color_greenx); 1872141cc406Sopenharmony_ci break; 1873141cc406Sopenharmony_ci case WD_comp_MC: 1874141cc406Sopenharmony_ci set_WD_color (buffer_r, WD_color_rgb); 1875141cc406Sopenharmony_ci set_WD_line_width (buffer_r, 3 * (s->br_x - s->tl_x) * s->x_res / 1200); 1876141cc406Sopenharmony_ci set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); 1877141cc406Sopenharmony_ci break; 1878141cc406Sopenharmony_ci case WD_comp_BC: 1879141cc406Sopenharmony_ci case WD_comp_DC: 1880141cc406Sopenharmony_ci default: 1881141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1882141cc406Sopenharmony_ci } 1883141cc406Sopenharmony_ci 1884141cc406Sopenharmony_ci /* prepare SCSI-BUFFER */ 1885141cc406Sopenharmony_ci memcpy (s->buffer, set_windowB.cmd, set_windowB.size); 1886141cc406Sopenharmony_ci memcpy ((s->buffer + set_windowB.size), 1887141cc406Sopenharmony_ci window_parameter_data_blockB.cmd, 1888141cc406Sopenharmony_ci window_parameter_data_blockB.size); 1889141cc406Sopenharmony_ci memcpy ((s->buffer + set_windowB.size + window_parameter_data_blockB.size), 1890141cc406Sopenharmony_ci buffer_r, window_descriptor_blockB.size); 1891141cc406Sopenharmony_ci 1892141cc406Sopenharmony_ci set_SW_xferlen (s->buffer, 1893141cc406Sopenharmony_ci (window_parameter_data_blockB.size 1894141cc406Sopenharmony_ci + WDB_size_Color)); 1895141cc406Sopenharmony_ci set_WDPB_wdblen ((s->buffer 1896141cc406Sopenharmony_ci + set_windowB.size), 1897141cc406Sopenharmony_ci WDB_size_Color); 1898141cc406Sopenharmony_ci set_WD_parm_length ((s->buffer 1899141cc406Sopenharmony_ci + set_windowB.size 1900141cc406Sopenharmony_ci + window_parameter_data_blockB.size), 1901141cc406Sopenharmony_ci 9); 1902141cc406Sopenharmony_ci 1903141cc406Sopenharmony_ci DBG (10, "\tx_res=%d, y_res=%d\n", 1904141cc406Sopenharmony_ci s->x_res, s->y_res); 1905141cc406Sopenharmony_ci DBG (10, "\tupper left-x=%d, upper left-y=%d\n", 1906141cc406Sopenharmony_ci s->tl_x, s->tl_y); 1907141cc406Sopenharmony_ci DBG (10, "\twindow width=%d, length=%d\n", 1908141cc406Sopenharmony_ci s->br_x - s->tl_x, 1909141cc406Sopenharmony_ci s->br_y - s->tl_y); 1910141cc406Sopenharmony_ci 1911141cc406Sopenharmony_ci active_buffer_size = set_windowB.size + get_SW_xferlen (s->buffer); 1912141cc406Sopenharmony_ci 1913141cc406Sopenharmony_ci hexdump (15, "Window set", s->buffer, active_buffer_size); 1914141cc406Sopenharmony_ci 1915141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, s->buffer, active_buffer_size, NULL, 0); 1916141cc406Sopenharmony_ci if (ret) 1917141cc406Sopenharmony_ci return ret; 1918141cc406Sopenharmony_ci 1919141cc406Sopenharmony_ci DBG (10, "set_window_param: ok\n"); 1920141cc406Sopenharmony_ci return ret; 1921141cc406Sopenharmony_ci} /* sp15c_set_window_param */ 1922141cc406Sopenharmony_ci 1923141cc406Sopenharmony_cistatic size_t 1924141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 1925141cc406Sopenharmony_ci{ 1926141cc406Sopenharmony_ci size_t size, max_size = 0; 1927141cc406Sopenharmony_ci int i; 1928141cc406Sopenharmony_ci 1929141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 1930141cc406Sopenharmony_ci { 1931141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 1932141cc406Sopenharmony_ci if (size > max_size) 1933141cc406Sopenharmony_ci max_size = size; 1934141cc406Sopenharmony_ci } 1935141cc406Sopenharmony_ci return max_size; 1936141cc406Sopenharmony_ci} /* max_string_size */ 1937141cc406Sopenharmony_ci 1938141cc406Sopenharmony_cistatic int 1939141cc406Sopenharmony_cisp15c_start_scan (struct sp15c *s) 1940141cc406Sopenharmony_ci{ 1941141cc406Sopenharmony_ci int ret; 1942141cc406Sopenharmony_ci DBG (10, "sp15c_start_scan\n"); 1943141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, scanB.cmd, scanB.size, NULL, 0); 1944141cc406Sopenharmony_ci if (ret) 1945141cc406Sopenharmony_ci return ret; 1946141cc406Sopenharmony_ci DBG (10, "sp15c_start_scan:ok\n"); 1947141cc406Sopenharmony_ci return ret; 1948141cc406Sopenharmony_ci} /* sp15c_start_scan */ 1949141cc406Sopenharmony_ci 1950141cc406Sopenharmony_cistatic void 1951141cc406Sopenharmony_cisigterm_handler (int signal) 1952141cc406Sopenharmony_ci{ 1953141cc406Sopenharmony_ci (void) signal; /* silence compilation warnings */ 1954141cc406Sopenharmony_ci 1955141cc406Sopenharmony_ci sanei_scsi_req_flush_all (); /* flush SCSI queue */ 1956141cc406Sopenharmony_ci _exit (SANE_STATUS_GOOD); 1957141cc406Sopenharmony_ci} /* sigterm_handler */ 1958141cc406Sopenharmony_ci 1959141cc406Sopenharmony_ci/* This function is executed as a child process. */ 1960141cc406Sopenharmony_cistatic int 1961141cc406Sopenharmony_cireader_process (void *data) 1962141cc406Sopenharmony_ci{ 1963141cc406Sopenharmony_ci struct sp15c *scanner = (struct sp15c *) data; 1964141cc406Sopenharmony_ci int pipe_fd = scanner->reader_pipe; 1965141cc406Sopenharmony_ci 1966141cc406Sopenharmony_ci int status; 1967141cc406Sopenharmony_ci unsigned int data_left; 1968141cc406Sopenharmony_ci unsigned int data_to_read; 1969141cc406Sopenharmony_ci FILE *fp; 1970141cc406Sopenharmony_ci sigset_t ignore_set; 1971141cc406Sopenharmony_ci sigset_t sigterm_set; 1972141cc406Sopenharmony_ci struct SIGACTION act; 1973141cc406Sopenharmony_ci unsigned int i; 1974141cc406Sopenharmony_ci unsigned char *src, *dst; 1975141cc406Sopenharmony_ci 1976141cc406Sopenharmony_ci DBG (10, "reader_process started\n"); 1977141cc406Sopenharmony_ci 1978141cc406Sopenharmony_ci if (sanei_thread_is_forked ()) 1979141cc406Sopenharmony_ci close (scanner->pipe); 1980141cc406Sopenharmony_ci 1981141cc406Sopenharmony_ci sigfillset (&ignore_set); 1982141cc406Sopenharmony_ci sigdelset (&ignore_set, SIGTERM); 1983141cc406Sopenharmony_ci#if defined (__APPLE__) && defined (__MACH__) 1984141cc406Sopenharmony_ci sigdelset (&ignore_set, SIGUSR2); 1985141cc406Sopenharmony_ci#endif 1986141cc406Sopenharmony_ci sigprocmask (SIG_SETMASK, &ignore_set, 0); 1987141cc406Sopenharmony_ci 1988141cc406Sopenharmony_ci memset (&act, 0, sizeof (act)); 1989141cc406Sopenharmony_ci sigaction (SIGTERM, &act, 0); 1990141cc406Sopenharmony_ci 1991141cc406Sopenharmony_ci sigemptyset (&sigterm_set); 1992141cc406Sopenharmony_ci sigaddset (&sigterm_set, SIGTERM); 1993141cc406Sopenharmony_ci 1994141cc406Sopenharmony_ci fp = fdopen (pipe_fd, "w"); 1995141cc406Sopenharmony_ci if (!fp) 1996141cc406Sopenharmony_ci { 1997141cc406Sopenharmony_ci DBG (1, "reader_process: couldn't open pipe!\n"); 1998141cc406Sopenharmony_ci return 1; 1999141cc406Sopenharmony_ci } 2000141cc406Sopenharmony_ci 2001141cc406Sopenharmony_ci DBG (10, "reader_process: starting to READ data\n"); 2002141cc406Sopenharmony_ci 2003141cc406Sopenharmony_ci data_left = bytes_per_line (scanner) * 2004141cc406Sopenharmony_ci lines_per_scan (scanner); 2005141cc406Sopenharmony_ci 2006141cc406Sopenharmony_ci sp15c_trim_rowbufsize (scanner); /* trim bufsize */ 2007141cc406Sopenharmony_ci 2008141cc406Sopenharmony_ci DBG (10, "reader_process: reading %u bytes in blocks of %u bytes\n", 2009141cc406Sopenharmony_ci data_left, scanner->row_bufsize); 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci memset (&act, 0, sizeof (act)); 2012141cc406Sopenharmony_ci 2013141cc406Sopenharmony_ci act.sa_handler = sigterm_handler; 2014141cc406Sopenharmony_ci sigaction (SIGTERM, &act, 0); 2015141cc406Sopenharmony_ci /* wait_scanner(scanner); */ 2016141cc406Sopenharmony_ci do 2017141cc406Sopenharmony_ci { 2018141cc406Sopenharmony_ci data_to_read = (data_left < scanner->row_bufsize) 2019141cc406Sopenharmony_ci ? data_left 2020141cc406Sopenharmony_ci : scanner->row_bufsize; 2021141cc406Sopenharmony_ci 2022141cc406Sopenharmony_ci if (scanner->composition == WD_comp_G4) 2023141cc406Sopenharmony_ci { 2024141cc406Sopenharmony_ci data_to_read /= 2; /* 'cause each byte holds two pixels */ 2025141cc406Sopenharmony_ci } 2026141cc406Sopenharmony_ci status = sp15c_read_data_block (scanner, data_to_read); 2027141cc406Sopenharmony_ci if (status == 0) 2028141cc406Sopenharmony_ci { 2029141cc406Sopenharmony_ci DBG (1, "reader_process: no data yet\n"); 2030141cc406Sopenharmony_ci fflush (stdout); 2031141cc406Sopenharmony_ci fflush (stderr); 2032141cc406Sopenharmony_ci usleep (50000); 2033141cc406Sopenharmony_ci continue; 2034141cc406Sopenharmony_ci } 2035141cc406Sopenharmony_ci if (status == -1) 2036141cc406Sopenharmony_ci { 2037141cc406Sopenharmony_ci DBG (1, "reader_process: unable to get image data from scanner!\n"); 2038141cc406Sopenharmony_ci fflush (stdout); 2039141cc406Sopenharmony_ci fflush (stderr); 2040141cc406Sopenharmony_ci fclose (fp); 2041141cc406Sopenharmony_ci return (-1); 2042141cc406Sopenharmony_ci } 2043141cc406Sopenharmony_ci 2044141cc406Sopenharmony_ci /* expand 4-bit pixels to 8-bit bytes */ 2045141cc406Sopenharmony_ci if (scanner->composition == WD_comp_G4) 2046141cc406Sopenharmony_ci { 2047141cc406Sopenharmony_ci src = &scanner->buffer[data_to_read - 1]; 2048141cc406Sopenharmony_ci dst = &scanner->buffer[data_to_read * 2 - 1]; 2049141cc406Sopenharmony_ci for (i = 0; i < data_to_read; i++) 2050141cc406Sopenharmony_ci { 2051141cc406Sopenharmony_ci *dst-- = ((*src << 4) & 0xf0) + ((*src) & 0x0f); 2052141cc406Sopenharmony_ci *dst-- = ((*src) & 0xf0) + ((*src >> 4) & 0x0f); 2053141cc406Sopenharmony_ci --src; 2054141cc406Sopenharmony_ci } 2055141cc406Sopenharmony_ci data_to_read *= 2; 2056141cc406Sopenharmony_ci } 2057141cc406Sopenharmony_ci 2058141cc406Sopenharmony_ci fwrite (scanner->buffer, 1, data_to_read, fp); 2059141cc406Sopenharmony_ci fflush (fp); 2060141cc406Sopenharmony_ci 2061141cc406Sopenharmony_ci data_left -= data_to_read; 2062141cc406Sopenharmony_ci DBG (10, "reader_process: buffer of %d bytes read; %d bytes to go\n", 2063141cc406Sopenharmony_ci data_to_read, data_left); 2064141cc406Sopenharmony_ci fflush (stdout); 2065141cc406Sopenharmony_ci fflush (stderr); 2066141cc406Sopenharmony_ci } 2067141cc406Sopenharmony_ci while (data_left); 2068141cc406Sopenharmony_ci 2069141cc406Sopenharmony_ci fclose (fp); 2070141cc406Sopenharmony_ci 2071141cc406Sopenharmony_ci DBG (10, "reader_process: finished\n"); 2072141cc406Sopenharmony_ci 2073141cc406Sopenharmony_ci return 0; 2074141cc406Sopenharmony_ci} /* reader_process */ 2075141cc406Sopenharmony_ci 2076141cc406Sopenharmony_cistatic SANE_Status 2077141cc406Sopenharmony_cido_eof (struct sp15c *scanner) 2078141cc406Sopenharmony_ci{ 2079141cc406Sopenharmony_ci DBG (10, "do_eof\n"); 2080141cc406Sopenharmony_ci 2081141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2082141cc406Sopenharmony_ci if (scanner->pipe >= 0) 2083141cc406Sopenharmony_ci { 2084141cc406Sopenharmony_ci close (scanner->pipe); 2085141cc406Sopenharmony_ci scanner->pipe = -1; 2086141cc406Sopenharmony_ci } 2087141cc406Sopenharmony_ci return SANE_STATUS_EOF; 2088141cc406Sopenharmony_ci} /* do_eof */ 2089141cc406Sopenharmony_ci 2090141cc406Sopenharmony_cistatic int 2091141cc406Sopenharmony_cipixels_per_line (struct sp15c *s) 2092141cc406Sopenharmony_ci{ 2093141cc406Sopenharmony_ci int pixels; 2094141cc406Sopenharmony_ci pixels = s->x_res * (s->br_x - s->tl_x) / 1200; 2095141cc406Sopenharmony_ci return pixels; 2096141cc406Sopenharmony_ci} /* pixels_per_line */ 2097141cc406Sopenharmony_ci 2098141cc406Sopenharmony_cistatic int 2099141cc406Sopenharmony_cilines_per_scan (struct sp15c *s) 2100141cc406Sopenharmony_ci{ 2101141cc406Sopenharmony_ci int lines; 2102141cc406Sopenharmony_ci lines = s->y_res * (s->br_y - s->tl_y) / 1200; 2103141cc406Sopenharmony_ci return lines; 2104141cc406Sopenharmony_ci} /* lines_per_scan */ 2105141cc406Sopenharmony_ci 2106141cc406Sopenharmony_cistatic int 2107141cc406Sopenharmony_cibytes_per_line (struct sp15c *s) 2108141cc406Sopenharmony_ci{ 2109141cc406Sopenharmony_ci int bytes; 2110141cc406Sopenharmony_ci /* SEE PAGE 29 OF SANE SPEC!!! */ 2111141cc406Sopenharmony_ci if (s->bitsperpixel == 1) 2112141cc406Sopenharmony_ci { 2113141cc406Sopenharmony_ci bytes = (pixels_per_line (s) + 7) / 8; 2114141cc406Sopenharmony_ci } 2115141cc406Sopenharmony_ci else 2116141cc406Sopenharmony_ci { 2117141cc406Sopenharmony_ci bytes = pixels_per_line (s); 2118141cc406Sopenharmony_ci } 2119141cc406Sopenharmony_ci if (s->composition == WD_comp_MC) 2120141cc406Sopenharmony_ci { 2121141cc406Sopenharmony_ci bytes *= 3; 2122141cc406Sopenharmony_ci } 2123141cc406Sopenharmony_ci return bytes; 2124141cc406Sopenharmony_ci} /* bytes_per_line */ 2125141cc406Sopenharmony_ci 2126141cc406Sopenharmony_cistatic void 2127141cc406Sopenharmony_cisp15c_trim_rowbufsize (struct sp15c *s) 2128141cc406Sopenharmony_ci{ 2129141cc406Sopenharmony_ci unsigned int row_len; 2130141cc406Sopenharmony_ci row_len = bytes_per_line (s); 2131141cc406Sopenharmony_ci if (s->row_bufsize >= row_len) 2132141cc406Sopenharmony_ci { 2133141cc406Sopenharmony_ci s->row_bufsize = s->row_bufsize - (s->row_bufsize % row_len); 2134141cc406Sopenharmony_ci DBG (10, "trim_rowbufsize to %d (%d lines)\n", 2135141cc406Sopenharmony_ci s->row_bufsize, s->row_bufsize / row_len); 2136141cc406Sopenharmony_ci } 2137141cc406Sopenharmony_ci} /* sp15c_trim_rowbufsize */ 2138141cc406Sopenharmony_ci 2139141cc406Sopenharmony_cistatic int 2140141cc406Sopenharmony_cisp15c_read_data_block (struct sp15c *s, unsigned int length) 2141141cc406Sopenharmony_ci{ 2142141cc406Sopenharmony_ci int r; 2143141cc406Sopenharmony_ci 2144141cc406Sopenharmony_ci DBG (10, "sp15c_read_data_block (length = %d)\n", length); 2145141cc406Sopenharmony_ci /*wait_scanner(s); */ 2146141cc406Sopenharmony_ci 2147141cc406Sopenharmony_ci set_R_datatype_code (readB.cmd, R_datatype_imagedata); 2148141cc406Sopenharmony_ci set_R_xfer_length (readB.cmd, length); 2149141cc406Sopenharmony_ci 2150141cc406Sopenharmony_ci r = do_scsi_cmd (s->sfd, readB.cmd, readB.size, s->buffer, length); 2151141cc406Sopenharmony_ci#if 0 2152141cc406Sopenharmony_ci return ((r != 0) ? -1 : length); 2153141cc406Sopenharmony_ci#else 2154141cc406Sopenharmony_ci if (r) 2155141cc406Sopenharmony_ci { 2156141cc406Sopenharmony_ci return -1; 2157141cc406Sopenharmony_ci } 2158141cc406Sopenharmony_ci else 2159141cc406Sopenharmony_ci { 2160141cc406Sopenharmony_ci return length; 2161141cc406Sopenharmony_ci } 2162141cc406Sopenharmony_ci#endif 2163141cc406Sopenharmony_ci} /* sp15c_read_data_block */ 2164141cc406Sopenharmony_ci 2165141cc406Sopenharmony_ci/* Increase initial width by increasing bottom right X 2166141cc406Sopenharmony_ci * until we have a HAPPY number of bytes in line. 2167141cc406Sopenharmony_ci * Should be called whenever s->composition, s->x_res, 2168141cc406Sopenharmony_ci * s->br_x, or s->tl_x are changed */ 2169141cc406Sopenharmony_cistatic void 2170141cc406Sopenharmony_ciadjust_width (struct sp15c *s, SANE_Int * info) 2171141cc406Sopenharmony_ci{ 2172141cc406Sopenharmony_ci int pixels; 2173141cc406Sopenharmony_ci int changed = 0; 2174141cc406Sopenharmony_ci if (s->composition == WD_comp_MC) 2175141cc406Sopenharmony_ci { 2176141cc406Sopenharmony_ci while (pixels = s->x_res * (s->br_x - s->tl_x) / 1200, 2177141cc406Sopenharmony_ci (s->bitsperpixel * pixels) % (8 * 4)) 2178141cc406Sopenharmony_ci { 2179141cc406Sopenharmony_ci s->br_x--; 2180141cc406Sopenharmony_ci changed++; 2181141cc406Sopenharmony_ci } 2182141cc406Sopenharmony_ci } 2183141cc406Sopenharmony_ci else 2184141cc406Sopenharmony_ci { 2185141cc406Sopenharmony_ci while (pixels = s->x_res * (s->br_x - s->tl_x) / 1200, 2186141cc406Sopenharmony_ci (s->bitsperpixel * pixels) % 8) 2187141cc406Sopenharmony_ci { 2188141cc406Sopenharmony_ci s->br_x--; 2189141cc406Sopenharmony_ci changed++; 2190141cc406Sopenharmony_ci } 2191141cc406Sopenharmony_ci } 2192141cc406Sopenharmony_ci if (changed && info) 2193141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 2194141cc406Sopenharmony_ci 2195141cc406Sopenharmony_ci return; 2196141cc406Sopenharmony_ci} /* adjust_width */ 2197141cc406Sopenharmony_ci 2198141cc406Sopenharmony_cistatic SANE_Status 2199141cc406Sopenharmony_ciapply_constraints (struct sp15c *scanner, SANE_Int opt, 2200141cc406Sopenharmony_ci SANE_Int * target, SANE_Word * info) 2201141cc406Sopenharmony_ci{ 2202141cc406Sopenharmony_ci SANE_Status status; 2203141cc406Sopenharmony_ci status = sanei_constrain_value (scanner->opt + opt, target, info); 2204141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2205141cc406Sopenharmony_ci { 2206141cc406Sopenharmony_ci if (SANE_CONSTRAINT_RANGE == 2207141cc406Sopenharmony_ci scanner->opt[opt].constraint_type) 2208141cc406Sopenharmony_ci { 2209141cc406Sopenharmony_ci if (*target < scanner->opt[opt].constraint.range->min) 2210141cc406Sopenharmony_ci { 2211141cc406Sopenharmony_ci *target = scanner->opt[opt].constraint.range->min; 2212141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2213141cc406Sopenharmony_ci } 2214141cc406Sopenharmony_ci else if (scanner->opt[opt].constraint.range->max < *target) 2215141cc406Sopenharmony_ci { 2216141cc406Sopenharmony_ci *target = scanner->opt[opt].constraint.range->max; 2217141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2218141cc406Sopenharmony_ci } 2219141cc406Sopenharmony_ci } 2220141cc406Sopenharmony_ci return status; 2221141cc406Sopenharmony_ci } 2222141cc406Sopenharmony_ci else 2223141cc406Sopenharmony_ci { 2224141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2225141cc406Sopenharmony_ci } 2226141cc406Sopenharmony_ci} /* apply_constraints */ 2227141cc406Sopenharmony_ci 2228141cc406Sopenharmony_ci/****************************************************************************** 2229141cc406Sopenharmony_ci}############################################################################# 2230141cc406Sopenharmony_ci******************************************************************************/ 2231