1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 1998, 1999 4141cc406Sopenharmony_ci Kazuya Fukuda, Abel Deuring based on BYTEC GmbH Germany 5141cc406Sopenharmony_ci Written by Helmut Koeberle previous Work on canon.c file from the 6141cc406Sopenharmony_ci SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This file is part of the SANE package. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 11141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 12141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 13141cc406Sopenharmony_ci License, or (at your option) any later version. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 16141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 17141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18141cc406Sopenharmony_ci General Public License for more details. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 21141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 24141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 27141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 28141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 29141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 30141cc406Sopenharmony_ci account of linking the SANE library code into it. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 33141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 34141cc406Sopenharmony_ci License. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 37141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 38141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 41141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 42141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci This file implements a SANE backend for Sharp flatbed scanners. */ 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci/* 47141cc406Sopenharmony_ci Version 0.32 48141cc406Sopenharmony_ci changes to version 0.31: 49141cc406Sopenharmony_ci - support for JX320 added (Thanks to Isaac Wilcox for providind the 50141cc406Sopenharmony_ci patch) 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci Version 0.31 53141cc406Sopenharmony_ci changes to version 0.30: 54141cc406Sopenharmony_ci - support for JX350 added (Thanks to Shuhei Tomita for providind the 55141cc406Sopenharmony_ci patch) 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci changes to version 0.20 58141cc406Sopenharmony_ci - support for the proposed extended open function in sanei_scsi.c added 59141cc406Sopenharmony_ci - support for ADF and FSU (transparency adapter) added 60141cc406Sopenharmony_ci - simple sense handler added 61141cc406Sopenharmony_ci - preview added 62141cc406Sopenharmony_ci - added several missing statements "s->fd = -1;" after 63141cc406Sopenharmony_ci "sanei_scsi_close(s->fd)" to error returns in sane_start(); 64141cc406Sopenharmony_ci - maximum scan sizes are read from the scanner, if a JX330 or JX250 65141cc406Sopenharmony_ci is used. (this avoids the guessing of scan sizes for the JX330) 66141cc406Sopenharmony_ci - gamma table support added 67141cc406Sopenharmony_ci - "Fixed gamma selection (1.0/2.2)", available for JX330 and JX610, 68141cc406Sopenharmony_ci is now implemented for the JX250 by downloading a gamma table 69141cc406Sopenharmony_ci - changed the calls to free() and strdup() in sane_control_option to 70141cc406Sopenharmony_ci strcpy. 71141cc406Sopenharmony_ci (I don't like too frequent unchecked malloc()s and strdups :) Abel) 72141cc406Sopenharmony_ci - cleaned up some quirks in option handling, eg, that "threshold" 73141cc406Sopenharmony_ci was initially enabled, while the initial scan mode is "color" 74141cc406Sopenharmony_ci - cleaned up setting SANE_INFO_RELOAD_OPTIONS and SANE_INFO_RELOAD_PARAMS 75141cc406Sopenharmony_ci bits in sane_control_option 76141cc406Sopenharmony_ci - bi-level color scans now give useful (8 bit) output 77141cc406Sopenharmony_ci - separate thresholds for red, green, blue (bi-level color scan) added 78141cc406Sopenharmony_ci*/ 79141cc406Sopenharmony_ci#include "../include/sane/config.h" 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci#include <limits.h> 82141cc406Sopenharmony_ci#include <stdlib.h> 83141cc406Sopenharmony_ci#include <stdarg.h> 84141cc406Sopenharmony_ci#include <string.h> 85141cc406Sopenharmony_ci#include <unistd.h> 86141cc406Sopenharmony_ci#include <errno.h> 87141cc406Sopenharmony_ci#include <math.h> 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci#include "../include/sane/sane.h" 90141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 91141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci/* QUEUEDEBUG should be undefined unless you want to play 94141cc406Sopenharmony_ci with the sanei_scsi.c under Linux and/or with the Linux's SG driver, 95141cc406Sopenharmony_ci or your suspect problems with command queueing 96141cc406Sopenharmony_ci*/ 97141cc406Sopenharmony_ci#if 0 98141cc406Sopenharmony_ci#define QUEUEDEBUG 99141cc406Sopenharmony_ci#define DEBUG 100141cc406Sopenharmony_ci#ifdef DEBUG 101141cc406Sopenharmony_ci#include <unistd.h> 102141cc406Sopenharmony_ci#include <sys/time.h> 103141cc406Sopenharmony_ci#endif 104141cc406Sopenharmony_ci#endif 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci/* USE_FORK: fork a special reader process 107141cc406Sopenharmony_ci*/ 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci#ifdef HAVE_SYS_SHM_H 110141cc406Sopenharmony_ci#ifndef HAVE_OS2_H 111141cc406Sopenharmony_ci#define USE_FORK 112141cc406Sopenharmony_ci#endif 113141cc406Sopenharmony_ci#endif 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_ci#ifdef USE_FORK 116141cc406Sopenharmony_ci#include <signal.h> 117141cc406Sopenharmony_ci#include <fcntl.h> 118141cc406Sopenharmony_ci#include <sys/types.h> 119141cc406Sopenharmony_ci#include <sys/wait.h> 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_ci#include <sys/ipc.h> 122141cc406Sopenharmony_ci#include <sys/shm.h> 123141cc406Sopenharmony_ci 124141cc406Sopenharmony_ci#endif /* USE_FORK */ 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci/* xxx I'm not sure, if I understood the JX610 and JX330 manuals right, 127141cc406Sopenharmony_ci that the data for the SEND command should be in ASCII format... 128141cc406Sopenharmony_ci SEND commands with a data bock are used, if USE_CUSTOM_GAMMA 129141cc406Sopenharmony_ci and / or USE_COLOR_THRESHOLD are enabled. 130141cc406Sopenharmony_ci Abel 131141cc406Sopenharmony_ci*/ 132141cc406Sopenharmony_ci#define USE_CUSTOM_GAMMA 133141cc406Sopenharmony_ci#define USE_COLOR_THRESHOLD 134141cc406Sopenharmony_ci/* enable a short list of some standard resolutions. XSane provides 135141cc406Sopenharmony_ci its own resolution list; therefore its is generally not reasonable 136141cc406Sopenharmony_ci to enable this list, if you mainly using XSane. But it might be handy 137141cc406Sopenharmony_ci if you are working with xscanimage 138141cc406Sopenharmony_ci*/ 139141cc406Sopenharmony_ci/* #define USE_RESOLUTION_LIST */ 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci/* enable separate specification of resolution in X and Y direction. 142141cc406Sopenharmony_ci XSane will show the Y-resolution at a quite different place than 143141cc406Sopenharmony_ci the X-resolution 144141cc406Sopenharmony_ci*/ 145141cc406Sopenharmony_ci/* #define USE_SEPARATE_Y_RESOLUTION */ 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci 148141cc406Sopenharmony_ci#define BACKEND_NAME sharp 149141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_ci#include <sharp.h> 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_ci#ifndef PATH_MAX 154141cc406Sopenharmony_ci#define PATH_MAX 1024 155141cc406Sopenharmony_ci#endif 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci#define DEFAULT_MUD_JX610 25 158141cc406Sopenharmony_ci#define DEFAULT_MUD_JX320 25 159141cc406Sopenharmony_ci#define DEFAULT_MUD_JX330 1200 160141cc406Sopenharmony_ci#define DEFAULT_MUD_JX250 1200 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_ci#define PIX_TO_MM(x, mud) ((x) * 25.4 / mud) 163141cc406Sopenharmony_ci#define MM_TO_PIX(x, mud) ((x) * mud / 25.4) 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 166141cc406Sopenharmony_ci#define SHARP_CONFIG_FILE "sharp.conf" 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_cistatic int num_devices = 0; 169141cc406Sopenharmony_cistatic SHARP_Device *first_dev = NULL; 170141cc406Sopenharmony_cistatic SHARP_Scanner *first_handle = NULL; 171141cc406Sopenharmony_ci 172141cc406Sopenharmony_citypedef enum 173141cc406Sopenharmony_ci { 174141cc406Sopenharmony_ci MODES_LINEART = 0, 175141cc406Sopenharmony_ci MODES_GRAY, 176141cc406Sopenharmony_ci MODES_LINEART_COLOR, 177141cc406Sopenharmony_ci MODES_COLOR 178141cc406Sopenharmony_ci } 179141cc406Sopenharmony_ciModes; 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci#define M_LINEART SANE_VALUE_SCAN_MODE_LINEART 182141cc406Sopenharmony_ci#define M_GRAY SANE_VALUE_SCAN_MODE_GRAY 183141cc406Sopenharmony_ci#define M_LINEART_COLOR SANE_VALUE_SCAN_MODE_COLOR_LINEART 184141cc406Sopenharmony_ci#define M_COLOR SANE_VALUE_SCAN_MODE_COLOR 185141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] = 186141cc406Sopenharmony_ci{ 187141cc406Sopenharmony_ci M_LINEART, M_GRAY, M_LINEART_COLOR, M_COLOR, 188141cc406Sopenharmony_ci 0 189141cc406Sopenharmony_ci}; 190141cc406Sopenharmony_ci 191141cc406Sopenharmony_ci#define M_BILEVEL "none" 192141cc406Sopenharmony_ci#define M_BAYER "Dither Bayer" 193141cc406Sopenharmony_ci#define M_SPIRAL "Dither Spiral" 194141cc406Sopenharmony_ci#define M_DISPERSED "Dither Dispersed" 195141cc406Sopenharmony_ci#define M_ERRDIFFUSION "Error Diffusion" 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list[] = 198141cc406Sopenharmony_ci{ 199141cc406Sopenharmony_ci M_BILEVEL, M_BAYER, M_SPIRAL, M_DISPERSED, M_ERRDIFFUSION, 200141cc406Sopenharmony_ci 0 201141cc406Sopenharmony_ci}; 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci#define LIGHT_GREEN "green" 204141cc406Sopenharmony_ci#define LIGHT_RED "red" 205141cc406Sopenharmony_ci#define LIGHT_BLUE "blue" 206141cc406Sopenharmony_ci#define LIGHT_WHITE "white" 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci#define MAX_RETRIES 50 209141cc406Sopenharmony_ci 210141cc406Sopenharmony_cistatic const SANE_String_Const light_color_list[] = 211141cc406Sopenharmony_ci{ 212141cc406Sopenharmony_ci LIGHT_GREEN, LIGHT_RED, LIGHT_BLUE, LIGHT_WHITE, 213141cc406Sopenharmony_ci 0 214141cc406Sopenharmony_ci}; 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_ci/* possible values for ADF/FSU selection */ 217141cc406Sopenharmony_cistatic SANE_String use_adf = "Automatic Document Feeder"; 218141cc406Sopenharmony_cistatic SANE_String use_fsu = "Transparency Adapter"; 219141cc406Sopenharmony_cistatic SANE_String use_simple = "Flatbed"; 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci/* auto selection of ADF and FSU, as described in the JX330 manual, 222141cc406Sopenharmony_ci is a nice idea -- but I assume that the possible scan window 223141cc406Sopenharmony_ci sizes depend not only for the JX250, but also for JX330 on the 224141cc406Sopenharmony_ci usage of ADF or FSU. Thus, the user might be able to select scan 225141cc406Sopenharmony_ci windows of an "illegal" size, which would have to be automatically 226141cc406Sopenharmony_ci corrected, and I don't see, how the user could be informed about 227141cc406Sopenharmony_ci this "window clipping". More important, I don't see, how the 228141cc406Sopenharmony_ci frontend could be informed that the ADF is automatically enabled. 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci Insert a "#define ALLOW_AUTO_SELECT_ADF", if you want to play 231141cc406Sopenharmony_ci with this feature. 232141cc406Sopenharmony_ci*/ 233141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF 234141cc406Sopenharmony_cistatic SANE_String_Const use_auto = "AutoSelection"; 235141cc406Sopenharmony_ci#endif 236141cc406Sopenharmony_ci 237141cc406Sopenharmony_ci#define HAVE_FSU 1 238141cc406Sopenharmony_ci#define HAVE_ADF 2 239141cc406Sopenharmony_ci 240141cc406Sopenharmony_ci/* The follow #defines are used in SHARP_Scanner.adf_fsu_mode 241141cc406Sopenharmony_ci and as indexes for the arrays x_ranges, y_ranges in SHARP_Device 242141cc406Sopenharmony_ci*/ 243141cc406Sopenharmony_ci#define SCAN_SIMPLE 0 244141cc406Sopenharmony_ci#define SCAN_WITH_FSU 1 245141cc406Sopenharmony_ci#define SCAN_WITH_ADF 2 246141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF 247141cc406Sopenharmony_ci#define SCAN_ADF_FSU_AUTO 3 248141cc406Sopenharmony_ci#endif 249141cc406Sopenharmony_ci#define LOAD_PAPER 1 250141cc406Sopenharmony_ci#define UNLOAD_PAPER 0 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ci#define PAPER_MAX 10 253141cc406Sopenharmony_ci#define W_LETTER "11\"x17\"" 254141cc406Sopenharmony_ci#define INVOICE "8.5\"x5.5\"" 255141cc406Sopenharmony_cistatic const SANE_String_Const paper_list_jx610[] = 256141cc406Sopenharmony_ci{ 257141cc406Sopenharmony_ci "A3", "A4", "A5", "A6", "B4", "B5", 258141cc406Sopenharmony_ci W_LETTER, "Legal", "Letter", INVOICE, 259141cc406Sopenharmony_ci 0 260141cc406Sopenharmony_ci}; 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_cistatic const SANE_String_Const paper_list_jx330[] = 263141cc406Sopenharmony_ci{ 264141cc406Sopenharmony_ci "A4", "A5", "A6", "B5", 265141cc406Sopenharmony_ci 0 266141cc406Sopenharmony_ci}; 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci#define GAMMA10 "1.0" 269141cc406Sopenharmony_ci#define GAMMA22 "2.2" 270141cc406Sopenharmony_ci 271141cc406Sopenharmony_cistatic const SANE_String_Const gamma_list[] = 272141cc406Sopenharmony_ci{ 273141cc406Sopenharmony_ci GAMMA10, GAMMA22, 274141cc406Sopenharmony_ci 0 275141cc406Sopenharmony_ci}; 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci#if 0 278141cc406Sopenharmony_ci#define SPEED_NORMAL "Normal" 279141cc406Sopenharmony_ci#define SPEED_FAST "Fast" 280141cc406Sopenharmony_cistatic const SANE_String_Const speed_list[] = 281141cc406Sopenharmony_ci{ 282141cc406Sopenharmony_ci SPEED_NORMAL, SPEED_FAST, 283141cc406Sopenharmony_ci 0 284141cc406Sopenharmony_ci}; 285141cc406Sopenharmony_ci#endif 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST 288141cc406Sopenharmony_ci#define RESOLUTION_MAX_JX610 8 289141cc406Sopenharmony_cistatic const SANE_String_Const resolution_list_jx610[] = 290141cc406Sopenharmony_ci{ 291141cc406Sopenharmony_ci "50", "75", "100", "150", "200", "300", "400", "600", "Select", 292141cc406Sopenharmony_ci 0 293141cc406Sopenharmony_ci}; 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_ci#define RESOLUTION_MAX_JX250 7 296141cc406Sopenharmony_cistatic const SANE_String_Const resolution_list_jx250[] = 297141cc406Sopenharmony_ci{ 298141cc406Sopenharmony_ci "50", "75", "100", "150", "200", "300", "400", "Select", 299141cc406Sopenharmony_ci 0 300141cc406Sopenharmony_ci}; 301141cc406Sopenharmony_ci#endif 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci#define EDGE_NONE "None" 304141cc406Sopenharmony_ci#define EDGE_MIDDLE "Middle" 305141cc406Sopenharmony_ci#define EDGE_STRONG "Strong" 306141cc406Sopenharmony_ci#define EDGE_BLUR "Blur" 307141cc406Sopenharmony_cistatic const SANE_String_Const edge_emphasis_list[] = 308141cc406Sopenharmony_ci{ 309141cc406Sopenharmony_ci EDGE_NONE, EDGE_MIDDLE, EDGE_STRONG, EDGE_BLUR, 310141cc406Sopenharmony_ci 0 311141cc406Sopenharmony_ci}; 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 314141cc406Sopenharmony_cistatic const SANE_Range u8_range = 315141cc406Sopenharmony_ci { 316141cc406Sopenharmony_ci 0, /* minimum */ 317141cc406Sopenharmony_ci 255, /* maximum */ 318141cc406Sopenharmony_ci 0 /* quantization */ 319141cc406Sopenharmony_ci }; 320141cc406Sopenharmony_ci#endif 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_cistatic SANE_Status 323141cc406Sopenharmony_cisense_handler(int __sane_unused__ fd, u_char *sense_buffer, void *s) 324141cc406Sopenharmony_ci{ 325141cc406Sopenharmony_ci int sense_key; 326141cc406Sopenharmony_ci SHARP_Sense_Data *sdat = (SHARP_Sense_Data *) s; 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci#define add_sense_code sense_buffer[12] 329141cc406Sopenharmony_ci#define add_sense_qual sense_buffer[13] 330141cc406Sopenharmony_ci 331141cc406Sopenharmony_ci memcpy(sdat->sb, sense_buffer, 16); 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci DBG(10, "sense code: %02x %02x %02x %02x %02x %02x %02x %02x " 334141cc406Sopenharmony_ci "%02x %02x %02x %02x %02x %02x %02x %02x\n", 335141cc406Sopenharmony_ci sense_buffer[0], sense_buffer[1], sense_buffer[2], sense_buffer[3], 336141cc406Sopenharmony_ci sense_buffer[4], sense_buffer[5], sense_buffer[6], sense_buffer[7], 337141cc406Sopenharmony_ci sense_buffer[8], sense_buffer[9], sense_buffer[10], sense_buffer[11], 338141cc406Sopenharmony_ci sense_buffer[12], sense_buffer[13], sense_buffer[14], sense_buffer[15]); 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ci sense_key = sense_buffer[2] & 0x0F; 341141cc406Sopenharmony_ci /* do we have additional information ? */ 342141cc406Sopenharmony_ci if (sense_buffer[7] >= 5) 343141cc406Sopenharmony_ci { 344141cc406Sopenharmony_ci if (sdat->model == JX610) 345141cc406Sopenharmony_ci { 346141cc406Sopenharmony_ci /* The JX610 uses somewhat different error codes */ 347141cc406Sopenharmony_ci switch (add_sense_code) 348141cc406Sopenharmony_ci { 349141cc406Sopenharmony_ci case 0x04: 350141cc406Sopenharmony_ci DBG(5, "error: scanner not ready\n"); 351141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 352141cc406Sopenharmony_ci case 0x08: 353141cc406Sopenharmony_ci DBG(5, "error: scanner communication failure (time out?)\n"); 354141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 355141cc406Sopenharmony_ci case 0x1A: 356141cc406Sopenharmony_ci DBG(10, "error: parameter list length error\n"); 357141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 358141cc406Sopenharmony_ci case 0x20: 359141cc406Sopenharmony_ci DBG(10, "error: invalid command code\n"); 360141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 361141cc406Sopenharmony_ci case 0x24: 362141cc406Sopenharmony_ci DBG(10, "error: invalid field in CDB\n"); 363141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 364141cc406Sopenharmony_ci case 0x25: 365141cc406Sopenharmony_ci DBG(10, "error: LUN not supported\n"); 366141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 367141cc406Sopenharmony_ci case 0x26: 368141cc406Sopenharmony_ci DBG(10, "error: invalid field in parameter list\n"); 369141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 370141cc406Sopenharmony_ci case 0x29: 371141cc406Sopenharmony_ci DBG(10, "note: reset occurred\n"); 372141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 373141cc406Sopenharmony_ci case 0x2a: 374141cc406Sopenharmony_ci DBG(10, "note: mode parameter change\n"); 375141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 376141cc406Sopenharmony_ci case 0x37: 377141cc406Sopenharmony_ci DBG(10, "note: rounded parameter\n"); 378141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 379141cc406Sopenharmony_ci case 0x39: 380141cc406Sopenharmony_ci DBG(10, "error: saving parameter not supported\n"); 381141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 382141cc406Sopenharmony_ci case 0x47: 383141cc406Sopenharmony_ci DBG(10, "SCSI parity error\n"); 384141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 385141cc406Sopenharmony_ci case 0x48: 386141cc406Sopenharmony_ci DBG(10, "initiator detected error message received\n"); 387141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 388141cc406Sopenharmony_ci case 0x60: 389141cc406Sopenharmony_ci DBG(1, "error: lamp failure\n"); 390141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 391141cc406Sopenharmony_ci case 0x62: 392141cc406Sopenharmony_ci DBG(1, "scan head positioning error\n"); 393141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 394141cc406Sopenharmony_ci } 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci } 397141cc406Sopenharmony_ci else if (sdat->model == JX250 || sdat->model == JX330 || 398141cc406Sopenharmony_ci sdat->model == JX350 || sdat->model == JX320) 399141cc406Sopenharmony_ci { 400141cc406Sopenharmony_ci switch (sense_key) 401141cc406Sopenharmony_ci { 402141cc406Sopenharmony_ci case 0x02: /* not ready */ 403141cc406Sopenharmony_ci switch (add_sense_code) 404141cc406Sopenharmony_ci { 405141cc406Sopenharmony_ci case 0x80: 406141cc406Sopenharmony_ci switch (add_sense_qual) 407141cc406Sopenharmony_ci { 408141cc406Sopenharmony_ci case 0: 409141cc406Sopenharmony_ci DBG(1, "Scanner not ready: ADF cover open\n"); 410141cc406Sopenharmony_ci if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) 411141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 412141cc406Sopenharmony_ci else 413141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 414141cc406Sopenharmony_ci case 1: 415141cc406Sopenharmony_ci DBG(1, "Scanner not ready: ADF maintenance " 416141cc406Sopenharmony_ci "cover open\n"); 417141cc406Sopenharmony_ci if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) 418141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 419141cc406Sopenharmony_ci else 420141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 421141cc406Sopenharmony_ci default: 422141cc406Sopenharmony_ci DBG(5, "Scanner not ready: undocumented reason\n"); 423141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 424141cc406Sopenharmony_ci } 425141cc406Sopenharmony_ci case 0x81: 426141cc406Sopenharmony_ci /* NOT TESTED -- I don't have a FSU */ 427141cc406Sopenharmony_ci switch (add_sense_qual) 428141cc406Sopenharmony_ci { 429141cc406Sopenharmony_ci case 0: 430141cc406Sopenharmony_ci DBG(1, "Scanner not ready: FSU cover open\n"); 431141cc406Sopenharmony_ci if (sdat->complain_on_errors & COMPLAIN_ON_FSU_ERROR) 432141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 433141cc406Sopenharmony_ci else 434141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 435141cc406Sopenharmony_ci case 1: 436141cc406Sopenharmony_ci DBG(1, "Scanner not ready: FSU light dispersion " 437141cc406Sopenharmony_ci "error\n"); 438141cc406Sopenharmony_ci if (sdat->complain_on_errors & COMPLAIN_ON_FSU_ERROR) 439141cc406Sopenharmony_ci { 440141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 441141cc406Sopenharmony_ci } 442141cc406Sopenharmony_ci else 443141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 444141cc406Sopenharmony_ci default: 445141cc406Sopenharmony_ci DBG(5, "Scanner not ready: undocumented reason\n"); 446141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 447141cc406Sopenharmony_ci } 448141cc406Sopenharmony_ci default: 449141cc406Sopenharmony_ci DBG(5, "Scanner not ready: undocumented reason\n"); 450141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 451141cc406Sopenharmony_ci } 452141cc406Sopenharmony_ci case 0x03: /* medium error */ 453141cc406Sopenharmony_ci switch (add_sense_code) 454141cc406Sopenharmony_ci { 455141cc406Sopenharmony_ci case 0x3a: 456141cc406Sopenharmony_ci DBG(1, "ADF is empty\n"); 457141cc406Sopenharmony_ci if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) 458141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 459141cc406Sopenharmony_ci else 460141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 461141cc406Sopenharmony_ci case 0x53: 462141cc406Sopenharmony_ci DBG(1, "ADF paper jam\n" 463141cc406Sopenharmony_ci "Open and close the maintenance cover to clear " 464141cc406Sopenharmony_ci "this error\n"); 465141cc406Sopenharmony_ci if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) 466141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 467141cc406Sopenharmony_ci else 468141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 469141cc406Sopenharmony_ci default: 470141cc406Sopenharmony_ci DBG(5, "medium error: undocumented reason\n"); 471141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 472141cc406Sopenharmony_ci } 473141cc406Sopenharmony_ci case 0x04: /* hardware error */ 474141cc406Sopenharmony_ci switch (add_sense_code) 475141cc406Sopenharmony_ci { 476141cc406Sopenharmony_ci case 0x08: 477141cc406Sopenharmony_ci DBG(1, "hardware error: scanner communication failed\n"); 478141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 479141cc406Sopenharmony_ci case 0x60: 480141cc406Sopenharmony_ci DBG(1, "hardware error: lamp failure\n"); 481141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 482141cc406Sopenharmony_ci case 0x62: 483141cc406Sopenharmony_ci DBG(1, "hardware error: scan head positioning failed\n"); 484141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 485141cc406Sopenharmony_ci default: 486141cc406Sopenharmony_ci DBG(1, "general hardware error\n"); 487141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 488141cc406Sopenharmony_ci } 489141cc406Sopenharmony_ci case 0x05: /* illegal request */ 490141cc406Sopenharmony_ci DBG(10, "error: illegal request\n"); 491141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 492141cc406Sopenharmony_ci case 0x06: /* unit attention */ 493141cc406Sopenharmony_ci switch (add_sense_code) 494141cc406Sopenharmony_ci { 495141cc406Sopenharmony_ci case 0x29: 496141cc406Sopenharmony_ci DBG(5, "unit attention: reset occurred\n"); 497141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 498141cc406Sopenharmony_ci case 0x2a: 499141cc406Sopenharmony_ci DBG(5, "unit attention: parameter changed by " 500141cc406Sopenharmony_ci "another initiator\n"); 501141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 502141cc406Sopenharmony_ci default: 503141cc406Sopenharmony_ci DBG(5, "unit attention: exact reason not documented\n"); 504141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 505141cc406Sopenharmony_ci } 506141cc406Sopenharmony_ci case 0x09: /* data remains */ 507141cc406Sopenharmony_ci DBG(5, "error: data remains\n"); 508141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 509141cc406Sopenharmony_ci default: 510141cc406Sopenharmony_ci DBG(5, "error: sense code not documented\n"); 511141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 512141cc406Sopenharmony_ci } 513141cc406Sopenharmony_ci } 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 516141cc406Sopenharmony_ci} 517141cc406Sopenharmony_ci 518141cc406Sopenharmony_cistatic SANE_Status 519141cc406Sopenharmony_citest_unit_ready (int fd) 520141cc406Sopenharmony_ci{ 521141cc406Sopenharmony_ci static u_char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0}; 522141cc406Sopenharmony_ci SANE_Status status; 523141cc406Sopenharmony_ci DBG (11, "<< test_unit_ready "); 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci DBG (11, ">>\n"); 528141cc406Sopenharmony_ci return (status); 529141cc406Sopenharmony_ci} 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci#if 0 532141cc406Sopenharmony_cistatic SANE_Status 533141cc406Sopenharmony_cirequest_sense (int fd, void *sense_buf, size_t *sense_size) 534141cc406Sopenharmony_ci{ 535141cc406Sopenharmony_ci static u_char cmd[] = {REQUEST_SENSE, 0, 0, 0, SENSE_LEN, 0}; 536141cc406Sopenharmony_ci SANE_Status status; 537141cc406Sopenharmony_ci DBG (11, "<< request_sense "); 538141cc406Sopenharmony_ci 539141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), sense_buf, sense_size); 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ci DBG (11, ">>\n"); 542141cc406Sopenharmony_ci return (status); 543141cc406Sopenharmony_ci} 544141cc406Sopenharmony_ci#endif 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_cistatic SANE_Status 547141cc406Sopenharmony_ciinquiry (int fd, void *inq_buf, size_t *inq_size) 548141cc406Sopenharmony_ci{ 549141cc406Sopenharmony_ci static u_char cmd[] = {INQUIRY, 0, 0, 0, INQUIRY_LEN, 0}; 550141cc406Sopenharmony_ci SANE_Status status; 551141cc406Sopenharmony_ci DBG (11, "<< inquiry "); 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), inq_buf, inq_size); 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci DBG (11, ">>\n"); 556141cc406Sopenharmony_ci return (status); 557141cc406Sopenharmony_ci} 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_cistatic SANE_Status 560141cc406Sopenharmony_cimode_select_mud (int fd, int mud) 561141cc406Sopenharmony_ci{ 562141cc406Sopenharmony_ci static u_char cmd[6 + MODEPARAM_LEN] = 563141cc406Sopenharmony_ci {MODE_SELECT6, 0x10, 0, 0, MODEPARAM_LEN, 0}; 564141cc406Sopenharmony_ci mode_select_param *mp; 565141cc406Sopenharmony_ci SANE_Status status; 566141cc406Sopenharmony_ci DBG (11, "<< mode_select_mud "); 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci mp = (mode_select_param *)(cmd + 6); 569141cc406Sopenharmony_ci memset (mp, 0, MODEPARAM_LEN); 570141cc406Sopenharmony_ci mp->page_code = 3; 571141cc406Sopenharmony_ci mp->page_length = 6; 572141cc406Sopenharmony_ci mp->mud[0] = mud >> 8; 573141cc406Sopenharmony_ci mp->mud[1] = mud & 0xFF; 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci DBG (11, ">>\n"); 578141cc406Sopenharmony_ci return (status); 579141cc406Sopenharmony_ci} 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_cistatic SANE_Status 582141cc406Sopenharmony_cimode_select_adf_fsu (int fd, int mode) 583141cc406Sopenharmony_ci{ 584141cc406Sopenharmony_ci static u_char cmd[6 + MODE_SUBDEV_LEN] = 585141cc406Sopenharmony_ci {MODE_SELECT6, 0x10, 0, 0, MODE_SUBDEV_LEN, 0}; 586141cc406Sopenharmony_ci mode_select_subdevice *mp; 587141cc406Sopenharmony_ci SANE_Status status; 588141cc406Sopenharmony_ci DBG (11, "<< mode_select_adf_fsu "); 589141cc406Sopenharmony_ci 590141cc406Sopenharmony_ci mp = (mode_select_subdevice *)(cmd + 6); 591141cc406Sopenharmony_ci memset (mp, 0, MODE_SUBDEV_LEN); 592141cc406Sopenharmony_ci mp->page_code = 0x20; 593141cc406Sopenharmony_ci mp->page_length = 26; 594141cc406Sopenharmony_ci switch (mode) 595141cc406Sopenharmony_ci { 596141cc406Sopenharmony_ci case SCAN_SIMPLE: 597141cc406Sopenharmony_ci mp->a_mode = 0x40; 598141cc406Sopenharmony_ci mp->f_mode = 0x40; 599141cc406Sopenharmony_ci break; 600141cc406Sopenharmony_ci case SCAN_WITH_FSU: 601141cc406Sopenharmony_ci mp->a_mode = 0; 602141cc406Sopenharmony_ci mp->f_mode = 0x40; 603141cc406Sopenharmony_ci break; 604141cc406Sopenharmony_ci case SCAN_WITH_ADF: 605141cc406Sopenharmony_ci mp->a_mode = 0x40; 606141cc406Sopenharmony_ci mp->f_mode = 0; 607141cc406Sopenharmony_ci break; 608141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF 609141cc406Sopenharmony_ci case: SCAN_ADF_FSU_AUTO: 610141cc406Sopenharmony_ci mp->a_mode = 0; 611141cc406Sopenharmony_ci mp->f_mode = 0; 612141cc406Sopenharmony_ci break; 613141cc406Sopenharmony_ci#endif 614141cc406Sopenharmony_ci } 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 617141cc406Sopenharmony_ci 618141cc406Sopenharmony_ci DBG (11, ">>\n"); 619141cc406Sopenharmony_ci return (status); 620141cc406Sopenharmony_ci} 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_cistatic SANE_Status wait_ready(int fd); 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_cistatic SANE_Status 625141cc406Sopenharmony_ciobject_position(int fd, int load) 626141cc406Sopenharmony_ci{ 627141cc406Sopenharmony_ci static u_char cmd[] = {OBJECT_POSITION, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 628141cc406Sopenharmony_ci SANE_Status status; 629141cc406Sopenharmony_ci DBG (11, "<< object_position "); 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci cmd[1] = load; 632141cc406Sopenharmony_ci 633141cc406Sopenharmony_ci wait_ready(fd); 634141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_ci DBG (11, ">>\n"); 637141cc406Sopenharmony_ci return (status); 638141cc406Sopenharmony_ci} 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci#if 0 641141cc406Sopenharmony_cistatic SANE_Status 642141cc406Sopenharmony_cireserve_unit (int fd) 643141cc406Sopenharmony_ci{ 644141cc406Sopenharmony_ci static u_char cmd[] = {RESERVE_UNIT, 0, 0, 0, 0, 0}; 645141cc406Sopenharmony_ci SANE_Status status; 646141cc406Sopenharmony_ci DBG (11, "<< reserve_unit "); 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_ci DBG (11, ">>\n"); 651141cc406Sopenharmony_ci return (status); 652141cc406Sopenharmony_ci} 653141cc406Sopenharmony_ci#endif 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci#if 0 656141cc406Sopenharmony_cistatic SANE_Status 657141cc406Sopenharmony_cirelease_unit (int fd) 658141cc406Sopenharmony_ci{ 659141cc406Sopenharmony_ci static u_char cmd[] = {RELEASE_UNIT, 0, 0, 0, 0, 0}; 660141cc406Sopenharmony_ci SANE_Status status; 661141cc406Sopenharmony_ci DBG (11, "<< release_unit "); 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci DBG (11, ">>\n"); 666141cc406Sopenharmony_ci return (status); 667141cc406Sopenharmony_ci} 668141cc406Sopenharmony_ci#endif 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_cistatic SANE_Status 671141cc406Sopenharmony_cimode_sense (int fd, void *modeparam_buf, size_t * modeparam_size, 672141cc406Sopenharmony_ci int page) 673141cc406Sopenharmony_ci{ 674141cc406Sopenharmony_ci static u_char cmd[6]; 675141cc406Sopenharmony_ci SANE_Status status; 676141cc406Sopenharmony_ci DBG (11, "<< mode_sense "); 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci memset (cmd, 0, sizeof (cmd)); 679141cc406Sopenharmony_ci cmd[0] = 0x1a; 680141cc406Sopenharmony_ci cmd[2] = page; 681141cc406Sopenharmony_ci cmd[4] = *modeparam_size; 682141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), modeparam_buf, 683141cc406Sopenharmony_ci modeparam_size); 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci DBG (11, ">>\n"); 686141cc406Sopenharmony_ci return (status); 687141cc406Sopenharmony_ci} 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_cistatic SANE_Status 690141cc406Sopenharmony_ciscan (int fd) 691141cc406Sopenharmony_ci{ 692141cc406Sopenharmony_ci static u_char cmd[] = {SCAN, 0, 0, 0, 0, 0}; 693141cc406Sopenharmony_ci SANE_Status status; 694141cc406Sopenharmony_ci DBG (11, "<< scan "); 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci DBG (11, ">>\n"); 699141cc406Sopenharmony_ci return (status); 700141cc406Sopenharmony_ci} 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_ci#if 0 703141cc406Sopenharmony_cistatic SANE_Status 704141cc406Sopenharmony_cisend_diagnostics (int fd) 705141cc406Sopenharmony_ci{ 706141cc406Sopenharmony_ci static u_char cmd[] = {SEND_DIAGNOSTIC, 0x04, 0, 0, 0, 0}; 707141cc406Sopenharmony_ci SANE_Status status; 708141cc406Sopenharmony_ci DBG (11, "<< send_diagnostics "); 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci DBG (11, ">>\n"); 713141cc406Sopenharmony_ci return (status); 714141cc406Sopenharmony_ci} 715141cc406Sopenharmony_ci#endif 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_cistatic SANE_Status 718141cc406Sopenharmony_cisend (int fd, SHARP_Send * ss) 719141cc406Sopenharmony_ci{ 720141cc406Sopenharmony_ci static u_char cmd[] = {SEND, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 721141cc406Sopenharmony_ci SANE_Status status; 722141cc406Sopenharmony_ci DBG (11, "<< send "); 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci cmd[2] = ss->dtc; 725141cc406Sopenharmony_ci cmd[4] = ss->dtq >> 8; 726141cc406Sopenharmony_ci cmd[5] = ss->dtq; 727141cc406Sopenharmony_ci cmd[6] = ss->length >> 16; 728141cc406Sopenharmony_ci cmd[7] = ss->length >> 8; 729141cc406Sopenharmony_ci cmd[8] = ss->length >> 0; 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci DBG (11, ">>\n"); 734141cc406Sopenharmony_ci return (status); 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci} 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_cistatic SANE_Status 739141cc406Sopenharmony_ciset_window (int fd, window_param *wp, int len) 740141cc406Sopenharmony_ci{ 741141cc406Sopenharmony_ci static u_char cmd[10 + WINDOW_LEN] = 742141cc406Sopenharmony_ci {SET_WINDOW, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 743141cc406Sopenharmony_ci window_param *winp; 744141cc406Sopenharmony_ci SANE_Status status; 745141cc406Sopenharmony_ci DBG (11, "<< set_window "); 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ci cmd[8] = len; 748141cc406Sopenharmony_ci winp = (window_param *)(cmd + 10); 749141cc406Sopenharmony_ci memset (winp, 0, WINDOW_LEN); 750141cc406Sopenharmony_ci memcpy (winp, wp, len); 751141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); 752141cc406Sopenharmony_ci 753141cc406Sopenharmony_ci DBG (11, ">>\n"); 754141cc406Sopenharmony_ci return (status); 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_ci} 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_cistatic SANE_Status 759141cc406Sopenharmony_ciget_window (int fd, void *buf, size_t * buf_size) 760141cc406Sopenharmony_ci{ 761141cc406Sopenharmony_ci 762141cc406Sopenharmony_ci static u_char cmd[10] = {GET_WINDOW, 0, 0, 0, 0, 0, 0, 0, WINDOW_LEN, 0}; 763141cc406Sopenharmony_ci SANE_Status status; 764141cc406Sopenharmony_ci DBG (11, "<< get_window "); 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci cmd[8] = *buf_size; 767141cc406Sopenharmony_ci status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci DBG (11, ">>\n"); 770141cc406Sopenharmony_ci return (status); 771141cc406Sopenharmony_ci} 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci#ifdef USE_FORK 774141cc406Sopenharmony_ci 775141cc406Sopenharmony_ci/* the following four functions serve simply the purpose 776141cc406Sopenharmony_ci to avoid "over-optimised" code when reader_process and 777141cc406Sopenharmony_ci read_data wait for the buffer to become ready. The simple 778141cc406Sopenharmony_ci while-loops in these functions which check the buffer 779141cc406Sopenharmony_ci status may be optimised so that the machine code only 780141cc406Sopenharmony_ci operates with registers instead of using the variable 781141cc406Sopenharmony_ci values stored in memory. (This is only a workaround - 782141cc406Sopenharmony_ci it would be better to set a compiler pragma, which ensures 783141cc406Sopenharmony_ci that the program looks into the RAM in these while loops -- 784141cc406Sopenharmony_ci but unfortunately I could not find appropriate information 785141cc406Sopenharmony_ci about this at least for gcc, not to speak about other 786141cc406Sopenharmony_ci compilers... 787141cc406Sopenharmony_ci Abel) 788141cc406Sopenharmony_ci*/ 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_cistatic int 791141cc406Sopenharmony_cicancel_requested(SHARP_Scanner *s) 792141cc406Sopenharmony_ci{ 793141cc406Sopenharmony_ci return s->rdr_ctl->cancel; 794141cc406Sopenharmony_ci} 795141cc406Sopenharmony_ci 796141cc406Sopenharmony_cistatic SANE_Status 797141cc406Sopenharmony_cirdr_status(SHARP_Scanner *s) 798141cc406Sopenharmony_ci{ 799141cc406Sopenharmony_ci return s->rdr_ctl->status; 800141cc406Sopenharmony_ci} 801141cc406Sopenharmony_ci 802141cc406Sopenharmony_cistatic int 803141cc406Sopenharmony_cibuf_status(SHARP_shmem_ctl *s) 804141cc406Sopenharmony_ci{ 805141cc406Sopenharmony_ci return s->shm_status; 806141cc406Sopenharmony_ci} 807141cc406Sopenharmony_ci 808141cc406Sopenharmony_cistatic int 809141cc406Sopenharmony_cireader_running(SHARP_Scanner *s) 810141cc406Sopenharmony_ci{ 811141cc406Sopenharmony_ci return s->rdr_ctl->running; 812141cc406Sopenharmony_ci} 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_cistatic int 815141cc406Sopenharmony_cireader_process(SHARP_Scanner *s) 816141cc406Sopenharmony_ci{ 817141cc406Sopenharmony_ci SANE_Status status; 818141cc406Sopenharmony_ci sigset_t sigterm_set; 819141cc406Sopenharmony_ci static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 820141cc406Sopenharmony_ci int full_count = 0, counted; 821141cc406Sopenharmony_ci size_t waitindex, cmdindex; 822141cc406Sopenharmony_ci size_t bytes_to_queue; 823141cc406Sopenharmony_ci size_t nread; 824141cc406Sopenharmony_ci size_t max_bytes_per_read; 825141cc406Sopenharmony_ci int max_queue; 826141cc406Sopenharmony_ci int i, retries = MAX_RETRIES; 827141cc406Sopenharmony_ci SHARP_shmem_ctl *bc; 828141cc406Sopenharmony_ci 829141cc406Sopenharmony_ci s->rdr_ctl->running = 1; 830141cc406Sopenharmony_ci DBG(11, "<< reader_process\n"); 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci sigemptyset (&sigterm_set); 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci bytes_to_queue = s->bytes_to_read; 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci /* it seems that some carriage stops can be avoided with the 837141cc406Sopenharmony_ci JX-250, if the data of an integral number of scan lines is 838141cc406Sopenharmony_ci read with one SCSI command 839141cc406Sopenharmony_ci */ 840141cc406Sopenharmony_ci max_bytes_per_read = s->dev->info.bufsize / s->params.bytes_per_line; 841141cc406Sopenharmony_ci if (max_bytes_per_read) 842141cc406Sopenharmony_ci max_bytes_per_read *= s->params.bytes_per_line; 843141cc406Sopenharmony_ci else 844141cc406Sopenharmony_ci /* this is a really tiny buffer..*/ 845141cc406Sopenharmony_ci max_bytes_per_read = s->dev->info.bufsize; 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci /* wait_ready(s->fd); */ 848141cc406Sopenharmony_ci 849141cc406Sopenharmony_ci if (s->dev->info.queued_reads <= s->dev->info.buffers) 850141cc406Sopenharmony_ci max_queue = s->dev->info.queued_reads; 851141cc406Sopenharmony_ci else 852141cc406Sopenharmony_ci max_queue = s->dev->info.buffers; 853141cc406Sopenharmony_ci if (max_queue <= 0) 854141cc406Sopenharmony_ci max_queue = 1; 855141cc406Sopenharmony_ci for (i = 0; i < max_queue; i++) 856141cc406Sopenharmony_ci { 857141cc406Sopenharmony_ci bc = &s->rdr_ctl->buf_ctl[i]; 858141cc406Sopenharmony_ci if (bytes_to_queue) 859141cc406Sopenharmony_ci { 860141cc406Sopenharmony_ci nread = bytes_to_queue; 861141cc406Sopenharmony_ci if (nread > max_bytes_per_read) 862141cc406Sopenharmony_ci nread = max_bytes_per_read; 863141cc406Sopenharmony_ci bc->used = nread; 864141cc406Sopenharmony_ci cmd[6] = nread >> 16; 865141cc406Sopenharmony_ci cmd[7] = nread >> 8; 866141cc406Sopenharmony_ci cmd[8] = nread; 867141cc406Sopenharmony_ci#ifdef QUEUEDEBUG 868141cc406Sopenharmony_ci DBG(2, "reader: req_enter...\n"); 869141cc406Sopenharmony_ci#endif 870141cc406Sopenharmony_ci status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd), 871141cc406Sopenharmony_ci bc->buffer, 872141cc406Sopenharmony_ci &bc->used, 873141cc406Sopenharmony_ci &bc->qid); 874141cc406Sopenharmony_ci#ifdef QUEUEDEBUG 875141cc406Sopenharmony_ci DBG(2, "reader: req_enter ok\n"); 876141cc406Sopenharmony_ci#endif 877141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 878141cc406Sopenharmony_ci { 879141cc406Sopenharmony_ci DBG(1, "reader_process: read command failed: %s", 880141cc406Sopenharmony_ci sane_strstatus(status)); 881141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 882141cc406Sopenharmony_ci sanei_scsi_req_flush_all_extended(s->fd); 883141cc406Sopenharmony_ci#else 884141cc406Sopenharmony_ci sanei_scsi_req_flush_all(); 885141cc406Sopenharmony_ci#endif 886141cc406Sopenharmony_ci s->rdr_ctl->status = status; 887141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 888141cc406Sopenharmony_ci return 2; 889141cc406Sopenharmony_ci } 890141cc406Sopenharmony_ci bc->shm_status = SHM_BUSY; 891141cc406Sopenharmony_ci bc->nreq = bc->used; 892141cc406Sopenharmony_ci bytes_to_queue -= bc->nreq; 893141cc406Sopenharmony_ci } 894141cc406Sopenharmony_ci else 895141cc406Sopenharmony_ci { 896141cc406Sopenharmony_ci bc->used = 0; 897141cc406Sopenharmony_ci bc->shm_status = SHM_EMPTY; 898141cc406Sopenharmony_ci } 899141cc406Sopenharmony_ci } 900141cc406Sopenharmony_ci waitindex = 0; 901141cc406Sopenharmony_ci cmdindex = i % s->dev->info.buffers; 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci while(s->bytes_to_read > 0) 904141cc406Sopenharmony_ci { 905141cc406Sopenharmony_ci if (cancel_requested(s)) 906141cc406Sopenharmony_ci { 907141cc406Sopenharmony_ci#ifdef QUEUEDEBUG 908141cc406Sopenharmony_ci DBG(2, "reader: flushing requests...\n"); 909141cc406Sopenharmony_ci#endif 910141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 911141cc406Sopenharmony_ci sanei_scsi_req_flush_all_extended(s->fd); 912141cc406Sopenharmony_ci#else 913141cc406Sopenharmony_ci sanei_scsi_req_flush_all(); 914141cc406Sopenharmony_ci#endif 915141cc406Sopenharmony_ci#ifdef QUEUEDEBUG 916141cc406Sopenharmony_ci DBG(2, "reader: flushing requests ok\n"); 917141cc406Sopenharmony_ci#endif 918141cc406Sopenharmony_ci s->rdr_ctl->cancel = 0; 919141cc406Sopenharmony_ci s->rdr_ctl->status = SANE_STATUS_CANCELLED; 920141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 921141cc406Sopenharmony_ci DBG(11, " reader_process (cancelled) >>\n"); 922141cc406Sopenharmony_ci return 1; 923141cc406Sopenharmony_ci } 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci bc = &s->rdr_ctl->buf_ctl[waitindex]; 926141cc406Sopenharmony_ci if (bc->shm_status == SHM_BUSY) 927141cc406Sopenharmony_ci { 928141cc406Sopenharmony_ci#ifdef DEBUG 929141cc406Sopenharmony_ci { 930141cc406Sopenharmony_ci struct timeval t; 931141cc406Sopenharmony_ci gettimeofday(&t, 0); 932141cc406Sopenharmony_ci DBG(2, "rd: waiting for data %li.%06li\n", t.tv_sec, t.tv_usec); 933141cc406Sopenharmony_ci } 934141cc406Sopenharmony_ci#endif 935141cc406Sopenharmony_ci#ifdef QUEUEDEBUG 936141cc406Sopenharmony_ci DBG(2, "reader: req_wait...\n"); 937141cc406Sopenharmony_ci#endif 938141cc406Sopenharmony_ci status = sanei_scsi_req_wait(bc->qid); 939141cc406Sopenharmony_ci#ifdef QUEUEDEBUG 940141cc406Sopenharmony_ci DBG(2, "reader: req_wait ok\n"); 941141cc406Sopenharmony_ci#endif 942141cc406Sopenharmony_ci#ifdef DEBUG 943141cc406Sopenharmony_ci { 944141cc406Sopenharmony_ci struct timeval t; 945141cc406Sopenharmony_ci gettimeofday(&t, 0); 946141cc406Sopenharmony_ci DBG(2, "rd: data received %li.%06li\n", t.tv_sec, t.tv_usec); 947141cc406Sopenharmony_ci } 948141cc406Sopenharmony_ci#endif 949141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY && retries) 950141cc406Sopenharmony_ci { 951141cc406Sopenharmony_ci bc->used = 0; 952141cc406Sopenharmony_ci retries--; 953141cc406Sopenharmony_ci DBG(11, "reader: READ command returned BUSY\n"); 954141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 955141cc406Sopenharmony_ci usleep(10000); 956141cc406Sopenharmony_ci } 957141cc406Sopenharmony_ci else if (status != SANE_STATUS_GOOD) 958141cc406Sopenharmony_ci { 959141cc406Sopenharmony_ci DBG(1, "reader_process: read command failed: %s\n", 960141cc406Sopenharmony_ci sane_strstatus(status)); 961141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 962141cc406Sopenharmony_ci sanei_scsi_req_flush_all_extended(s->fd); 963141cc406Sopenharmony_ci#else 964141cc406Sopenharmony_ci sanei_scsi_req_flush_all(); 965141cc406Sopenharmony_ci#endif 966141cc406Sopenharmony_ci s->rdr_ctl->status = status; 967141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 968141cc406Sopenharmony_ci return 2; 969141cc406Sopenharmony_ci } 970141cc406Sopenharmony_ci else 971141cc406Sopenharmony_ci { 972141cc406Sopenharmony_ci retries = MAX_RETRIES; 973141cc406Sopenharmony_ci } 974141cc406Sopenharmony_ci#if 1 975141cc406Sopenharmony_ci s->bytes_to_read -= bc->used; 976141cc406Sopenharmony_ci bytes_to_queue += bc->nreq - bc->used; 977141cc406Sopenharmony_ci#else 978141cc406Sopenharmony_ci /* xxxxxxxxxxxxxxxxxxx TEST xxxxxxxxxxxxxxx */ 979141cc406Sopenharmony_ci s->bytes_to_read -= bc->nreq; 980141cc406Sopenharmony_ci /* memset(bc->buffer + bc->used, 0, bc->nreq - bc->used); */ 981141cc406Sopenharmony_ci bc->used = bc->nreq; 982141cc406Sopenharmony_ci /* bytes_to_queue += bc->nreq - bc->used; */ 983141cc406Sopenharmony_ci DBG(1, "btr: %i btq: %i nreq: %i nrcv: %i\n", 984141cc406Sopenharmony_ci s->bytes_to_read, bytes_to_queue, bc->nreq, bc->used); 985141cc406Sopenharmony_ci#endif 986141cc406Sopenharmony_ci bc->start = 0; 987141cc406Sopenharmony_ci bc->shm_status = SHM_FULL; 988141cc406Sopenharmony_ci 989141cc406Sopenharmony_ci waitindex++; 990141cc406Sopenharmony_ci if (waitindex == s->dev->info.buffers) 991141cc406Sopenharmony_ci waitindex = 0; 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci } 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_ci if (bytes_to_queue) 996141cc406Sopenharmony_ci { 997141cc406Sopenharmony_ci /* wait until the next buffer is completely read via read_data */ 998141cc406Sopenharmony_ci bc = &s->rdr_ctl->buf_ctl[cmdindex]; 999141cc406Sopenharmony_ci counted = 0; 1000141cc406Sopenharmony_ci while (buf_status(bc) != SHM_EMPTY) 1001141cc406Sopenharmony_ci { 1002141cc406Sopenharmony_ci if (!counted) 1003141cc406Sopenharmony_ci { 1004141cc406Sopenharmony_ci counted = 1; 1005141cc406Sopenharmony_ci full_count++; 1006141cc406Sopenharmony_ci } 1007141cc406Sopenharmony_ci if (cancel_requested(s)) 1008141cc406Sopenharmony_ci { 1009141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 1010141cc406Sopenharmony_ci sanei_scsi_req_flush_all_extended(s->fd); 1011141cc406Sopenharmony_ci#else 1012141cc406Sopenharmony_ci sanei_scsi_req_flush_all(); 1013141cc406Sopenharmony_ci#endif 1014141cc406Sopenharmony_ci s->rdr_ctl->cancel = 0; 1015141cc406Sopenharmony_ci s->rdr_ctl->status = SANE_STATUS_CANCELLED; 1016141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 1017141cc406Sopenharmony_ci DBG(11, " reader_process (cancelled) >>\n"); 1018141cc406Sopenharmony_ci return 1; 1019141cc406Sopenharmony_ci } 1020141cc406Sopenharmony_ci } 1021141cc406Sopenharmony_ci 1022141cc406Sopenharmony_ci nread = bytes_to_queue; 1023141cc406Sopenharmony_ci if (nread > max_bytes_per_read) 1024141cc406Sopenharmony_ci nread = max_bytes_per_read; 1025141cc406Sopenharmony_ci bc->used = nread; 1026141cc406Sopenharmony_ci cmd[6] = nread >> 16; 1027141cc406Sopenharmony_ci cmd[7] = nread >> 8; 1028141cc406Sopenharmony_ci cmd[8] = nread; 1029141cc406Sopenharmony_ci status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd), 1030141cc406Sopenharmony_ci bc->buffer, &bc->used, &bc->qid); 1031141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1032141cc406Sopenharmony_ci { 1033141cc406Sopenharmony_ci DBG(1, "reader_process: read command failed: %s", 1034141cc406Sopenharmony_ci sane_strstatus(status)); 1035141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 1036141cc406Sopenharmony_ci sanei_scsi_req_flush_all_extended(s->fd); 1037141cc406Sopenharmony_ci#else 1038141cc406Sopenharmony_ci sanei_scsi_req_flush_all(); 1039141cc406Sopenharmony_ci#endif 1040141cc406Sopenharmony_ci s->rdr_ctl->status = status; 1041141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 1042141cc406Sopenharmony_ci return 2; 1043141cc406Sopenharmony_ci } 1044141cc406Sopenharmony_ci bc->shm_status = SHM_BUSY; 1045141cc406Sopenharmony_ci bc->nreq = nread; 1046141cc406Sopenharmony_ci bytes_to_queue -= nread; 1047141cc406Sopenharmony_ci 1048141cc406Sopenharmony_ci cmdindex++; 1049141cc406Sopenharmony_ci if (cmdindex == s->dev->info.buffers) 1050141cc406Sopenharmony_ci cmdindex = 0; 1051141cc406Sopenharmony_ci } 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci if (cancel_requested(s)) 1054141cc406Sopenharmony_ci { 1055141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 1056141cc406Sopenharmony_ci sanei_scsi_req_flush_all_extended(s->fd); 1057141cc406Sopenharmony_ci#else 1058141cc406Sopenharmony_ci sanei_scsi_req_flush_all(); 1059141cc406Sopenharmony_ci#endif 1060141cc406Sopenharmony_ci s->rdr_ctl->cancel = 0; 1061141cc406Sopenharmony_ci s->rdr_ctl->status = SANE_STATUS_CANCELLED; 1062141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 1063141cc406Sopenharmony_ci DBG(11, " reader_process (cancelled) >>\n"); 1064141cc406Sopenharmony_ci return 1; 1065141cc406Sopenharmony_ci } 1066141cc406Sopenharmony_ci } 1067141cc406Sopenharmony_ci 1068141cc406Sopenharmony_ci DBG(1, "buffer full conditions: %i\n", full_count); 1069141cc406Sopenharmony_ci DBG(11, " reader_process>>\n"); 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 1072141cc406Sopenharmony_ci return 0; 1073141cc406Sopenharmony_ci} 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_cistatic SANE_Status 1076141cc406Sopenharmony_ciread_data (SHARP_Scanner *s, SANE_Byte *buf, size_t * buf_size) 1077141cc406Sopenharmony_ci{ 1078141cc406Sopenharmony_ci size_t copysize, copied = 0; 1079141cc406Sopenharmony_ci SHARP_shmem_ctl *bc; 1080141cc406Sopenharmony_ci 1081141cc406Sopenharmony_ci DBG(11, "<< read_data "); 1082141cc406Sopenharmony_ci 1083141cc406Sopenharmony_ci bc = &s->rdr_ctl->buf_ctl[s->read_buff]; 1084141cc406Sopenharmony_ci 1085141cc406Sopenharmony_ci while (copied < *buf_size) 1086141cc406Sopenharmony_ci { 1087141cc406Sopenharmony_ci /* wait until the reader process delivers data or a scanner error occurs: */ 1088141cc406Sopenharmony_ci while ( buf_status(bc) != SHM_FULL 1089141cc406Sopenharmony_ci && rdr_status(s) == SANE_STATUS_GOOD) 1090141cc406Sopenharmony_ci { 1091141cc406Sopenharmony_ci usleep(10); /* could perhaps be longer. make this user configurable?? */ 1092141cc406Sopenharmony_ci } 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci if (rdr_status(s) != SANE_STATUS_GOOD) 1095141cc406Sopenharmony_ci { 1096141cc406Sopenharmony_ci return rdr_status(s); 1097141cc406Sopenharmony_ci DBG(11, ">>\n"); 1098141cc406Sopenharmony_ci } 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci copysize = bc->used - bc->start; 1101141cc406Sopenharmony_ci 1102141cc406Sopenharmony_ci if (copysize > *buf_size - copied ) 1103141cc406Sopenharmony_ci copysize = *buf_size - copied; 1104141cc406Sopenharmony_ci 1105141cc406Sopenharmony_ci memcpy(buf, &(bc->buffer[bc->start]), copysize); 1106141cc406Sopenharmony_ci 1107141cc406Sopenharmony_ci copied += copysize; 1108141cc406Sopenharmony_ci buf = &buf[copysize]; 1109141cc406Sopenharmony_ci 1110141cc406Sopenharmony_ci bc->start += copysize; 1111141cc406Sopenharmony_ci if (bc->start >= bc->used) 1112141cc406Sopenharmony_ci { 1113141cc406Sopenharmony_ci bc->start = 0; 1114141cc406Sopenharmony_ci bc->shm_status = SHM_EMPTY; 1115141cc406Sopenharmony_ci s->read_buff++; 1116141cc406Sopenharmony_ci if (s->read_buff == s->dev->info.buffers) 1117141cc406Sopenharmony_ci s->read_buff = 0; 1118141cc406Sopenharmony_ci bc = &s->rdr_ctl->buf_ctl[s->read_buff]; 1119141cc406Sopenharmony_ci } 1120141cc406Sopenharmony_ci } 1121141cc406Sopenharmony_ci 1122141cc406Sopenharmony_ci DBG(11, ">>\n"); 1123141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1124141cc406Sopenharmony_ci} 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci#else /* don't USE_FORK: */ 1127141cc406Sopenharmony_ci 1128141cc406Sopenharmony_cistatic SANE_Status 1129141cc406Sopenharmony_ciread_data (SHARP_Scanner *s, SANE_Byte *buf, size_t * buf_size) 1130141cc406Sopenharmony_ci{ 1131141cc406Sopenharmony_ci static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 1132141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1133141cc406Sopenharmony_ci size_t remain = *buf_size; 1134141cc406Sopenharmony_ci size_t nread; 1135141cc406Sopenharmony_ci int retries = MAX_RETRIES; 1136141cc406Sopenharmony_ci DBG (11, "<< read_data "); 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci /* sane_read_shuffled requires that read_data returns 1139141cc406Sopenharmony_ci exactly *buf_size bytes, so it must be guaranteed here. 1140141cc406Sopenharmony_ci Further make sure that not more bytes are read in than 1141141cc406Sopenharmony_ci sanei_scsi_max_request_size allows, to avoid a failure 1142141cc406Sopenharmony_ci of the read command 1143141cc406Sopenharmony_ci */ 1144141cc406Sopenharmony_ci while (remain > 0) 1145141cc406Sopenharmony_ci { 1146141cc406Sopenharmony_ci nread = remain; 1147141cc406Sopenharmony_ci if (nread > s->dev->info.bufsize) 1148141cc406Sopenharmony_ci nread = s->dev->info.bufsize; 1149141cc406Sopenharmony_ci cmd[6] = nread >> 16; 1150141cc406Sopenharmony_ci cmd[7] = nread >> 8; 1151141cc406Sopenharmony_ci cmd[8] = nread; 1152141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 1153141cc406Sopenharmony_ci &buf[*buf_size - remain], &nread); 1154141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY && retries) 1155141cc406Sopenharmony_ci { 1156141cc406Sopenharmony_ci retries--; 1157141cc406Sopenharmony_ci nread = 0; 1158141cc406Sopenharmony_ci usleep(10000); 1159141cc406Sopenharmony_ci } 1160141cc406Sopenharmony_ci else if (status != SANE_STATUS_GOOD) 1161141cc406Sopenharmony_ci { 1162141cc406Sopenharmony_ci DBG(11, ">>\n"); 1163141cc406Sopenharmony_ci return(status); 1164141cc406Sopenharmony_ci } 1165141cc406Sopenharmony_ci else 1166141cc406Sopenharmony_ci { 1167141cc406Sopenharmony_ci retries = MAX_RETRIES; 1168141cc406Sopenharmony_ci } 1169141cc406Sopenharmony_ci remain -= nread; 1170141cc406Sopenharmony_ci } 1171141cc406Sopenharmony_ci DBG (11, ">>\n"); 1172141cc406Sopenharmony_ci return (status); 1173141cc406Sopenharmony_ci} 1174141cc406Sopenharmony_ci#endif 1175141cc406Sopenharmony_ci 1176141cc406Sopenharmony_cistatic size_t 1177141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 1178141cc406Sopenharmony_ci{ 1179141cc406Sopenharmony_ci size_t size, max_size = 0; 1180141cc406Sopenharmony_ci int i; 1181141cc406Sopenharmony_ci DBG (10, "<< max_string_size "); 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 1184141cc406Sopenharmony_ci { 1185141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 1186141cc406Sopenharmony_ci if (size > max_size) 1187141cc406Sopenharmony_ci max_size = size; 1188141cc406Sopenharmony_ci } 1189141cc406Sopenharmony_ci 1190141cc406Sopenharmony_ci DBG (10, ">>\n"); 1191141cc406Sopenharmony_ci return max_size; 1192141cc406Sopenharmony_ci} 1193141cc406Sopenharmony_ci 1194141cc406Sopenharmony_cistatic SANE_Status 1195141cc406Sopenharmony_ciwait_ready(int fd) 1196141cc406Sopenharmony_ci{ 1197141cc406Sopenharmony_ci SANE_Status status; 1198141cc406Sopenharmony_ci int retry = 0; 1199141cc406Sopenharmony_ci 1200141cc406Sopenharmony_ci while ((status = test_unit_ready (fd)) != SANE_STATUS_GOOD) 1201141cc406Sopenharmony_ci { 1202141cc406Sopenharmony_ci DBG (5, "wait_ready failed (%d)\n", retry); 1203141cc406Sopenharmony_ci if (retry++ > 15){ 1204141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1205141cc406Sopenharmony_ci } 1206141cc406Sopenharmony_ci sleep(3); 1207141cc406Sopenharmony_ci } 1208141cc406Sopenharmony_ci return (status); 1209141cc406Sopenharmony_ci 1210141cc406Sopenharmony_ci} 1211141cc406Sopenharmony_ci 1212141cc406Sopenharmony_ci/* ask the scanner for the maximum scan sizes with/without ADF and 1213141cc406Sopenharmony_ci FSU. The JX330 manual does mention the sizes. 1214141cc406Sopenharmony_ci*/ 1215141cc406Sopenharmony_cistatic SANE_Status 1216141cc406Sopenharmony_ciget_max_scan_size(int fd, SHARP_Device *dev, int mode) 1217141cc406Sopenharmony_ci{ 1218141cc406Sopenharmony_ci SANE_Status status; 1219141cc406Sopenharmony_ci mode_sense_subdevice m_subdev; 1220141cc406Sopenharmony_ci size_t buf_size; 1221141cc406Sopenharmony_ci 1222141cc406Sopenharmony_ci status = mode_select_adf_fsu(fd, mode); 1223141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1224141cc406Sopenharmony_ci { 1225141cc406Sopenharmony_ci DBG (1, "get_scan_sizes: MODE_SELECT/subdevice page failed\n"); 1226141cc406Sopenharmony_ci sanei_scsi_close (fd); 1227141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1228141cc406Sopenharmony_ci } 1229141cc406Sopenharmony_ci 1230141cc406Sopenharmony_ci DBG (3, "get_scan_sizes: sending MODE SENSE/subdevice page\n"); 1231141cc406Sopenharmony_ci memset (&m_subdev, 0, sizeof (m_subdev)); 1232141cc406Sopenharmony_ci buf_size = sizeof (m_subdev); 1233141cc406Sopenharmony_ci status = mode_sense (fd, &m_subdev, &buf_size, 0x20); 1234141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1235141cc406Sopenharmony_ci { 1236141cc406Sopenharmony_ci DBG (1, "get_scan_sizes: MODE_SENSE/subdevice page failed\n"); 1237141cc406Sopenharmony_ci sanei_scsi_close (fd); 1238141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1239141cc406Sopenharmony_ci } 1240141cc406Sopenharmony_ci 1241141cc406Sopenharmony_ci dev->info.tl_x_ranges[mode].min = 0; 1242141cc406Sopenharmony_ci dev->info.tl_x_ranges[mode].max = SANE_FIX(PIX_TO_MM( 1243141cc406Sopenharmony_ci (m_subdev.max_x[0] << 24) + (m_subdev.max_x[1] << 16) + 1244141cc406Sopenharmony_ci (m_subdev.max_x[2] << 8) + m_subdev.max_x[3] - 1, dev->info.mud)); 1245141cc406Sopenharmony_ci dev->info.tl_x_ranges[mode].quant = 0; 1246141cc406Sopenharmony_ci 1247141cc406Sopenharmony_ci dev->info.br_x_ranges[mode].min = SANE_FIX(PIX_TO_MM(1, dev->info.mud)); 1248141cc406Sopenharmony_ci dev->info.br_x_ranges[mode].max = SANE_FIX(PIX_TO_MM( 1249141cc406Sopenharmony_ci (m_subdev.max_x[0] << 24) + (m_subdev.max_x[1] << 16) + 1250141cc406Sopenharmony_ci (m_subdev.max_x[2] << 8) + m_subdev.max_x[3], dev->info.mud)); 1251141cc406Sopenharmony_ci dev->info.br_x_ranges[mode].quant = 0; 1252141cc406Sopenharmony_ci 1253141cc406Sopenharmony_ci dev->info.tl_y_ranges[mode].min = 0; 1254141cc406Sopenharmony_ci if ((dev->sensedat.model != JX250 && dev->sensedat.model != JX350) || 1255141cc406Sopenharmony_ci mode != SCAN_WITH_FSU) 1256141cc406Sopenharmony_ci dev->info.tl_y_ranges[mode].max = SANE_FIX(PIX_TO_MM( 1257141cc406Sopenharmony_ci (m_subdev.max_y[0] << 24) + (m_subdev.max_y[1] << 16) + 1258141cc406Sopenharmony_ci (m_subdev.max_y[2] << 8) + m_subdev.max_y[3] - 1, dev->info.mud)); 1259141cc406Sopenharmony_ci else 1260141cc406Sopenharmony_ci /* The manual for the JX250 states on page 62 that the maximum 1261141cc406Sopenharmony_ci value for tl_y in FSU mode is 13199, while the max value for 1262141cc406Sopenharmony_ci br_y is 13900, which is (probably -- I don't have a FSU) returned 1263141cc406Sopenharmony_ci by mode sense/subdevice page. Therefore, we cannot simply 1264141cc406Sopenharmony_ci decrement that value and store it as max(tl_y). 1265141cc406Sopenharmony_ci */ 1266141cc406Sopenharmony_ci dev->info.tl_y_ranges[mode].max = 13199; 1267141cc406Sopenharmony_ci dev->info.tl_y_ranges[mode].quant = 0; 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_ci dev->info.br_y_ranges[mode].min = SANE_FIX(PIX_TO_MM(1, dev->info.mud)); 1270141cc406Sopenharmony_ci dev->info.br_y_ranges[mode].max = SANE_FIX(PIX_TO_MM( 1271141cc406Sopenharmony_ci (m_subdev.max_y[0] << 24) + (m_subdev.max_y[1] << 16) + 1272141cc406Sopenharmony_ci (m_subdev.max_y[2] << 8) + m_subdev.max_y[3], dev->info.mud)); 1273141cc406Sopenharmony_ci dev->info.br_y_ranges[mode].quant = 0; 1274141cc406Sopenharmony_ci 1275141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1276141cc406Sopenharmony_ci} 1277141cc406Sopenharmony_ci 1278141cc406Sopenharmony_cistatic SANE_Status 1279141cc406Sopenharmony_ciattach (const char *devnam, SHARP_Device ** devp) 1280141cc406Sopenharmony_ci{ 1281141cc406Sopenharmony_ci SANE_Status status; 1282141cc406Sopenharmony_ci SHARP_Device *dev; 1283141cc406Sopenharmony_ci SHARP_Sense_Data sensedat; 1284141cc406Sopenharmony_ci 1285141cc406Sopenharmony_ci int fd; 1286141cc406Sopenharmony_ci char inquiry_data[INQUIRY_LEN]; 1287141cc406Sopenharmony_ci const char *model_name; 1288141cc406Sopenharmony_ci mode_sense_param msp; 1289141cc406Sopenharmony_ci mode_sense_subdevice m_subdev; 1290141cc406Sopenharmony_ci size_t buf_size; 1291141cc406Sopenharmony_ci DBG (10, "<< attach "); 1292141cc406Sopenharmony_ci 1293141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1294141cc406Sopenharmony_ci { 1295141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devnam) == 0) 1296141cc406Sopenharmony_ci { 1297141cc406Sopenharmony_ci if (devp) 1298141cc406Sopenharmony_ci *devp = dev; 1299141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1300141cc406Sopenharmony_ci } 1301141cc406Sopenharmony_ci } 1302141cc406Sopenharmony_ci 1303141cc406Sopenharmony_ci sensedat.model = unknown; 1304141cc406Sopenharmony_ci sensedat.complain_on_errors = 0; 1305141cc406Sopenharmony_ci DBG (3, "attach: opening %s\n", devnam); 1306141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 1307141cc406Sopenharmony_ci { 1308141cc406Sopenharmony_ci int bufsize = 4096; 1309141cc406Sopenharmony_ci status = sanei_scsi_open_extended (devnam, &fd, &sense_handler, &sensedat, &bufsize); 1310141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1311141cc406Sopenharmony_ci { 1312141cc406Sopenharmony_ci DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); 1313141cc406Sopenharmony_ci return (status); 1314141cc406Sopenharmony_ci } 1315141cc406Sopenharmony_ci if (bufsize < 4096) 1316141cc406Sopenharmony_ci { 1317141cc406Sopenharmony_ci DBG(1, "attach: open failed. no memory\n"); 1318141cc406Sopenharmony_ci sanei_scsi_close(fd); 1319141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1320141cc406Sopenharmony_ci } 1321141cc406Sopenharmony_ci } 1322141cc406Sopenharmony_ci#else 1323141cc406Sopenharmony_ci status = sanei_scsi_open (devnam, &fd, &sense_handler, &sensedat); 1324141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1325141cc406Sopenharmony_ci { 1326141cc406Sopenharmony_ci DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); 1327141cc406Sopenharmony_ci return (status); 1328141cc406Sopenharmony_ci } 1329141cc406Sopenharmony_ci#endif 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci DBG (3, "attach: sending INQUIRY\n"); 1332141cc406Sopenharmony_ci memset (inquiry_data, 0, sizeof (inquiry_data)); 1333141cc406Sopenharmony_ci buf_size = sizeof (inquiry_data); 1334141cc406Sopenharmony_ci status = inquiry (fd, inquiry_data, &buf_size); 1335141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1336141cc406Sopenharmony_ci { 1337141cc406Sopenharmony_ci DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); 1338141cc406Sopenharmony_ci sanei_scsi_close (fd); 1339141cc406Sopenharmony_ci return (status); 1340141cc406Sopenharmony_ci } 1341141cc406Sopenharmony_ci 1342141cc406Sopenharmony_ci if (inquiry_data[0] == 6 && strncmp (inquiry_data + 8, "SHARP", 5) == 0) 1343141cc406Sopenharmony_ci { 1344141cc406Sopenharmony_ci if (strncmp (inquiry_data + 16, "JX610", 5) == 0) 1345141cc406Sopenharmony_ci sensedat.model = JX610; 1346141cc406Sopenharmony_ci else if (strncmp (inquiry_data + 16, "JX250", 5) == 0) 1347141cc406Sopenharmony_ci sensedat.model = JX250; 1348141cc406Sopenharmony_ci else if (strncmp (inquiry_data + 16, "JX350", 5) == 0) 1349141cc406Sopenharmony_ci sensedat.model = JX350; 1350141cc406Sopenharmony_ci else if ( strncmp (inquiry_data + 16, "JX320", 5) == 0 1351141cc406Sopenharmony_ci || strncmp (inquiry_data + 16, "JX325", 5) == 0) 1352141cc406Sopenharmony_ci sensedat.model = JX320; 1353141cc406Sopenharmony_ci else if (strncmp (inquiry_data + 16, "JX330", 5) == 0) 1354141cc406Sopenharmony_ci sensedat.model = JX330; 1355141cc406Sopenharmony_ci } 1356141cc406Sopenharmony_ci 1357141cc406Sopenharmony_ci if (sensedat.model == unknown) 1358141cc406Sopenharmony_ci { 1359141cc406Sopenharmony_ci DBG (1, "attach: device doesn't look like a Sharp scanner\n"); 1360141cc406Sopenharmony_ci sanei_scsi_close (fd); 1361141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1362141cc406Sopenharmony_ci } 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci DBG (3, "attach: sending TEST_UNIT_READY\n"); 1365141cc406Sopenharmony_ci status = test_unit_ready (fd); 1366141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1367141cc406Sopenharmony_ci { 1368141cc406Sopenharmony_ci DBG (1, "attach: test unit ready failed (%s)\n", 1369141cc406Sopenharmony_ci sane_strstatus (status)); 1370141cc406Sopenharmony_ci sanei_scsi_close (fd); 1371141cc406Sopenharmony_ci return (status); 1372141cc406Sopenharmony_ci } 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_ci DBG (3, "attach: sending MODE SELECT\n"); 1375141cc406Sopenharmony_ci /* JX-610 probably supports only 25 MUD size 1376141cc406Sopenharmony_ci JX-320 only supports 25 MUD size 1377141cc406Sopenharmony_ci */ 1378141cc406Sopenharmony_ci if (strncmp (inquiry_data + 16, "JX610", 5) == 0) 1379141cc406Sopenharmony_ci status = mode_select_mud (fd, DEFAULT_MUD_JX610); 1380141cc406Sopenharmony_ci else if (strncmp (inquiry_data + 16, "JX320", 5) == 0) 1381141cc406Sopenharmony_ci status = mode_select_mud (fd, DEFAULT_MUD_JX320); 1382141cc406Sopenharmony_ci else 1383141cc406Sopenharmony_ci status = mode_select_mud (fd, DEFAULT_MUD_JX330); 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1386141cc406Sopenharmony_ci { 1387141cc406Sopenharmony_ci DBG (1, "attach: MODE_SELECT6 failed\n"); 1388141cc406Sopenharmony_ci sanei_scsi_close (fd); 1389141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1390141cc406Sopenharmony_ci } 1391141cc406Sopenharmony_ci 1392141cc406Sopenharmony_ci DBG (3, "attach: sending MODE SENSE/MUP page\n"); 1393141cc406Sopenharmony_ci memset (&msp, 0, sizeof (msp)); 1394141cc406Sopenharmony_ci buf_size = sizeof (msp); 1395141cc406Sopenharmony_ci status = mode_sense (fd, &msp, &buf_size, 3); 1396141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1397141cc406Sopenharmony_ci { 1398141cc406Sopenharmony_ci DBG (1, "attach: MODE_SENSE/MUP page failed\n"); 1399141cc406Sopenharmony_ci sanei_scsi_close (fd); 1400141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1401141cc406Sopenharmony_ci } 1402141cc406Sopenharmony_ci 1403141cc406Sopenharmony_ci dev = malloc (sizeof (*dev)); 1404141cc406Sopenharmony_ci if (!dev) 1405141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 1406141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 1407141cc406Sopenharmony_ci 1408141cc406Sopenharmony_ci dev->sane.name = strdup (devnam); 1409141cc406Sopenharmony_ci dev->sane.vendor = "SHARP"; 1410141cc406Sopenharmony_ci model_name = (char*) inquiry_data + 16; 1411141cc406Sopenharmony_ci dev->sane.model = strndup (model_name, 10); 1412141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 1413141cc406Sopenharmony_ci 1414141cc406Sopenharmony_ci dev->sensedat.model = sensedat.model; 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci DBG (5, "dev->sane.name = %s\n", dev->sane.name); 1417141cc406Sopenharmony_ci DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor); 1418141cc406Sopenharmony_ci DBG (5, "dev->sane.model = %s\n", dev->sane.model); 1419141cc406Sopenharmony_ci DBG (5, "dev->sane.type = %s\n", dev->sane.type); 1420141cc406Sopenharmony_ci 1421141cc406Sopenharmony_ci dev->info.xres_range.quant = 0; 1422141cc406Sopenharmony_ci dev->info.yres_range.quant = 0; 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_ci dev->info.tl_x_ranges[SCAN_SIMPLE].min = SANE_FIX(0); 1425141cc406Sopenharmony_ci dev->info.br_x_ranges[SCAN_SIMPLE].min = SANE_FIX(1); 1426141cc406Sopenharmony_ci dev->info.tl_y_ranges[SCAN_SIMPLE].min = SANE_FIX(0); 1427141cc406Sopenharmony_ci dev->info.br_y_ranges[SCAN_SIMPLE].min = SANE_FIX(1); 1428141cc406Sopenharmony_ci dev->info.tl_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); 1429141cc406Sopenharmony_ci dev->info.br_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); 1430141cc406Sopenharmony_ci dev->info.tl_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); 1431141cc406Sopenharmony_ci dev->info.br_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); 1432141cc406Sopenharmony_ci 1433141cc406Sopenharmony_ci dev->info.xres_default = 150; 1434141cc406Sopenharmony_ci dev->info.yres_default = 150; 1435141cc406Sopenharmony_ci dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(209); 1436141cc406Sopenharmony_ci dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210); 1437141cc406Sopenharmony_ci dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(296); 1438141cc406Sopenharmony_ci dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297); 1439141cc406Sopenharmony_ci 1440141cc406Sopenharmony_ci dev->info.bmu = msp.bmu; 1441141cc406Sopenharmony_ci dev->info.mud = (msp.mud[0] << 8) + msp.mud[1]; 1442141cc406Sopenharmony_ci 1443141cc406Sopenharmony_ci dev->info.adf_fsu_installed = 0; 1444141cc406Sopenharmony_ci if (dev->sensedat.model == JX610) 1445141cc406Sopenharmony_ci { 1446141cc406Sopenharmony_ci dev->info.xres_range.max = 600; 1447141cc406Sopenharmony_ci dev->info.xres_range.min = 30; 1448141cc406Sopenharmony_ci 1449141cc406Sopenharmony_ci dev->info.yres_range.max = 600; 1450141cc406Sopenharmony_ci dev->info.yres_range.min = 30; 1451141cc406Sopenharmony_ci dev->info.x_default = SANE_FIX(210); 1452141cc406Sopenharmony_ci dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(303); /* 304.8mm is the real max */ 1453141cc406Sopenharmony_ci dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(304); /* 304.8mm is the real max */ 1454141cc406Sopenharmony_ci 1455141cc406Sopenharmony_ci dev->info.y_default = SANE_FIX(297); 1456141cc406Sopenharmony_ci dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(430); /* 431.8 is the real max */ 1457141cc406Sopenharmony_ci dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(431); /* 431.8 is the real max */ 1458141cc406Sopenharmony_ci } 1459141cc406Sopenharmony_ci else if (dev->sensedat.model == JX320) 1460141cc406Sopenharmony_ci { 1461141cc406Sopenharmony_ci dev->info.xres_range.max = 600; 1462141cc406Sopenharmony_ci dev->info.xres_range.min = 30; 1463141cc406Sopenharmony_ci 1464141cc406Sopenharmony_ci dev->info.yres_range.max = 600; 1465141cc406Sopenharmony_ci dev->info.yres_range.min = 30; 1466141cc406Sopenharmony_ci dev->info.x_default = SANE_FIX(210); 1467141cc406Sopenharmony_ci dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(212); 1468141cc406Sopenharmony_ci dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(213); 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci dev->info.y_default = SANE_FIX(297); 1471141cc406Sopenharmony_ci dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(292); 1472141cc406Sopenharmony_ci dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(293); 1473141cc406Sopenharmony_ci } 1474141cc406Sopenharmony_ci else 1475141cc406Sopenharmony_ci { 1476141cc406Sopenharmony_ci /* ask the scanner, if ADF or FSU are installed, and ask for 1477141cc406Sopenharmony_ci the maximum scan sizes with/without ADF and FSU. 1478141cc406Sopenharmony_ci */ 1479141cc406Sopenharmony_ci 1480141cc406Sopenharmony_ci DBG (3, "attach: sending MODE SENSE/subdevice page\n"); 1481141cc406Sopenharmony_ci memset (&m_subdev, 0, sizeof (m_subdev)); 1482141cc406Sopenharmony_ci buf_size = sizeof (m_subdev); 1483141cc406Sopenharmony_ci status = mode_sense (fd, &m_subdev, &buf_size, 0x20); 1484141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1485141cc406Sopenharmony_ci { 1486141cc406Sopenharmony_ci DBG (1, "attach: MODE_SENSE/subdevice page failed\n"); 1487141cc406Sopenharmony_ci sanei_scsi_close (fd); 1488141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 1489141cc406Sopenharmony_ci } 1490141cc406Sopenharmony_ci 1491141cc406Sopenharmony_ci /* The JX330 manual is not very clear about the ADF- und FSU-Bits 1492141cc406Sopenharmony_ci returned by a JX320 and JX325 for the mode sense command: 1493141cc406Sopenharmony_ci Are these bits set to zero or not? To be on the safe side, let's 1494141cc406Sopenharmony_ci clear them. 1495141cc406Sopenharmony_ci */ 1496141cc406Sopenharmony_ci 1497141cc406Sopenharmony_ci if ( strncmp(inquiry_data + 16, "JX320", 5) == 0 1498141cc406Sopenharmony_ci || strncmp(inquiry_data + 16, "JX325", 5) == 0) 1499141cc406Sopenharmony_ci { 1500141cc406Sopenharmony_ci m_subdev.f_mode_type = 0; 1501141cc406Sopenharmony_ci m_subdev.a_mode_type = 0; 1502141cc406Sopenharmony_ci } 1503141cc406Sopenharmony_ci 1504141cc406Sopenharmony_ci get_max_scan_size(fd, dev, SCAN_SIMPLE); 1505141cc406Sopenharmony_ci 1506141cc406Sopenharmony_ci if (m_subdev.a_mode_type & 0x03) 1507141cc406Sopenharmony_ci { 1508141cc406Sopenharmony_ci dev->info.adf_fsu_installed = HAVE_ADF; 1509141cc406Sopenharmony_ci get_max_scan_size(fd, dev, SCAN_WITH_ADF); 1510141cc406Sopenharmony_ci } 1511141cc406Sopenharmony_ci if (m_subdev.f_mode_type & 0x07) 1512141cc406Sopenharmony_ci { 1513141cc406Sopenharmony_ci dev->info.adf_fsu_installed |= HAVE_FSU; 1514141cc406Sopenharmony_ci get_max_scan_size(fd, dev, SCAN_WITH_FSU); 1515141cc406Sopenharmony_ci } 1516141cc406Sopenharmony_ci 1517141cc406Sopenharmony_ci if ( dev->sensedat.model == JX320 1518141cc406Sopenharmony_ci || dev->sensedat.model == JX330 1519141cc406Sopenharmony_ci || dev->sensedat.model == JX350) 1520141cc406Sopenharmony_ci { 1521141cc406Sopenharmony_ci dev->info.xres_range.max = 600; 1522141cc406Sopenharmony_ci dev->info.xres_range.min = 30; 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci dev->info.yres_range.max = 600; 1525141cc406Sopenharmony_ci dev->info.yres_range.min = 30; 1526141cc406Sopenharmony_ci dev->info.x_default = SANE_FIX(210); 1527141cc406Sopenharmony_ci dev->info.y_default = SANE_FIX(297); 1528141cc406Sopenharmony_ci } 1529141cc406Sopenharmony_ci else if (dev->sensedat.model == JX250) 1530141cc406Sopenharmony_ci { 1531141cc406Sopenharmony_ci dev->info.xres_range.max = 400; 1532141cc406Sopenharmony_ci dev->info.xres_range.min = 30; 1533141cc406Sopenharmony_ci 1534141cc406Sopenharmony_ci dev->info.yres_range.max = 400; 1535141cc406Sopenharmony_ci dev->info.yres_range.min = 30; 1536141cc406Sopenharmony_ci dev->info.x_default = SANE_FIX(210); 1537141cc406Sopenharmony_ci dev->info.y_default = SANE_FIX(297); 1538141cc406Sopenharmony_ci } 1539141cc406Sopenharmony_ci } 1540141cc406Sopenharmony_ci sanei_scsi_close (fd); 1541141cc406Sopenharmony_ci 1542141cc406Sopenharmony_ci dev->info.threshold_range.min = 1; 1543141cc406Sopenharmony_ci dev->info.threshold_range.max = 255; 1544141cc406Sopenharmony_ci dev->info.threshold_range.quant = 0; 1545141cc406Sopenharmony_ci 1546141cc406Sopenharmony_ci DBG (5, "xres_default=%d\n", dev->info.xres_default); 1547141cc406Sopenharmony_ci DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max); 1548141cc406Sopenharmony_ci DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min); 1549141cc406Sopenharmony_ci DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant); 1550141cc406Sopenharmony_ci DBG (5, "yres_default=%d\n", dev->info.yres_default); 1551141cc406Sopenharmony_ci DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max); 1552141cc406Sopenharmony_ci DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min); 1553141cc406Sopenharmony_ci DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant); 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci DBG (5, "x_default=%f\n", SANE_UNFIX(dev->info.x_default)); 1556141cc406Sopenharmony_ci DBG (5, "tl_x_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].max)); 1557141cc406Sopenharmony_ci DBG (5, "tl_x_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].min)); 1558141cc406Sopenharmony_ci DBG (5, "tl_x_range[0].quant=%d\n", dev->info.tl_x_ranges[SCAN_SIMPLE].quant); 1559141cc406Sopenharmony_ci DBG (5, "br_x_range[0].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].max)); 1560141cc406Sopenharmony_ci DBG (5, "br_x_range[0].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].min)); 1561141cc406Sopenharmony_ci DBG (5, "br_x_range[0].quant=%d\n", dev->info.br_x_ranges[SCAN_SIMPLE].quant); 1562141cc406Sopenharmony_ci DBG (5, "y_default=%f\n", SANE_UNFIX(dev->info.y_default)); 1563141cc406Sopenharmony_ci DBG (5, "tl_y_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].max)); 1564141cc406Sopenharmony_ci DBG (5, "tl_y_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].min)); 1565141cc406Sopenharmony_ci DBG (5, "tl_y_range[0].quant=%d\n", dev->info.tl_y_ranges[SCAN_SIMPLE].quant); 1566141cc406Sopenharmony_ci DBG (5, "br_y_range[0].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].max)); 1567141cc406Sopenharmony_ci DBG (5, "br_y_range[0].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].min)); 1568141cc406Sopenharmony_ci DBG (5, "br_y_range[0].quant=%d\n", dev->info.br_y_ranges[SCAN_SIMPLE].quant); 1569141cc406Sopenharmony_ci 1570141cc406Sopenharmony_ci if (dev->info.adf_fsu_installed & HAVE_FSU) 1571141cc406Sopenharmony_ci { 1572141cc406Sopenharmony_ci DBG (5, "tl_x_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].max)); 1573141cc406Sopenharmony_ci DBG (5, "tl_x_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].min)); 1574141cc406Sopenharmony_ci DBG (5, "tl_x_range[1].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_FSU].quant); 1575141cc406Sopenharmony_ci DBG (5, "br_x_range[1].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].max)); 1576141cc406Sopenharmony_ci DBG (5, "br_x_range[1].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].min)); 1577141cc406Sopenharmony_ci DBG (5, "br_x_range[1].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_FSU].quant); 1578141cc406Sopenharmony_ci DBG (5, "tl_y_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].max)); 1579141cc406Sopenharmony_ci DBG (5, "tl_y_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].min)); 1580141cc406Sopenharmony_ci DBG (5, "tl_y_range[1].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_FSU].quant); 1581141cc406Sopenharmony_ci DBG (5, "br_y_range[1].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].max)); 1582141cc406Sopenharmony_ci DBG (5, "br_y_range[1].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].min)); 1583141cc406Sopenharmony_ci DBG (5, "br_y_range[1].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_FSU].quant); 1584141cc406Sopenharmony_ci } 1585141cc406Sopenharmony_ci 1586141cc406Sopenharmony_ci if (dev->info.adf_fsu_installed & HAVE_ADF) 1587141cc406Sopenharmony_ci { 1588141cc406Sopenharmony_ci DBG (5, "tl_x_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].max)); 1589141cc406Sopenharmony_ci DBG (5, "tl_x_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].min)); 1590141cc406Sopenharmony_ci DBG (5, "tl_x_range[2].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_ADF].quant); 1591141cc406Sopenharmony_ci DBG (5, "br_x_range[2].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].max)); 1592141cc406Sopenharmony_ci DBG (5, "br_x_range[2].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].min)); 1593141cc406Sopenharmony_ci DBG (5, "br_x_range[2].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_ADF].quant); 1594141cc406Sopenharmony_ci DBG (5, "tl_y_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].max)); 1595141cc406Sopenharmony_ci DBG (5, "tl_y_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].min)); 1596141cc406Sopenharmony_ci DBG (5, "tl_y_range[2].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_ADF].quant); 1597141cc406Sopenharmony_ci DBG (5, "br_y_range[2].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].max)); 1598141cc406Sopenharmony_ci DBG (5, "br_y_range[2].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].min)); 1599141cc406Sopenharmony_ci DBG (5, "br_y_range[2].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_ADF].quant); 1600141cc406Sopenharmony_ci } 1601141cc406Sopenharmony_ci 1602141cc406Sopenharmony_ci DBG (5, "bmu=%d\n", dev->info.bmu); 1603141cc406Sopenharmony_ci DBG (5, "mud=%d\n", dev->info.mud); 1604141cc406Sopenharmony_ci 1605141cc406Sopenharmony_ci ++num_devices; 1606141cc406Sopenharmony_ci dev->next = first_dev; 1607141cc406Sopenharmony_ci first_dev = dev; 1608141cc406Sopenharmony_ci 1609141cc406Sopenharmony_ci if (devp) 1610141cc406Sopenharmony_ci *devp = dev; 1611141cc406Sopenharmony_ci 1612141cc406Sopenharmony_ci DBG (10, ">>\n"); 1613141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1614141cc406Sopenharmony_ci} 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci/* Enabling / disabling of gamma options. 1617141cc406Sopenharmony_ci Depends on many user settable options, so lets put it into 1618141cc406Sopenharmony_ci one function to be called by init_options and by sane_control_option 1619141cc406Sopenharmony_ci 1620141cc406Sopenharmony_ci*/ 1621141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 1622141cc406Sopenharmony_cistatic void 1623141cc406Sopenharmony_ciset_gamma_caps(SHARP_Scanner *s) 1624141cc406Sopenharmony_ci{ 1625141cc406Sopenharmony_ci /* neither fixed nor custom gamma for line art modes */ 1626141cc406Sopenharmony_ci if ( strcmp(s->val[OPT_MODE].s, M_LINEART) == 0 1627141cc406Sopenharmony_ci || strcmp(s->val[OPT_MODE].s, M_LINEART_COLOR) == 0) 1628141cc406Sopenharmony_ci { 1629141cc406Sopenharmony_ci s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; 1630141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1631141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1632141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1633141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1634141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1635141cc406Sopenharmony_ci } 1636141cc406Sopenharmony_ci else if (strcmp(s->val[OPT_MODE].s, M_GRAY) == 0) 1637141cc406Sopenharmony_ci { 1638141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1639141cc406Sopenharmony_ci if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) 1640141cc406Sopenharmony_ci { 1641141cc406Sopenharmony_ci s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1642141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1643141cc406Sopenharmony_ci } 1644141cc406Sopenharmony_ci else 1645141cc406Sopenharmony_ci { 1646141cc406Sopenharmony_ci s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; 1647141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1648141cc406Sopenharmony_ci } 1649141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1650141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1651141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1652141cc406Sopenharmony_ci } 1653141cc406Sopenharmony_ci else 1654141cc406Sopenharmony_ci { 1655141cc406Sopenharmony_ci /* color mode */ 1656141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1657141cc406Sopenharmony_ci if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) 1658141cc406Sopenharmony_ci { 1659141cc406Sopenharmony_ci s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1660141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1661141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1662141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1663141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1664141cc406Sopenharmony_ci } 1665141cc406Sopenharmony_ci else 1666141cc406Sopenharmony_ci { 1667141cc406Sopenharmony_ci s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; 1668141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1669141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1670141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1671141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1672141cc406Sopenharmony_ci } 1673141cc406Sopenharmony_ci } 1674141cc406Sopenharmony_ci} 1675141cc406Sopenharmony_ci#endif /* USE_CUSTOM_GAMMA */ 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci/* The next function is a slightly modified version of sanei_constrain_value 1678141cc406Sopenharmony_ci Instead of returning status information like STATUS_INVAL, it adjusts 1679141cc406Sopenharmony_ci an invalid value to the nearest allowed one. 1680141cc406Sopenharmony_ci*/ 1681141cc406Sopenharmony_cistatic void 1682141cc406Sopenharmony_ciclip_value (const SANE_Option_Descriptor * opt, void * value) 1683141cc406Sopenharmony_ci{ 1684141cc406Sopenharmony_ci const SANE_String_Const * string_list; 1685141cc406Sopenharmony_ci const SANE_Word * word_list; 1686141cc406Sopenharmony_ci int i, num_matches, match; 1687141cc406Sopenharmony_ci const SANE_Range * range; 1688141cc406Sopenharmony_ci SANE_Word w, v; 1689141cc406Sopenharmony_ci size_t len; 1690141cc406Sopenharmony_ci 1691141cc406Sopenharmony_ci switch (opt->constraint_type) 1692141cc406Sopenharmony_ci { 1693141cc406Sopenharmony_ci case SANE_CONSTRAINT_RANGE: 1694141cc406Sopenharmony_ci w = *(SANE_Word *) value; 1695141cc406Sopenharmony_ci range = opt->constraint.range; 1696141cc406Sopenharmony_ci 1697141cc406Sopenharmony_ci if (w < range->min) 1698141cc406Sopenharmony_ci w = range->min; 1699141cc406Sopenharmony_ci else if (w > range->max) 1700141cc406Sopenharmony_ci w = range->max; 1701141cc406Sopenharmony_ci 1702141cc406Sopenharmony_ci if (range->quant) 1703141cc406Sopenharmony_ci { 1704141cc406Sopenharmony_ci v = (w - range->min + range->quant/2) / range->quant; 1705141cc406Sopenharmony_ci w = v * range->quant + range->min; 1706141cc406Sopenharmony_ci *(SANE_Word*) value = w; 1707141cc406Sopenharmony_ci } 1708141cc406Sopenharmony_ci break; 1709141cc406Sopenharmony_ci 1710141cc406Sopenharmony_ci case SANE_CONSTRAINT_WORD_LIST: 1711141cc406Sopenharmony_ci w = *(SANE_Word *) value; 1712141cc406Sopenharmony_ci word_list = opt->constraint.word_list; 1713141cc406Sopenharmony_ci for (i = 1; w != word_list[i]; ++i) 1714141cc406Sopenharmony_ci if (i >= word_list[0]) 1715141cc406Sopenharmony_ci /* somewhat arbitrary... Would be better to have a default value 1716141cc406Sopenharmony_ci explicitly defined. 1717141cc406Sopenharmony_ci */ 1718141cc406Sopenharmony_ci *(SANE_Word*) value = word_list[1]; 1719141cc406Sopenharmony_ci break; 1720141cc406Sopenharmony_ci 1721141cc406Sopenharmony_ci case SANE_CONSTRAINT_STRING_LIST: 1722141cc406Sopenharmony_ci /* Matching algorithm: take the longest unique match ignoring 1723141cc406Sopenharmony_ci case. If there is an exact match, it is admissible even if 1724141cc406Sopenharmony_ci the same string is a prefix of a longer option name. */ 1725141cc406Sopenharmony_ci string_list = opt->constraint.string_list; 1726141cc406Sopenharmony_ci len = strlen (value); 1727141cc406Sopenharmony_ci 1728141cc406Sopenharmony_ci /* count how many matches of length LEN characters we have: */ 1729141cc406Sopenharmony_ci num_matches = 0; 1730141cc406Sopenharmony_ci match = -1; 1731141cc406Sopenharmony_ci for (i = 0; string_list[i]; ++i) 1732141cc406Sopenharmony_ci if (strncasecmp (value, string_list[i], len) == 0 1733141cc406Sopenharmony_ci && len <= strlen (string_list[i])) 1734141cc406Sopenharmony_ci { 1735141cc406Sopenharmony_ci match = i; 1736141cc406Sopenharmony_ci if (len == strlen (string_list[i])) 1737141cc406Sopenharmony_ci { 1738141cc406Sopenharmony_ci /* exact match... */ 1739141cc406Sopenharmony_ci if (strcmp (value, string_list[i]) != 0) 1740141cc406Sopenharmony_ci /* ...but case differs */ 1741141cc406Sopenharmony_ci strcpy (value, string_list[match]); 1742141cc406Sopenharmony_ci } 1743141cc406Sopenharmony_ci ++num_matches; 1744141cc406Sopenharmony_ci } 1745141cc406Sopenharmony_ci 1746141cc406Sopenharmony_ci if (num_matches > 1) 1747141cc406Sopenharmony_ci /* xxx quite arbitrary... We could also choose the first match 1748141cc406Sopenharmony_ci */ 1749141cc406Sopenharmony_ci strcpy(value, string_list[match]); 1750141cc406Sopenharmony_ci else if (num_matches == 1) 1751141cc406Sopenharmony_ci strcpy (value, string_list[match]); 1752141cc406Sopenharmony_ci else 1753141cc406Sopenharmony_ci strcpy (value, string_list[0]); 1754141cc406Sopenharmony_ci 1755141cc406Sopenharmony_ci default: 1756141cc406Sopenharmony_ci break; 1757141cc406Sopenharmony_ci } 1758141cc406Sopenharmony_ci} 1759141cc406Sopenharmony_ci 1760141cc406Sopenharmony_ci/* make sure that enough memory is allocated for each string, 1761141cc406Sopenharmony_ci so that the strcpy in sane_control_option / set value cannot 1762141cc406Sopenharmony_ci write behind the end of the allocated memory. 1763141cc406Sopenharmony_ci*/ 1764141cc406Sopenharmony_cistatic SANE_Status 1765141cc406Sopenharmony_ciinit_string_option(SHARP_Scanner *s, SANE_String_Const name, 1766141cc406Sopenharmony_ci SANE_String_Const title, SANE_String_Const desc, 1767141cc406Sopenharmony_ci const SANE_String_Const *string_list, int option, int default_index) 1768141cc406Sopenharmony_ci{ 1769141cc406Sopenharmony_ci int i; 1770141cc406Sopenharmony_ci 1771141cc406Sopenharmony_ci s->opt[option].name = name; 1772141cc406Sopenharmony_ci s->opt[option].title = title; 1773141cc406Sopenharmony_ci s->opt[option].desc = desc; 1774141cc406Sopenharmony_ci s->opt[option].type = SANE_TYPE_STRING; 1775141cc406Sopenharmony_ci s->opt[option].size = max_string_size (string_list); 1776141cc406Sopenharmony_ci s->opt[option].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1777141cc406Sopenharmony_ci s->opt[option].constraint.string_list = string_list; 1778141cc406Sopenharmony_ci s->val[option].s = malloc(s->opt[option].size); 1779141cc406Sopenharmony_ci if (s->val[option].s == 0) 1780141cc406Sopenharmony_ci { 1781141cc406Sopenharmony_ci for (i = 1; i < NUM_OPTIONS; i++) 1782141cc406Sopenharmony_ci { 1783141cc406Sopenharmony_ci if (s->val[i].s && s->opt[i].type == SANE_TYPE_STRING) 1784141cc406Sopenharmony_ci free(s->val[i].s); 1785141cc406Sopenharmony_ci } 1786141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1787141cc406Sopenharmony_ci } 1788141cc406Sopenharmony_ci strcpy(s->val[option].s, string_list[default_index]); 1789141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1790141cc406Sopenharmony_ci} 1791141cc406Sopenharmony_ci 1792141cc406Sopenharmony_cistatic SANE_Status 1793141cc406Sopenharmony_ciinit_options (SHARP_Scanner * s) 1794141cc406Sopenharmony_ci{ 1795141cc406Sopenharmony_ci int i, default_source, sourcename_index = 0; 1796141cc406Sopenharmony_ci SANE_Word scalar; 1797141cc406Sopenharmony_ci DBG (10, "<< init_options "); 1798141cc406Sopenharmony_ci 1799141cc406Sopenharmony_ci memset (s->opt, 0, sizeof (s->opt)); 1800141cc406Sopenharmony_ci memset (s->val, 0, sizeof (s->val)); 1801141cc406Sopenharmony_ci 1802141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 1803141cc406Sopenharmony_ci { 1804141cc406Sopenharmony_ci s->opt[i].size = sizeof (SANE_Word); 1805141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1806141cc406Sopenharmony_ci s->val[i].s = 0; 1807141cc406Sopenharmony_ci } 1808141cc406Sopenharmony_ci 1809141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 1810141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 1811141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 1812141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 1813141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 1814141cc406Sopenharmony_ci 1815141cc406Sopenharmony_ci /* Mode group: */ 1816141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = "Scan Mode"; 1817141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 1818141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 1819141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 1820141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1821141cc406Sopenharmony_ci 1822141cc406Sopenharmony_ci /* scan mode */ 1823141cc406Sopenharmony_ci#if 0 1824141cc406Sopenharmony_ci s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 1825141cc406Sopenharmony_ci s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 1826141cc406Sopenharmony_ci s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 1827141cc406Sopenharmony_ci s->opt[OPT_MODE].type = SANE_TYPE_STRING; 1828141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size (mode_list); 1829141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1830141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_list; 1831141cc406Sopenharmony_ci s->val[OPT_MODE].s = strdup (mode_list[3]); /* color scan */ 1832141cc406Sopenharmony_ci#endif 1833141cc406Sopenharmony_ci init_string_option(s, SANE_NAME_SCAN_MODE, SANE_TITLE_SCAN_MODE, 1834141cc406Sopenharmony_ci SANE_DESC_SCAN_MODE, mode_list, OPT_MODE, 3); 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci /* half tone */ 1837141cc406Sopenharmony_ci#if 0 1838141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE_PATTERN; 1839141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE_PATTERN; 1840141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].desc = SANE_DESC_HALFTONE " (JX-330 only)"; 1841141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING; 1842141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].size = max_string_size (halftone_list); 1843141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1844141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list; 1845141cc406Sopenharmony_ci s->val[OPT_HALFTONE].s = strdup (halftone_list[0]); 1846141cc406Sopenharmony_ci#endif 1847141cc406Sopenharmony_ci init_string_option(s, SANE_NAME_HALFTONE_PATTERN, SANE_TITLE_HALFTONE_PATTERN, 1848141cc406Sopenharmony_ci SANE_DESC_HALFTONE " (JX-330 only)", halftone_list, OPT_HALFTONE, 0); 1849141cc406Sopenharmony_ci 1850141cc406Sopenharmony_ci if (s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350 || 1851141cc406Sopenharmony_ci s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX320) 1852141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci i = 0; 1855141cc406Sopenharmony_ci default_source = s->dev->info.default_scan_mode; 1856141cc406Sopenharmony_ci 1857141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF 1858141cc406Sopenharmony_ci /* The JX330, but nut not the JX250 supports auto selection of ADF/FSU: */ 1859141cc406Sopenharmony_ci if (s->dev->info.adf_fsu_installed && (s->dev->sensedat.model == JX330)) 1860141cc406Sopenharmony_ci s->dev->info->scansources[i++] = use_auto; 1861141cc406Sopenharmony_ci#endif 1862141cc406Sopenharmony_ci if (s->dev->info.adf_fsu_installed & HAVE_ADF) 1863141cc406Sopenharmony_ci { 1864141cc406Sopenharmony_ci if (default_source == -1) 1865141cc406Sopenharmony_ci default_source = SCAN_WITH_ADF; 1866141cc406Sopenharmony_ci if (default_source == SCAN_WITH_ADF) 1867141cc406Sopenharmony_ci sourcename_index = i; 1868141cc406Sopenharmony_ci s->dev->info.scansources[i++] = use_adf; 1869141cc406Sopenharmony_ci } 1870141cc406Sopenharmony_ci else 1871141cc406Sopenharmony_ci { 1872141cc406Sopenharmony_ci if (default_source == SCAN_WITH_ADF) 1873141cc406Sopenharmony_ci default_source = SCAN_SIMPLE; 1874141cc406Sopenharmony_ci } 1875141cc406Sopenharmony_ci if (s->dev->info.adf_fsu_installed & HAVE_FSU) 1876141cc406Sopenharmony_ci { 1877141cc406Sopenharmony_ci if (default_source == -1) 1878141cc406Sopenharmony_ci default_source = SCAN_WITH_FSU; 1879141cc406Sopenharmony_ci if (default_source == SCAN_WITH_FSU) 1880141cc406Sopenharmony_ci sourcename_index = i; 1881141cc406Sopenharmony_ci s->dev->info.scansources[i++] = use_fsu; 1882141cc406Sopenharmony_ci } 1883141cc406Sopenharmony_ci else 1884141cc406Sopenharmony_ci { 1885141cc406Sopenharmony_ci if (default_source == SCAN_WITH_FSU) 1886141cc406Sopenharmony_ci default_source = SCAN_SIMPLE; 1887141cc406Sopenharmony_ci } 1888141cc406Sopenharmony_ci if (default_source < 0) 1889141cc406Sopenharmony_ci default_source = SCAN_SIMPLE; 1890141cc406Sopenharmony_ci if (default_source == SCAN_SIMPLE) 1891141cc406Sopenharmony_ci sourcename_index = i; 1892141cc406Sopenharmony_ci s->dev->info.scansources[i++] = use_simple; 1893141cc406Sopenharmony_ci s->dev->info.scansources[i] = 0; 1894141cc406Sopenharmony_ci 1895141cc406Sopenharmony_ci#if 0 1896141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].name = SANE_NAME_SCAN_SOURCE; 1897141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].title = SANE_TITLE_SCAN_SOURCE; 1898141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].desc = SANE_DESC_SCAN_SOURCE; 1899141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].type = SANE_TYPE_STRING; 1900141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].size = max_string_size (s->dev->info.scansources); 1901141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1902141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].constraint.string_list = (SANE_String_Const*)s->dev->info.scansources; 1903141cc406Sopenharmony_ci s->val[OPT_SCANSOURCE].s = strdup (s->dev->info.scansources[0]); 1904141cc406Sopenharmony_ci#endif 1905141cc406Sopenharmony_ci 1906141cc406Sopenharmony_ci init_string_option(s, SANE_NAME_SCAN_SOURCE, SANE_TITLE_SCAN_SOURCE, 1907141cc406Sopenharmony_ci SANE_DESC_SCAN_SOURCE, (SANE_String_Const*)s->dev->info.scansources, 1908141cc406Sopenharmony_ci OPT_SCANSOURCE, sourcename_index); 1909141cc406Sopenharmony_ci 1910141cc406Sopenharmony_ci if (i < 2) 1911141cc406Sopenharmony_ci s->opt[OPT_SCANSOURCE].cap |= SANE_CAP_INACTIVE; 1912141cc406Sopenharmony_ci 1913141cc406Sopenharmony_ci#if 0 1914141cc406Sopenharmony_ci s->opt[OPT_PAPER].name = "Paper size"; 1915141cc406Sopenharmony_ci s->opt[OPT_PAPER].title = "Paper size"; 1916141cc406Sopenharmony_ci s->opt[OPT_PAPER].desc = "Paper size"; 1917141cc406Sopenharmony_ci s->opt[OPT_PAPER].type = SANE_TYPE_STRING; 1918141cc406Sopenharmony_ci /* xxx the possible values for the paper size should be changeable, 1919141cc406Sopenharmony_ci to reflect the different maximum scan sizes with/without ADF and FSU 1920141cc406Sopenharmony_ci */ 1921141cc406Sopenharmony_ci if (s->dev->sensedat.model == JX610) 1922141cc406Sopenharmony_ci { 1923141cc406Sopenharmony_ci s->opt[OPT_PAPER].size = max_string_size (paper_list_jx610); 1924141cc406Sopenharmony_ci s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1925141cc406Sopenharmony_ci s->opt[OPT_PAPER].constraint.string_list = paper_list_jx610; 1926141cc406Sopenharmony_ci s->val[OPT_PAPER].s = strdup (paper_list_jx610[1]); 1927141cc406Sopenharmony_ci } 1928141cc406Sopenharmony_ci else 1929141cc406Sopenharmony_ci { 1930141cc406Sopenharmony_ci s->opt[OPT_PAPER].size = max_string_size (paper_list_jx330); 1931141cc406Sopenharmony_ci s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1932141cc406Sopenharmony_ci s->opt[OPT_PAPER].constraint.string_list = paper_list_jx330; 1933141cc406Sopenharmony_ci s->val[OPT_PAPER].s = strdup (paper_list_jx330[0]); 1934141cc406Sopenharmony_ci } 1935141cc406Sopenharmony_ci#endif 1936141cc406Sopenharmony_ci 1937141cc406Sopenharmony_ci if (s->dev->sensedat.model == JX610) 1938141cc406Sopenharmony_ci init_string_option(s, "Paper size", "Paper size", 1939141cc406Sopenharmony_ci "Paper size", paper_list_jx610, OPT_PAPER, 1); 1940141cc406Sopenharmony_ci else 1941141cc406Sopenharmony_ci init_string_option(s, "Paper size", "Paper size", 1942141cc406Sopenharmony_ci "Paper size", paper_list_jx330, OPT_PAPER, 0); 1943141cc406Sopenharmony_ci 1944141cc406Sopenharmony_ci /* gamma */ 1945141cc406Sopenharmony_ci#if 0 1946141cc406Sopenharmony_ci s->opt[OPT_GAMMA].name = "Gamma"; 1947141cc406Sopenharmony_ci s->opt[OPT_GAMMA].title = "Gamma"; 1948141cc406Sopenharmony_ci s->opt[OPT_GAMMA].desc = "Gamma"; 1949141cc406Sopenharmony_ci s->opt[OPT_GAMMA].type = SANE_TYPE_STRING; 1950141cc406Sopenharmony_ci s->opt[OPT_GAMMA].size = max_string_size (gamma_list); 1951141cc406Sopenharmony_ci s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1952141cc406Sopenharmony_ci s->opt[OPT_GAMMA].constraint.string_list = gamma_list; 1953141cc406Sopenharmony_ci s->val[OPT_GAMMA].s = strdup (gamma_list[1]); 1954141cc406Sopenharmony_ci#endif 1955141cc406Sopenharmony_ci 1956141cc406Sopenharmony_ci init_string_option(s, "Gamma", "Gamma", "Gamma", gamma_list, OPT_GAMMA, 1); 1957141cc406Sopenharmony_ci 1958141cc406Sopenharmony_ci /* scan speed */ 1959141cc406Sopenharmony_ci s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; 1960141cc406Sopenharmony_ci s->opt[OPT_SPEED].title = "Scan speed [fast]"; 1961141cc406Sopenharmony_ci s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; 1962141cc406Sopenharmony_ci s->opt[OPT_SPEED].type = SANE_TYPE_BOOL; 1963141cc406Sopenharmony_ci s->val[OPT_SPEED].w = SANE_TRUE; 1964141cc406Sopenharmony_ci 1965141cc406Sopenharmony_ci /* Resolution Group */ 1966141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_GROUP].title = "Resolution"; 1967141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_GROUP].desc = ""; 1968141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_GROUP].type = SANE_TYPE_GROUP; 1969141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_GROUP].cap = 0; 1970141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1971141cc406Sopenharmony_ci 1972141cc406Sopenharmony_ci /* select resolution */ 1973141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST 1974141cc406Sopenharmony_ci if (s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX330 || 1975141cc406Sopenharmony_ci s->dev->sensedat.model == JX350 || s->dev->sensedat.model == JX320) 1976141cc406Sopenharmony_ci init_string_option(s, "ResolutionList", "ResolutionList", "ResolutionList", 1977141cc406Sopenharmony_ci resolution_list_jx610, OPT_RESOLUTION_LIST, RESOLUTION_MAX_JX610); 1978141cc406Sopenharmony_ci else 1979141cc406Sopenharmony_ci init_string_option(s, "ResolutionList", "ResolutionList", "ResolutionList", 1980141cc406Sopenharmony_ci resolution_list_jx250, OPT_RESOLUTION_LIST, RESOLUTION_MAX_JX250); 1981141cc406Sopenharmony_ci#endif 1982141cc406Sopenharmony_ci /* x resolution */ 1983141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 1984141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 1985141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 1986141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; 1987141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; 1988141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 1989141cc406Sopenharmony_ci s->opt[OPT_X_RESOLUTION].constraint.range = &s->dev->info.xres_range; 1990141cc406Sopenharmony_ci s->val[OPT_X_RESOLUTION].w = s->dev->info.xres_default; 1991141cc406Sopenharmony_ci 1992141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION 1993141cc406Sopenharmony_ci /* y resolution */ 1994141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION; 1995141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION; 1996141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 1997141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; 1998141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; 1999141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 2000141cc406Sopenharmony_ci s->opt[OPT_Y_RESOLUTION].constraint.range = &s->dev->info.yres_range; 2001141cc406Sopenharmony_ci s->val[OPT_Y_RESOLUTION].w = s->dev->info.yres_default; 2002141cc406Sopenharmony_ci#endif 2003141cc406Sopenharmony_ci 2004141cc406Sopenharmony_ci /* "Geometry" group: */ 2005141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; 2006141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 2007141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 2008141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 2009141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci /* top-left x */ 2012141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 2013141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 2014141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 2015141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 2016141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 2017141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 2018141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = &s->dev->info.tl_x_ranges[default_source]; 2019141cc406Sopenharmony_ci s->val[OPT_TL_X].w = s->dev->info.tl_x_ranges[default_source].min; 2020141cc406Sopenharmony_ci 2021141cc406Sopenharmony_ci /* top-left y */ 2022141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 2023141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 2024141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 2025141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 2026141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 2027141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2028141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = &s->dev->info.tl_y_ranges[default_source]; 2029141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = s->dev->info.tl_y_ranges[default_source].min; 2030141cc406Sopenharmony_ci 2031141cc406Sopenharmony_ci /* bottom-right x */ 2032141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 2033141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 2034141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 2035141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 2036141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 2037141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 2038141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = &s->dev->info.br_x_ranges[default_source]; 2039141cc406Sopenharmony_ci scalar = s->dev->info.x_default; 2040141cc406Sopenharmony_ci clip_value (&s->opt[OPT_BR_X], &scalar); 2041141cc406Sopenharmony_ci s->val[OPT_BR_X].w = scalar; 2042141cc406Sopenharmony_ci 2043141cc406Sopenharmony_ci /* bottom-right y */ 2044141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 2045141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 2046141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 2047141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 2048141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 2049141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2050141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = &s->dev->info.br_y_ranges[default_source]; 2051141cc406Sopenharmony_ci /* The FSU for JX250 allows a maximum scan length of 11.5 inch, 2052141cc406Sopenharmony_ci which is less than the default value of 297 mm 2053141cc406Sopenharmony_ci */ 2054141cc406Sopenharmony_ci scalar = s->dev->info.y_default; 2055141cc406Sopenharmony_ci clip_value (&s->opt[OPT_BR_X], &scalar); 2056141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = scalar; 2057141cc406Sopenharmony_ci 2058141cc406Sopenharmony_ci /* "Enhancement" group: */ 2059141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; 2060141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 2061141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 2062141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; 2063141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2064141cc406Sopenharmony_ci 2065141cc406Sopenharmony_ci /* edge emphasis */ 2066141cc406Sopenharmony_ci#if 0 2067141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].name = "Edge emphasis"; 2068141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].title = "Edge emphasis"; 2069141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].desc = "Edge emphasis"; 2070141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].type = SANE_TYPE_STRING; 2071141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].size = max_string_size (edge_emphasis_list); 2072141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2073141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].constraint.string_list = edge_emphasis_list; 2074141cc406Sopenharmony_ci s->val[OPT_EDGE_EMPHASIS].s = strdup (edge_emphasis_list[0]); 2075141cc406Sopenharmony_ci#endif 2076141cc406Sopenharmony_ci init_string_option(s, "Edge emphasis", "Edge emphasis", 2077141cc406Sopenharmony_ci "Edge emphasis", edge_emphasis_list, 2078141cc406Sopenharmony_ci OPT_EDGE_EMPHASIS, 0); 2079141cc406Sopenharmony_ci 2080141cc406Sopenharmony_ci if ( s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350 2081141cc406Sopenharmony_ci || s->dev->sensedat.model == JX320) 2082141cc406Sopenharmony_ci s->opt[OPT_EDGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; 2083141cc406Sopenharmony_ci 2084141cc406Sopenharmony_ci /* threshold */ 2085141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 2086141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 2087141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 2088141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 2089141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 2090141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 2091141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint.range = &s->dev->info.threshold_range; 2092141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w = 128; 2093141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2094141cc406Sopenharmony_ci 2095141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 2096141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].name = SANE_NAME_THRESHOLD "-red"; 2097141cc406Sopenharmony_ci /* xxx the titles and descriptions are confusing: 2098141cc406Sopenharmony_ci "set white point (red)" 2099141cc406Sopenharmony_ci Any idea? maybe "threshold to get the red component on" 2100141cc406Sopenharmony_ci */ 2101141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].title = SANE_TITLE_THRESHOLD " (red)"; 2102141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].desc = SANE_DESC_THRESHOLD " (red)"; 2103141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].type = SANE_TYPE_INT; 2104141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].unit = SANE_UNIT_NONE; 2105141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].constraint_type = SANE_CONSTRAINT_RANGE; 2106141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].constraint.range = &s->dev->info.threshold_range; 2107141cc406Sopenharmony_ci s->val[OPT_THRESHOLD_R].w = 128; 2108141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; 2109141cc406Sopenharmony_ci 2110141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].name = SANE_NAME_THRESHOLD "-green"; 2111141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].title = SANE_TITLE_THRESHOLD " (green)"; 2112141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].desc = SANE_DESC_THRESHOLD " (green)"; 2113141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].type = SANE_TYPE_INT; 2114141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].unit = SANE_UNIT_NONE; 2115141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].constraint_type = SANE_CONSTRAINT_RANGE; 2116141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].constraint.range = &s->dev->info.threshold_range; 2117141cc406Sopenharmony_ci s->val[OPT_THRESHOLD_G].w = 128; 2118141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; 2119141cc406Sopenharmony_ci 2120141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].name = SANE_NAME_THRESHOLD "-blue"; 2121141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].title = SANE_TITLE_THRESHOLD " (blue)"; 2122141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].desc = SANE_DESC_THRESHOLD " (blue)"; 2123141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].type = SANE_TYPE_INT; 2124141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].unit = SANE_UNIT_NONE; 2125141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].constraint_type = SANE_CONSTRAINT_RANGE; 2126141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].constraint.range = &s->dev->info.threshold_range; 2127141cc406Sopenharmony_ci s->val[OPT_THRESHOLD_B].w = 128; 2128141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; 2129141cc406Sopenharmony_ci 2130141cc406Sopenharmony_ci#endif 2131141cc406Sopenharmony_ci 2132141cc406Sopenharmony_ci /* light color (for gray scale and line art scans) */ 2133141cc406Sopenharmony_ci#if 0 2134141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].name = "LightColor"; 2135141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].title = "Light Color"; 2136141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].desc = "Light Color"; 2137141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].type = SANE_TYPE_STRING; 2138141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].size = max_string_size (light_color_list); 2139141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2140141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].constraint.string_list = light_color_list; 2141141cc406Sopenharmony_ci s->val[OPT_LIGHTCOLOR].s = strdup (light_color_list[3]); 2142141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; 2143141cc406Sopenharmony_ci#endif 2144141cc406Sopenharmony_ci init_string_option(s, "LightColor", "LightColor", "LightColor", 2145141cc406Sopenharmony_ci light_color_list, OPT_LIGHTCOLOR, 3); 2146141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; 2147141cc406Sopenharmony_ci 2148141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 2149141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 2150141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 2151141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 2152141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 2153141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = SANE_FALSE; 2154141cc406Sopenharmony_ci 2155141cc406Sopenharmony_ci 2156141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 2157141cc406Sopenharmony_ci /* custom-gamma table */ 2158141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 2159141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 2160141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 2161141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 2162141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 2163141cc406Sopenharmony_ci 2164141cc406Sopenharmony_ci /* grayscale gamma vector */ 2165141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 2166141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 2167141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 2168141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 2169141cc406Sopenharmony_ci#if 0 2170141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 2171141cc406Sopenharmony_ci#endif 2172141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 2173141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); 2174141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 2175141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; 2176141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; 2177141cc406Sopenharmony_ci 2178141cc406Sopenharmony_ci /* red gamma vector */ 2179141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 2180141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 2181141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 2182141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 2183141cc406Sopenharmony_ci#if 0 2184141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 2185141cc406Sopenharmony_ci#endif 2186141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 2187141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); 2188141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 2189141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; 2190141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; 2191141cc406Sopenharmony_ci 2192141cc406Sopenharmony_ci /* green gamma vector */ 2193141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 2194141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 2195141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 2196141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 2197141cc406Sopenharmony_ci#if 0 2198141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 2199141cc406Sopenharmony_ci#endif 2200141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 2201141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); 2202141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 2203141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; 2204141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; 2205141cc406Sopenharmony_ci 2206141cc406Sopenharmony_ci /* blue gamma vector */ 2207141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 2208141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 2209141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 2210141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 2211141cc406Sopenharmony_ci#if 0 2212141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 2213141cc406Sopenharmony_ci#endif 2214141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 2215141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); 2216141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 2217141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; 2218141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; 2219141cc406Sopenharmony_ci set_gamma_caps(s); 2220141cc406Sopenharmony_ci#endif 2221141cc406Sopenharmony_ci 2222141cc406Sopenharmony_ci DBG (10, ">>\n"); 2223141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2224141cc406Sopenharmony_ci} 2225141cc406Sopenharmony_ci 2226141cc406Sopenharmony_cistatic SANE_Status 2227141cc406Sopenharmony_cido_cancel (SHARP_Scanner * s) 2228141cc406Sopenharmony_ci{ 2229141cc406Sopenharmony_ci static u_char cmd[] = {READ, 0, 0, 0, 0, 2, 0, 0, 0, 0}; 2230141cc406Sopenharmony_ci 2231141cc406Sopenharmony_ci DBG (10, "<< do_cancel "); 2232141cc406Sopenharmony_ci 2233141cc406Sopenharmony_ci#ifdef USE_FORK 2234141cc406Sopenharmony_ci if (s->reader_pid > 0) 2235141cc406Sopenharmony_ci { 2236141cc406Sopenharmony_ci int exit_status; 2237141cc406Sopenharmony_ci int count = 0; 2238141cc406Sopenharmony_ci /* ensure child knows it's time to stop: */ 2239141cc406Sopenharmony_ci 2240141cc406Sopenharmony_ci DBG(11, "stopping reader process\n"); 2241141cc406Sopenharmony_ci s->rdr_ctl->cancel = 1; 2242141cc406Sopenharmony_ci while(reader_running(s) && count < 100) 2243141cc406Sopenharmony_ci { 2244141cc406Sopenharmony_ci usleep(100000); 2245141cc406Sopenharmony_ci count++; 2246141cc406Sopenharmony_ci }; 2247141cc406Sopenharmony_ci if (reader_running(s)) 2248141cc406Sopenharmony_ci { 2249141cc406Sopenharmony_ci /* be brutal... 2250141cc406Sopenharmony_ci !! The waiting time of 10 seconds might be far too short 2251141cc406Sopenharmony_ci !! if the resolution limit of the JX 250 is increased to 2252141cc406Sopenharmony_ci !! to more than 400 dpi: for these (interpolated) resolutions, 2253141cc406Sopenharmony_ci !! the JX 250 is awfully slow. 2254141cc406Sopenharmony_ci */ 2255141cc406Sopenharmony_ci kill(s->reader_pid, SIGKILL); 2256141cc406Sopenharmony_ci } 2257141cc406Sopenharmony_ci wait(&exit_status); 2258141cc406Sopenharmony_ci DBG(11, "reader process stopped\n"); 2259141cc406Sopenharmony_ci 2260141cc406Sopenharmony_ci s->reader_pid = 0; 2261141cc406Sopenharmony_ci } 2262141cc406Sopenharmony_ci 2263141cc406Sopenharmony_ci#endif 2264141cc406Sopenharmony_ci if (s->scanning == SANE_TRUE) 2265141cc406Sopenharmony_ci { 2266141cc406Sopenharmony_ci wait_ready(s->fd); 2267141cc406Sopenharmony_ci sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0); 2268141cc406Sopenharmony_ci /* if (s->adf_scan) */ 2269141cc406Sopenharmony_ci if ( s->dev->sensedat.model != JX610 2270141cc406Sopenharmony_ci && s->dev->sensedat.model != JX320) 2271141cc406Sopenharmony_ci object_position(s->fd, UNLOAD_PAPER); 2272141cc406Sopenharmony_ci } 2273141cc406Sopenharmony_ci 2274141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 2275141cc406Sopenharmony_ci 2276141cc406Sopenharmony_ci if (s->fd >= 0) 2277141cc406Sopenharmony_ci { 2278141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 2279141cc406Sopenharmony_ci s->fd = -1; 2280141cc406Sopenharmony_ci } 2281141cc406Sopenharmony_ci#ifdef USE_FORK 2282141cc406Sopenharmony_ci { 2283141cc406Sopenharmony_ci struct shmid_ds ds; 2284141cc406Sopenharmony_ci if (s->shmid != -1) 2285141cc406Sopenharmony_ci shmctl(s->shmid, IPC_RMID, &ds); 2286141cc406Sopenharmony_ci s->shmid = -1; 2287141cc406Sopenharmony_ci } 2288141cc406Sopenharmony_ci#endif 2289141cc406Sopenharmony_ci if (s->buffer) 2290141cc406Sopenharmony_ci free(s->buffer); 2291141cc406Sopenharmony_ci s->buffer = 0; 2292141cc406Sopenharmony_ci 2293141cc406Sopenharmony_ci DBG (10, ">>\n"); 2294141cc406Sopenharmony_ci return (SANE_STATUS_CANCELLED); 2295141cc406Sopenharmony_ci} 2296141cc406Sopenharmony_ci 2297141cc406Sopenharmony_cistatic SHARP_New_Device *new_devs = 0; 2298141cc406Sopenharmony_cistatic SHARP_New_Device *new_dev_pool = 0; 2299141cc406Sopenharmony_ci 2300141cc406Sopenharmony_cistatic SANE_Status 2301141cc406Sopenharmony_ciattach_and_list(const char *devnam) 2302141cc406Sopenharmony_ci{ 2303141cc406Sopenharmony_ci SANE_Status res; 2304141cc406Sopenharmony_ci SHARP_Device *devp; 2305141cc406Sopenharmony_ci SHARP_New_Device *np; 2306141cc406Sopenharmony_ci 2307141cc406Sopenharmony_ci res = attach(devnam, &devp); 2308141cc406Sopenharmony_ci if (res == SANE_STATUS_GOOD) 2309141cc406Sopenharmony_ci { 2310141cc406Sopenharmony_ci if (new_dev_pool) 2311141cc406Sopenharmony_ci { 2312141cc406Sopenharmony_ci np = new_dev_pool; 2313141cc406Sopenharmony_ci new_dev_pool = np->next; 2314141cc406Sopenharmony_ci } 2315141cc406Sopenharmony_ci else 2316141cc406Sopenharmony_ci { 2317141cc406Sopenharmony_ci np = malloc(sizeof(SHARP_New_Device)); 2318141cc406Sopenharmony_ci if (np == 0) 2319141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2320141cc406Sopenharmony_ci } 2321141cc406Sopenharmony_ci np->next =new_devs; 2322141cc406Sopenharmony_ci np->dev = devp; 2323141cc406Sopenharmony_ci new_devs = np; 2324141cc406Sopenharmony_ci } 2325141cc406Sopenharmony_ci return res; 2326141cc406Sopenharmony_ci} 2327141cc406Sopenharmony_ci 2328141cc406Sopenharmony_cistatic int buffers[2] = {DEFAULT_BUFFERS, DEFAULT_BUFFERS}; 2329141cc406Sopenharmony_cistatic int bufsize[2] = {DEFAULT_BUFSIZE, DEFAULT_BUFSIZE}; 2330141cc406Sopenharmony_cistatic int queued_reads[2] = {DEFAULT_QUEUED_READS, DEFAULT_QUEUED_READS}; 2331141cc406Sopenharmony_cistatic int stop_on_fsu_error[2] = {COMPLAIN_ON_FSU_ERROR | COMPLAIN_ON_ADF_ERROR, 2332141cc406Sopenharmony_ci COMPLAIN_ON_FSU_ERROR | COMPLAIN_ON_ADF_ERROR}; 2333141cc406Sopenharmony_cistatic int default_scan_mode[2] = {-1, -1}; 2334141cc406Sopenharmony_ci 2335141cc406Sopenharmony_ciSANE_Status 2336141cc406Sopenharmony_cisane_init (SANE_Int * version_code, 2337141cc406Sopenharmony_ci SANE_Auth_Callback __sane_unused__ authorize) 2338141cc406Sopenharmony_ci{ 2339141cc406Sopenharmony_ci char devnam[PATH_MAX] = "/dev/scanner"; 2340141cc406Sopenharmony_ci char line[PATH_MAX]; 2341141cc406Sopenharmony_ci const char *lp; 2342141cc406Sopenharmony_ci char *word; 2343141cc406Sopenharmony_ci char *end; 2344141cc406Sopenharmony_ci FILE *fp; 2345141cc406Sopenharmony_ci int opt_index = 0; 2346141cc406Sopenharmony_ci int linecount = 0; 2347141cc406Sopenharmony_ci#if 1 2348141cc406Sopenharmony_ci SHARP_Device sd; 2349141cc406Sopenharmony_ci SHARP_Device *dp = &sd; 2350141cc406Sopenharmony_ci#else 2351141cc406Sopenharmony_ci SHARP_Device *dp; 2352141cc406Sopenharmony_ci#endif 2353141cc406Sopenharmony_ci SHARP_New_Device *np; 2354141cc406Sopenharmony_ci int i; 2355141cc406Sopenharmony_ci 2356141cc406Sopenharmony_ci DBG_INIT (); 2357141cc406Sopenharmony_ci DBG (10, "<< sane_init "); 2358141cc406Sopenharmony_ci 2359141cc406Sopenharmony_ci#if defined PACKAGE && defined VERSION 2360141cc406Sopenharmony_ci DBG (2, "sane_init: " PACKAGE " " VERSION "\n"); 2361141cc406Sopenharmony_ci#endif 2362141cc406Sopenharmony_ci 2363141cc406Sopenharmony_ci if (version_code) 2364141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 2365141cc406Sopenharmony_ci 2366141cc406Sopenharmony_ci fp = sanei_config_open (SHARP_CONFIG_FILE); 2367141cc406Sopenharmony_ci if (!fp) 2368141cc406Sopenharmony_ci { 2369141cc406Sopenharmony_ci /* use "/dev/scanner" as the default device name if no 2370141cc406Sopenharmony_ci config file is available 2371141cc406Sopenharmony_ci */ 2372141cc406Sopenharmony_ci attach (devnam, &dp); 2373141cc406Sopenharmony_ci /* make sure that there are at least two buffers */ 2374141cc406Sopenharmony_ci if (DEFAULT_BUFFERS < 2) 2375141cc406Sopenharmony_ci dp->info.buffers = DEFAULT_BUFFERS; 2376141cc406Sopenharmony_ci else 2377141cc406Sopenharmony_ci dp->info.buffers = 2; 2378141cc406Sopenharmony_ci dp->info.wanted_bufsize = DEFAULT_BUFSIZE; 2379141cc406Sopenharmony_ci dp->info.queued_reads = DEFAULT_QUEUED_READS; 2380141cc406Sopenharmony_ci dp->info.complain_on_errors = COMPLAIN_ON_ADF_ERROR | COMPLAIN_ON_FSU_ERROR; 2381141cc406Sopenharmony_ci dp->info.default_scan_mode = -1; 2382141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2383141cc406Sopenharmony_ci } 2384141cc406Sopenharmony_ci 2385141cc406Sopenharmony_ci while (fgets(line, PATH_MAX, fp)) 2386141cc406Sopenharmony_ci { 2387141cc406Sopenharmony_ci linecount++; 2388141cc406Sopenharmony_ci word = 0; 2389141cc406Sopenharmony_ci lp = sanei_config_get_string(line, &word); 2390141cc406Sopenharmony_ci if (word) 2391141cc406Sopenharmony_ci { 2392141cc406Sopenharmony_ci if (word[0] != '#') 2393141cc406Sopenharmony_ci { 2394141cc406Sopenharmony_ci if (strcmp(word, "option") == 0) 2395141cc406Sopenharmony_ci { 2396141cc406Sopenharmony_ci free(word); 2397141cc406Sopenharmony_ci word = 0; 2398141cc406Sopenharmony_ci lp = sanei_config_get_string(lp, &word); 2399141cc406Sopenharmony_ci if (strcmp(word, "buffers") == 0) 2400141cc406Sopenharmony_ci { 2401141cc406Sopenharmony_ci free(word); 2402141cc406Sopenharmony_ci word = 0; 2403141cc406Sopenharmony_ci sanei_config_get_string(lp, &word); 2404141cc406Sopenharmony_ci i = strtol(word, &end, 0); 2405141cc406Sopenharmony_ci if (end == word) 2406141cc406Sopenharmony_ci { 2407141cc406Sopenharmony_ci DBG(1, "error in config file, line %i: number expected:\n", 2408141cc406Sopenharmony_ci linecount); 2409141cc406Sopenharmony_ci DBG(1, "%s\n", line); 2410141cc406Sopenharmony_ci } 2411141cc406Sopenharmony_ci else 2412141cc406Sopenharmony_ci if (i > 2) 2413141cc406Sopenharmony_ci buffers[opt_index] = i; 2414141cc406Sopenharmony_ci else 2415141cc406Sopenharmony_ci buffers[opt_index] = 2; 2416141cc406Sopenharmony_ci } 2417141cc406Sopenharmony_ci else if (strcmp(word, "buffersize") == 0) 2418141cc406Sopenharmony_ci { 2419141cc406Sopenharmony_ci free(word); 2420141cc406Sopenharmony_ci word = 0; 2421141cc406Sopenharmony_ci sanei_config_get_string(lp, &word); 2422141cc406Sopenharmony_ci i = strtol(word, &end, 0); 2423141cc406Sopenharmony_ci if (word == end) 2424141cc406Sopenharmony_ci { 2425141cc406Sopenharmony_ci DBG(1, "error in config file, line %i: number expected:\n", 2426141cc406Sopenharmony_ci linecount); 2427141cc406Sopenharmony_ci DBG(1, "%s\n", line); 2428141cc406Sopenharmony_ci } 2429141cc406Sopenharmony_ci else 2430141cc406Sopenharmony_ci bufsize[opt_index] = i; 2431141cc406Sopenharmony_ci } 2432141cc406Sopenharmony_ci else if (strcmp(word, "readqueue") == 0) 2433141cc406Sopenharmony_ci { 2434141cc406Sopenharmony_ci free(word); 2435141cc406Sopenharmony_ci word = 0; 2436141cc406Sopenharmony_ci sanei_config_get_string(lp, &word); 2437141cc406Sopenharmony_ci i = strtol(word, &end, 0); 2438141cc406Sopenharmony_ci if (word == end) 2439141cc406Sopenharmony_ci { 2440141cc406Sopenharmony_ci DBG(1, "error in config file, line %i: number expected:\n", 2441141cc406Sopenharmony_ci linecount); 2442141cc406Sopenharmony_ci DBG(1, "%s\n", line); 2443141cc406Sopenharmony_ci } 2444141cc406Sopenharmony_ci else 2445141cc406Sopenharmony_ci queued_reads[opt_index] = i; 2446141cc406Sopenharmony_ci } 2447141cc406Sopenharmony_ci else if (strcmp(word, "stop_on_fsu_error") == 0) 2448141cc406Sopenharmony_ci { 2449141cc406Sopenharmony_ci free(word); 2450141cc406Sopenharmony_ci word = 0; 2451141cc406Sopenharmony_ci sanei_config_get_string(lp, &word); 2452141cc406Sopenharmony_ci i = strtol(word, &end, 0); 2453141cc406Sopenharmony_ci if (word == end) 2454141cc406Sopenharmony_ci { 2455141cc406Sopenharmony_ci DBG(1, "error in config file, line %i: number expected:\n", 2456141cc406Sopenharmony_ci linecount); 2457141cc406Sopenharmony_ci DBG(1, "%s\n", line); 2458141cc406Sopenharmony_ci } 2459141cc406Sopenharmony_ci else 2460141cc406Sopenharmony_ci stop_on_fsu_error[opt_index] 2461141cc406Sopenharmony_ci = i ? COMPLAIN_ON_FSU_ERROR : 0; 2462141cc406Sopenharmony_ci } 2463141cc406Sopenharmony_ci else if (strcmp(word, "default_scan_source") == 0) 2464141cc406Sopenharmony_ci { 2465141cc406Sopenharmony_ci free(word); 2466141cc406Sopenharmony_ci word = 0; 2467141cc406Sopenharmony_ci sanei_config_get_string(lp, &word); 2468141cc406Sopenharmony_ci if (strcmp(word, "auto") == 0) 2469141cc406Sopenharmony_ci default_scan_mode[opt_index] = -1; 2470141cc406Sopenharmony_ci else if (strcmp(word, "fsu") == 0) 2471141cc406Sopenharmony_ci default_scan_mode[opt_index] = SCAN_WITH_FSU; 2472141cc406Sopenharmony_ci else if (strcmp(word, "adf") == 0) 2473141cc406Sopenharmony_ci default_scan_mode[opt_index] = SCAN_WITH_ADF; 2474141cc406Sopenharmony_ci else if (strcmp(word, "flatbed") == 0) 2475141cc406Sopenharmony_ci default_scan_mode[opt_index] = SCAN_SIMPLE; 2476141cc406Sopenharmony_ci else 2477141cc406Sopenharmony_ci { 2478141cc406Sopenharmony_ci DBG(1, "error in config file, line %i: number expected:\n", 2479141cc406Sopenharmony_ci linecount); 2480141cc406Sopenharmony_ci DBG(1, "%s\n", line); 2481141cc406Sopenharmony_ci } 2482141cc406Sopenharmony_ci } 2483141cc406Sopenharmony_ci else 2484141cc406Sopenharmony_ci { 2485141cc406Sopenharmony_ci DBG(1, "error in config file, line %i: unknown option\n", 2486141cc406Sopenharmony_ci linecount); 2487141cc406Sopenharmony_ci DBG(1, "%s\n", line); 2488141cc406Sopenharmony_ci } 2489141cc406Sopenharmony_ci } 2490141cc406Sopenharmony_ci else 2491141cc406Sopenharmony_ci { 2492141cc406Sopenharmony_ci while (new_devs) 2493141cc406Sopenharmony_ci { 2494141cc406Sopenharmony_ci if (buffers[1] >= 2) 2495141cc406Sopenharmony_ci new_devs->dev->info.buffers = buffers[1]; 2496141cc406Sopenharmony_ci else 2497141cc406Sopenharmony_ci new_devs->dev->info.buffers = 2; 2498141cc406Sopenharmony_ci if (bufsize[1] > 0) 2499141cc406Sopenharmony_ci new_devs->dev->info.wanted_bufsize = bufsize[1]; 2500141cc406Sopenharmony_ci else 2501141cc406Sopenharmony_ci new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE; 2502141cc406Sopenharmony_ci if (queued_reads[1] >= 0) 2503141cc406Sopenharmony_ci new_devs->dev->info.queued_reads = queued_reads[1]; 2504141cc406Sopenharmony_ci else 2505141cc406Sopenharmony_ci new_devs->dev->info.queued_reads = 0; 2506141cc406Sopenharmony_ci new_devs->dev->info.complain_on_errors = stop_on_fsu_error[1]; 2507141cc406Sopenharmony_ci new_devs->dev->info.default_scan_mode = default_scan_mode[1]; 2508141cc406Sopenharmony_ci np = new_devs->next; 2509141cc406Sopenharmony_ci new_devs->next = new_dev_pool; 2510141cc406Sopenharmony_ci new_dev_pool = new_devs; 2511141cc406Sopenharmony_ci new_devs = np; 2512141cc406Sopenharmony_ci } 2513141cc406Sopenharmony_ci if (line[strlen(line)-1] == '\n') 2514141cc406Sopenharmony_ci line[strlen(line)-1] = 0; 2515141cc406Sopenharmony_ci sanei_config_attach_matching_devices(line, &attach_and_list); 2516141cc406Sopenharmony_ci buffers[1] = buffers[0]; 2517141cc406Sopenharmony_ci bufsize[1] = bufsize[0]; 2518141cc406Sopenharmony_ci queued_reads[1] = queued_reads[0]; 2519141cc406Sopenharmony_ci stop_on_fsu_error[1] = stop_on_fsu_error[0]; 2520141cc406Sopenharmony_ci default_scan_mode[1] = default_scan_mode[0]; 2521141cc406Sopenharmony_ci opt_index = 1; 2522141cc406Sopenharmony_ci } 2523141cc406Sopenharmony_ci } 2524141cc406Sopenharmony_ci if (word) free(word); 2525141cc406Sopenharmony_ci } 2526141cc406Sopenharmony_ci } 2527141cc406Sopenharmony_ci 2528141cc406Sopenharmony_ci while (new_devs) 2529141cc406Sopenharmony_ci { 2530141cc406Sopenharmony_ci if (buffers[1] >= 2) 2531141cc406Sopenharmony_ci new_devs->dev->info.buffers = buffers[1]; 2532141cc406Sopenharmony_ci else 2533141cc406Sopenharmony_ci new_devs->dev->info.buffers = 2; 2534141cc406Sopenharmony_ci if (bufsize[1] > 0) 2535141cc406Sopenharmony_ci new_devs->dev->info.wanted_bufsize = bufsize[1]; 2536141cc406Sopenharmony_ci else 2537141cc406Sopenharmony_ci new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE; 2538141cc406Sopenharmony_ci if (queued_reads[1] >= 0) 2539141cc406Sopenharmony_ci new_devs->dev->info.queued_reads = queued_reads[1]; 2540141cc406Sopenharmony_ci else 2541141cc406Sopenharmony_ci new_devs->dev->info.queued_reads = 0; 2542141cc406Sopenharmony_ci new_devs->dev->info.complain_on_errors = stop_on_fsu_error[1]; 2543141cc406Sopenharmony_ci new_devs->dev->info.default_scan_mode = default_scan_mode[1]; 2544141cc406Sopenharmony_ci if (line[strlen(line)-1] == '\n') 2545141cc406Sopenharmony_ci line[strlen(line)-1] = 0; 2546141cc406Sopenharmony_ci np = new_devs->next; 2547141cc406Sopenharmony_ci free(new_devs); 2548141cc406Sopenharmony_ci new_devs = np; 2549141cc406Sopenharmony_ci } 2550141cc406Sopenharmony_ci while (new_dev_pool) 2551141cc406Sopenharmony_ci { 2552141cc406Sopenharmony_ci np = new_dev_pool->next; 2553141cc406Sopenharmony_ci free(new_dev_pool); 2554141cc406Sopenharmony_ci new_dev_pool = np; 2555141cc406Sopenharmony_ci } 2556141cc406Sopenharmony_ci fclose(fp); 2557141cc406Sopenharmony_ci DBG (10, "sane_init >>\n"); 2558141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2559141cc406Sopenharmony_ci} 2560141cc406Sopenharmony_ci 2561141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 2562141cc406Sopenharmony_civoid 2563141cc406Sopenharmony_cisane_exit (void) 2564141cc406Sopenharmony_ci{ 2565141cc406Sopenharmony_ci SHARP_Device *dev, *next; 2566141cc406Sopenharmony_ci DBG (10, "<< sane_exit "); 2567141cc406Sopenharmony_ci 2568141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 2569141cc406Sopenharmony_ci { 2570141cc406Sopenharmony_ci next = dev->next; 2571141cc406Sopenharmony_ci free ((void *) dev->sane.name); 2572141cc406Sopenharmony_ci free ((void *) dev->sane.model); 2573141cc406Sopenharmony_ci free (dev); 2574141cc406Sopenharmony_ci } 2575141cc406Sopenharmony_ci 2576141cc406Sopenharmony_ci if (devlist) 2577141cc406Sopenharmony_ci free(devlist); 2578141cc406Sopenharmony_ci devlist = 0; 2579141cc406Sopenharmony_ci first_dev = 0; 2580141cc406Sopenharmony_ci 2581141cc406Sopenharmony_ci DBG (10, ">>\n"); 2582141cc406Sopenharmony_ci} 2583141cc406Sopenharmony_ci 2584141cc406Sopenharmony_ciSANE_Status 2585141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, 2586141cc406Sopenharmony_ci SANE_Bool __sane_unused__ local_only) 2587141cc406Sopenharmony_ci{ 2588141cc406Sopenharmony_ci SHARP_Device *dev; 2589141cc406Sopenharmony_ci int i; 2590141cc406Sopenharmony_ci DBG (10, "<< sane_get_devices "); 2591141cc406Sopenharmony_ci 2592141cc406Sopenharmony_ci if (devlist) 2593141cc406Sopenharmony_ci free (devlist); 2594141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 2595141cc406Sopenharmony_ci if (!devlist) 2596141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 2597141cc406Sopenharmony_ci 2598141cc406Sopenharmony_ci i = 0; 2599141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 2600141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 2601141cc406Sopenharmony_ci devlist[i++] = 0; 2602141cc406Sopenharmony_ci 2603141cc406Sopenharmony_ci *device_list = devlist; 2604141cc406Sopenharmony_ci 2605141cc406Sopenharmony_ci DBG (10, ">>\n"); 2606141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2607141cc406Sopenharmony_ci} 2608141cc406Sopenharmony_ci 2609141cc406Sopenharmony_ciSANE_Status 2610141cc406Sopenharmony_cisane_open (SANE_String_Const devnam, SANE_Handle * handle) 2611141cc406Sopenharmony_ci{ 2612141cc406Sopenharmony_ci SANE_Status status; 2613141cc406Sopenharmony_ci SHARP_Device *dev; 2614141cc406Sopenharmony_ci SHARP_Scanner *s; 2615141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 2616141cc406Sopenharmony_ci int i, j; 2617141cc406Sopenharmony_ci#endif 2618141cc406Sopenharmony_ci 2619141cc406Sopenharmony_ci DBG (10, "<< sane_open "); 2620141cc406Sopenharmony_ci 2621141cc406Sopenharmony_ci if (devnam[0]) 2622141cc406Sopenharmony_ci { 2623141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 2624141cc406Sopenharmony_ci { 2625141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devnam) == 0) 2626141cc406Sopenharmony_ci break; 2627141cc406Sopenharmony_ci } 2628141cc406Sopenharmony_ci 2629141cc406Sopenharmony_ci if (!dev) 2630141cc406Sopenharmony_ci { 2631141cc406Sopenharmony_ci status = attach (devnam, &dev); 2632141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2633141cc406Sopenharmony_ci return (status); 2634141cc406Sopenharmony_ci dev->info.buffers = buffers[0]; 2635141cc406Sopenharmony_ci dev->info.wanted_bufsize = bufsize[0]; 2636141cc406Sopenharmony_ci dev->info.queued_reads = queued_reads[0]; 2637141cc406Sopenharmony_ci } 2638141cc406Sopenharmony_ci } 2639141cc406Sopenharmony_ci else 2640141cc406Sopenharmony_ci { 2641141cc406Sopenharmony_ci dev = first_dev; 2642141cc406Sopenharmony_ci } 2643141cc406Sopenharmony_ci 2644141cc406Sopenharmony_ci if (!dev) 2645141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2646141cc406Sopenharmony_ci 2647141cc406Sopenharmony_ci s = malloc (sizeof (*s)); 2648141cc406Sopenharmony_ci if (!s) 2649141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2650141cc406Sopenharmony_ci memset (s, 0, sizeof (*s)); 2651141cc406Sopenharmony_ci 2652141cc406Sopenharmony_ci s->fd = -1; 2653141cc406Sopenharmony_ci s->dev = dev; 2654141cc406Sopenharmony_ci 2655141cc406Sopenharmony_ci s->buffer = 0; 2656141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 2657141cc406Sopenharmony_ci for (i = 0; i < 4; ++i) 2658141cc406Sopenharmony_ci for (j = 0; j < 256; ++j) 2659141cc406Sopenharmony_ci s->gamma_table[i][j] = j; 2660141cc406Sopenharmony_ci#endif 2661141cc406Sopenharmony_ci status = init_options (s); 2662141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2663141cc406Sopenharmony_ci { 2664141cc406Sopenharmony_ci /* xxx clean up mallocs */ 2665141cc406Sopenharmony_ci return status; 2666141cc406Sopenharmony_ci } 2667141cc406Sopenharmony_ci 2668141cc406Sopenharmony_ci s->next = first_handle; 2669141cc406Sopenharmony_ci first_handle = s; 2670141cc406Sopenharmony_ci 2671141cc406Sopenharmony_ci *handle = s; 2672141cc406Sopenharmony_ci 2673141cc406Sopenharmony_ci DBG (10, ">>\n"); 2674141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2675141cc406Sopenharmony_ci} 2676141cc406Sopenharmony_ci 2677141cc406Sopenharmony_civoid 2678141cc406Sopenharmony_cisane_close (SANE_Handle handle) 2679141cc406Sopenharmony_ci{ 2680141cc406Sopenharmony_ci SHARP_Scanner *s = (SHARP_Scanner *) handle; 2681141cc406Sopenharmony_ci DBG (10, "<< sane_close "); 2682141cc406Sopenharmony_ci 2683141cc406Sopenharmony_ci if (s->fd != -1) 2684141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 2685141cc406Sopenharmony_ci#ifdef USE_FORK 2686141cc406Sopenharmony_ci { 2687141cc406Sopenharmony_ci struct shmid_ds ds; 2688141cc406Sopenharmony_ci if (s->shmid != -1) 2689141cc406Sopenharmony_ci shmctl(s->shmid, IPC_RMID, &ds); 2690141cc406Sopenharmony_ci } 2691141cc406Sopenharmony_ci#endif 2692141cc406Sopenharmony_ci if (s->buffer) 2693141cc406Sopenharmony_ci free(s->buffer); 2694141cc406Sopenharmony_ci free (s); 2695141cc406Sopenharmony_ci 2696141cc406Sopenharmony_ci DBG (10, ">>\n"); 2697141cc406Sopenharmony_ci} 2698141cc406Sopenharmony_ci 2699141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 2700141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 2701141cc406Sopenharmony_ci{ 2702141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 2703141cc406Sopenharmony_ci DBG (10, "<< sane_get_option_descriptor "); 2704141cc406Sopenharmony_ci 2705141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 2706141cc406Sopenharmony_ci return (0); 2707141cc406Sopenharmony_ci 2708141cc406Sopenharmony_ci DBG (10, ">>\n"); 2709141cc406Sopenharmony_ci return (s->opt + option); 2710141cc406Sopenharmony_ci} 2711141cc406Sopenharmony_ci 2712141cc406Sopenharmony_ciSANE_Status 2713141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 2714141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 2715141cc406Sopenharmony_ci{ 2716141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 2717141cc406Sopenharmony_ci SANE_Status status; 2718141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 2719141cc406Sopenharmony_ci SANE_Word w, cap; 2720141cc406Sopenharmony_ci#else 2721141cc406Sopenharmony_ci SANE_Word cap; 2722141cc406Sopenharmony_ci#endif 2723141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST 2724141cc406Sopenharmony_ci int i; 2725141cc406Sopenharmony_ci#endif 2726141cc406Sopenharmony_ci int range_index; 2727141cc406Sopenharmony_ci DBG (10, "<< sane_control_option %i", option); 2728141cc406Sopenharmony_ci 2729141cc406Sopenharmony_ci if (info) 2730141cc406Sopenharmony_ci *info = 0; 2731141cc406Sopenharmony_ci 2732141cc406Sopenharmony_ci if (s->scanning) 2733141cc406Sopenharmony_ci return (SANE_STATUS_DEVICE_BUSY); 2734141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) 2735141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2736141cc406Sopenharmony_ci 2737141cc406Sopenharmony_ci cap = s->opt[option].cap; 2738141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 2739141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2740141cc406Sopenharmony_ci 2741141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 2742141cc406Sopenharmony_ci { 2743141cc406Sopenharmony_ci switch (option) 2744141cc406Sopenharmony_ci { 2745141cc406Sopenharmony_ci /* word options: */ 2746141cc406Sopenharmony_ci case OPT_X_RESOLUTION: 2747141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION 2748141cc406Sopenharmony_ci case OPT_Y_RESOLUTION: 2749141cc406Sopenharmony_ci#endif 2750141cc406Sopenharmony_ci case OPT_TL_X: 2751141cc406Sopenharmony_ci case OPT_TL_Y: 2752141cc406Sopenharmony_ci case OPT_BR_X: 2753141cc406Sopenharmony_ci case OPT_BR_Y: 2754141cc406Sopenharmony_ci case OPT_NUM_OPTS: 2755141cc406Sopenharmony_ci case OPT_THRESHOLD: 2756141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 2757141cc406Sopenharmony_ci case OPT_THRESHOLD_R: 2758141cc406Sopenharmony_ci case OPT_THRESHOLD_G: 2759141cc406Sopenharmony_ci case OPT_THRESHOLD_B: 2760141cc406Sopenharmony_ci#endif 2761141cc406Sopenharmony_ci case OPT_SPEED: 2762141cc406Sopenharmony_ci case OPT_PREVIEW: 2763141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 2764141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 2765141cc406Sopenharmony_ci#endif 2766141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 2767141cc406Sopenharmony_ci#if 0 /* here, values are read; reload should not be necessary */ 2768141cc406Sopenharmony_ci if (info) 2769141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 2770141cc406Sopenharmony_ci#endif 2771141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2772141cc406Sopenharmony_ci 2773141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 2774141cc406Sopenharmony_ci /* word-array options: */ 2775141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 2776141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 2777141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 2778141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 2779141cc406Sopenharmony_ci memcpy (val, s->val[option].wa, s->opt[option].size); 2780141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2781141cc406Sopenharmony_ci#endif 2782141cc406Sopenharmony_ci 2783141cc406Sopenharmony_ci /* string options: */ 2784141cc406Sopenharmony_ci case OPT_MODE: 2785141cc406Sopenharmony_ci case OPT_HALFTONE: 2786141cc406Sopenharmony_ci case OPT_PAPER: 2787141cc406Sopenharmony_ci case OPT_GAMMA: 2788141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST 2789141cc406Sopenharmony_ci case OPT_RESOLUTION_LIST: 2790141cc406Sopenharmony_ci#endif 2791141cc406Sopenharmony_ci case OPT_EDGE_EMPHASIS: 2792141cc406Sopenharmony_ci case OPT_LIGHTCOLOR: 2793141cc406Sopenharmony_ci case OPT_SCANSOURCE: 2794141cc406Sopenharmony_ci strcpy (val, s->val[option].s); 2795141cc406Sopenharmony_ci#if 0 2796141cc406Sopenharmony_ci if (info) 2797141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 2798141cc406Sopenharmony_ci#endif 2799141cc406Sopenharmony_ci 2800141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2801141cc406Sopenharmony_ci 2802141cc406Sopenharmony_ci } 2803141cc406Sopenharmony_ci } 2804141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 2805141cc406Sopenharmony_ci { 2806141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 2807141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2808141cc406Sopenharmony_ci 2809141cc406Sopenharmony_ci status = sanei_constrain_value (s->opt + option, val, info); 2810141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2811141cc406Sopenharmony_ci return status; 2812141cc406Sopenharmony_ci 2813141cc406Sopenharmony_ci switch (option) 2814141cc406Sopenharmony_ci { 2815141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 2816141cc406Sopenharmony_ci case OPT_X_RESOLUTION: 2817141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION 2818141cc406Sopenharmony_ci case OPT_Y_RESOLUTION: 2819141cc406Sopenharmony_ci#endif 2820141cc406Sopenharmony_ci case OPT_TL_X: 2821141cc406Sopenharmony_ci case OPT_TL_Y: 2822141cc406Sopenharmony_ci case OPT_BR_X: 2823141cc406Sopenharmony_ci case OPT_BR_Y: 2824141cc406Sopenharmony_ci if (info && s->val[option].w != *(SANE_Word *) val) 2825141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 2826141cc406Sopenharmony_ci // fall through 2827141cc406Sopenharmony_ci case OPT_NUM_OPTS: 2828141cc406Sopenharmony_ci case OPT_THRESHOLD: 2829141cc406Sopenharmony_ci /* xxx theoretically, we could use OPT_THRESHOLD in 2830141cc406Sopenharmony_ci bi-level color mode to adjust all three other 2831141cc406Sopenharmony_ci threshold together. But this would require to set 2832141cc406Sopenharmony_ci the bit SANE_INFO_RELOAD_OPTIONS in *info, and that 2833141cc406Sopenharmony_ci would unfortunately cause a crash in both xscanimage 2834141cc406Sopenharmony_ci and xsane... Therefore, OPT_THRESHOLD is disabled 2835141cc406Sopenharmony_ci for bi-level color scan right now. 2836141cc406Sopenharmony_ci */ 2837141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 2838141cc406Sopenharmony_ci case OPT_THRESHOLD_R: 2839141cc406Sopenharmony_ci case OPT_THRESHOLD_G: 2840141cc406Sopenharmony_ci case OPT_THRESHOLD_B: 2841141cc406Sopenharmony_ci#endif 2842141cc406Sopenharmony_ci case OPT_SPEED: 2843141cc406Sopenharmony_ci case OPT_PREVIEW: 2844141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 2845141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2846141cc406Sopenharmony_ci 2847141cc406Sopenharmony_ci 2848141cc406Sopenharmony_ci case OPT_MODE: 2849141cc406Sopenharmony_ci if (strcmp (val, M_LINEART) == 0) 2850141cc406Sopenharmony_ci { 2851141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 2852141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 2853141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; 2854141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; 2855141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; 2856141cc406Sopenharmony_ci#endif 2857141cc406Sopenharmony_ci if (s->dev->sensedat.model == JX330) 2858141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; 2859141cc406Sopenharmony_ci } 2860141cc406Sopenharmony_ci else if (strcmp (val, M_LINEART_COLOR) == 0) 2861141cc406Sopenharmony_ci { 2862141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2863141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 2864141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].cap &= ~SANE_CAP_INACTIVE; 2865141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].cap &= ~SANE_CAP_INACTIVE; 2866141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].cap &= ~SANE_CAP_INACTIVE; 2867141cc406Sopenharmony_ci#endif 2868141cc406Sopenharmony_ci if (s->dev->sensedat.model == JX330) 2869141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; 2870141cc406Sopenharmony_ci } 2871141cc406Sopenharmony_ci else 2872141cc406Sopenharmony_ci { 2873141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2874141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 2875141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; 2876141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; 2877141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; 2878141cc406Sopenharmony_ci#endif 2879141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 2880141cc406Sopenharmony_ci } 2881141cc406Sopenharmony_ci 2882141cc406Sopenharmony_ci if ( strcmp (val, M_LINEART) == 0 2883141cc406Sopenharmony_ci || strcmp (val, M_GRAY) == 0) 2884141cc406Sopenharmony_ci { 2885141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].cap &= ~SANE_CAP_INACTIVE; 2886141cc406Sopenharmony_ci } 2887141cc406Sopenharmony_ci else 2888141cc406Sopenharmony_ci { 2889141cc406Sopenharmony_ci s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; 2890141cc406Sopenharmony_ci } 2891141cc406Sopenharmony_ci 2892141cc406Sopenharmony_ci strcpy(s->val[option].s, val); 2893141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 2894141cc406Sopenharmony_ci set_gamma_caps(s); 2895141cc406Sopenharmony_ci#endif 2896141cc406Sopenharmony_ci if (info) 2897141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2898141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2899141cc406Sopenharmony_ci 2900141cc406Sopenharmony_ci case OPT_GAMMA: 2901141cc406Sopenharmony_ci case OPT_HALFTONE: 2902141cc406Sopenharmony_ci case OPT_EDGE_EMPHASIS: 2903141cc406Sopenharmony_ci case OPT_LIGHTCOLOR: 2904141cc406Sopenharmony_ci#if 0 2905141cc406Sopenharmony_ci if (s->val[option].s) 2906141cc406Sopenharmony_ci free (s->val[option].s); 2907141cc406Sopenharmony_ci s->val[option].s = strdup (val); 2908141cc406Sopenharmony_ci#endif 2909141cc406Sopenharmony_ci strcpy(s->val[option].s, val); 2910141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2911141cc406Sopenharmony_ci 2912141cc406Sopenharmony_ci case OPT_SCANSOURCE: 2913141cc406Sopenharmony_ci if (info && strcmp (s->val[option].s, (SANE_String) val)) 2914141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2915141cc406Sopenharmony_ci#if 0 2916141cc406Sopenharmony_ci if (s->val[option].s) 2917141cc406Sopenharmony_ci free (s->val[option].s); 2918141cc406Sopenharmony_ci s->val[option].s = strdup (val); 2919141cc406Sopenharmony_ci#endif 2920141cc406Sopenharmony_ci strcpy(s->val[option].s, val); 2921141cc406Sopenharmony_ci if (strcmp(val, use_fsu) == 0) 2922141cc406Sopenharmony_ci range_index = SCAN_WITH_FSU; 2923141cc406Sopenharmony_ci else if (strcmp(val, use_adf) == 0) 2924141cc406Sopenharmony_ci range_index = SCAN_WITH_ADF; 2925141cc406Sopenharmony_ci else 2926141cc406Sopenharmony_ci range_index = SCAN_SIMPLE; 2927141cc406Sopenharmony_ci 2928141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range 2929141cc406Sopenharmony_ci = &s->dev->info.tl_x_ranges[range_index]; 2930141cc406Sopenharmony_ci clip_value (&s->opt[OPT_TL_X], &s->val[OPT_TL_X].w); 2931141cc406Sopenharmony_ci 2932141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range 2933141cc406Sopenharmony_ci = &s->dev->info.tl_y_ranges[range_index]; 2934141cc406Sopenharmony_ci clip_value (&s->opt[OPT_TL_Y], &s->val[OPT_TL_Y].w); 2935141cc406Sopenharmony_ci 2936141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range 2937141cc406Sopenharmony_ci = &s->dev->info.br_x_ranges[range_index]; 2938141cc406Sopenharmony_ci clip_value (&s->opt[OPT_BR_X], &s->val[OPT_BR_X].w); 2939141cc406Sopenharmony_ci 2940141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range 2941141cc406Sopenharmony_ci = &s->dev->info.br_y_ranges[range_index]; 2942141cc406Sopenharmony_ci clip_value (&s->opt[OPT_BR_Y], &s->val[OPT_BR_Y].w); 2943141cc406Sopenharmony_ci 2944141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2945141cc406Sopenharmony_ci 2946141cc406Sopenharmony_ci case OPT_PAPER: 2947141cc406Sopenharmony_ci if (info) 2948141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2949141cc406Sopenharmony_ci#if 0 2950141cc406Sopenharmony_ci if (s->val[option].s) 2951141cc406Sopenharmony_ci free (s->val[option].s); 2952141cc406Sopenharmony_ci s->val[option].s = strdup (val); 2953141cc406Sopenharmony_ci#endif 2954141cc406Sopenharmony_ci strcpy(s->val[option].s, val); 2955141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX(0); 2956141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX(0); 2957141cc406Sopenharmony_ci if (strcmp (s->val[option].s, "A3") == 0){ 2958141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(297); 2959141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(420); 2960141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, "A4") == 0){ 2961141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(210); 2962141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(297); 2963141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, "A5") == 0){ 2964141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(148.5); 2965141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(210); 2966141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, "A6") == 0){ 2967141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(105); 2968141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(148.5); 2969141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, "B4") == 0){ 2970141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(250); 2971141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(353); 2972141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, "B5") == 0){ 2973141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(182); 2974141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(257); 2975141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, W_LETTER) == 0){ 2976141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(279.4); 2977141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(431.8); 2978141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, "Legal") == 0){ 2979141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(215.9); 2980141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(355.6); 2981141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, "Letter") == 0){ 2982141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(215.9); 2983141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(279.4); 2984141cc406Sopenharmony_ci }else if (strcmp (s->val[option].s, INVOICE) == 0){ 2985141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(215.9); 2986141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(139.7); 2987141cc406Sopenharmony_ci }else{ 2988141cc406Sopenharmony_ci } 2989141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 2990141cc406Sopenharmony_ci 2991141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST 2992141cc406Sopenharmony_ci case OPT_RESOLUTION_LIST: 2993141cc406Sopenharmony_ci if (info) 2994141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2995141cc406Sopenharmony_ci for (i = 0; s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]; i++) { 2996141cc406Sopenharmony_ci if (strcmp (val, 2997141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]) == 0){ 2998141cc406Sopenharmony_ci s->val[OPT_X_RESOLUTION].w 2999141cc406Sopenharmony_ci = atoi(s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]); 3000141cc406Sopenharmony_ci s->val[OPT_Y_RESOLUTION].w 3001141cc406Sopenharmony_ci = atoi(s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]); 3002141cc406Sopenharmony_ci if (info) 3003141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3004141cc406Sopenharmony_ci break; 3005141cc406Sopenharmony_ci } 3006141cc406Sopenharmony_ci } 3007141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3008141cc406Sopenharmony_ci#endif 3009141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 3010141cc406Sopenharmony_ci /* side-effect-free word-array options: */ 3011141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 3012141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3013141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3014141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3015141cc406Sopenharmony_ci memcpy (s->val[option].wa, val, s->opt[option].size); 3016141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3017141cc406Sopenharmony_ci 3018141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 3019141cc406Sopenharmony_ci w = *(SANE_Word *) val; 3020141cc406Sopenharmony_ci 3021141cc406Sopenharmony_ci if (w == s->val[OPT_CUSTOM_GAMMA].w) 3022141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 3023141cc406Sopenharmony_ci 3024141cc406Sopenharmony_ci if (info) 3025141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3026141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = w; 3027141cc406Sopenharmony_ci set_gamma_caps(s); 3028141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3029141cc406Sopenharmony_ci#endif 3030141cc406Sopenharmony_ci } 3031141cc406Sopenharmony_ci } 3032141cc406Sopenharmony_ci 3033141cc406Sopenharmony_ci DBG (10, ">>\n"); 3034141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 3035141cc406Sopenharmony_ci} 3036141cc406Sopenharmony_ci 3037141cc406Sopenharmony_ciSANE_Status 3038141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 3039141cc406Sopenharmony_ci{ 3040141cc406Sopenharmony_ci int width, length, xres, yres; 3041141cc406Sopenharmony_ci const char *mode; 3042141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 3043141cc406Sopenharmony_ci DBG (10, "<< sane_get_parameters "); 3044141cc406Sopenharmony_ci 3045141cc406Sopenharmony_ci xres = s->val[OPT_X_RESOLUTION].w; 3046141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION 3047141cc406Sopenharmony_ci yres = s->val[OPT_Y_RESOLUTION].w; 3048141cc406Sopenharmony_ci#else 3049141cc406Sopenharmony_ci yres = xres; 3050141cc406Sopenharmony_ci#endif 3051141cc406Sopenharmony_ci if (!s->scanning) 3052141cc406Sopenharmony_ci { 3053141cc406Sopenharmony_ci /* make best-effort guess at what parameters will look like once 3054141cc406Sopenharmony_ci scanning starts. */ 3055141cc406Sopenharmony_ci memset (&s->params, 0, sizeof (s->params)); 3056141cc406Sopenharmony_ci 3057141cc406Sopenharmony_ci width = MM_TO_PIX( SANE_UNFIX(s->val[OPT_BR_X].w) 3058141cc406Sopenharmony_ci - SANE_UNFIX(s->val[OPT_TL_X].w), 3059141cc406Sopenharmony_ci s->dev->info.mud); 3060141cc406Sopenharmony_ci length = MM_TO_PIX( SANE_UNFIX(s->val[OPT_BR_Y].w) 3061141cc406Sopenharmony_ci - SANE_UNFIX(s->val[OPT_TL_Y].w), 3062141cc406Sopenharmony_ci s->dev->info.mud); 3063141cc406Sopenharmony_ci 3064141cc406Sopenharmony_ci s->width = width; 3065141cc406Sopenharmony_ci s->length = length; 3066141cc406Sopenharmony_ci s->params.pixels_per_line = width * xres / s->dev->info.mud; 3067141cc406Sopenharmony_ci s->params.lines = length * yres / s->dev->info.mud; 3068141cc406Sopenharmony_ci s->unscanned_lines = s->params.lines; 3069141cc406Sopenharmony_ci } 3070141cc406Sopenharmony_ci else 3071141cc406Sopenharmony_ci { 3072141cc406Sopenharmony_ci static u_char cmd[] = {READ, 0, 0x81, 0, 0, 0, 0, 0, 4, 0}; 3073141cc406Sopenharmony_ci static u_char buf[4]; 3074141cc406Sopenharmony_ci size_t len = 4; 3075141cc406Sopenharmony_ci SANE_Status status; 3076141cc406Sopenharmony_ci 3077141cc406Sopenharmony_ci /* if async reads are used, )ie. if USE_FORK is defined, 3078141cc406Sopenharmony_ci this command may only be issued immediately after the 3079141cc406Sopenharmony_ci "start scan" command. Later calls will confuse the 3080141cc406Sopenharmony_ci read queue. 3081141cc406Sopenharmony_ci */ 3082141cc406Sopenharmony_ci if (!s->get_params_called) 3083141cc406Sopenharmony_ci { 3084141cc406Sopenharmony_ci wait_ready(s->fd); 3085141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), buf, &len); 3086141cc406Sopenharmony_ci 3087141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3088141cc406Sopenharmony_ci { 3089141cc406Sopenharmony_ci do_cancel(s); 3090141cc406Sopenharmony_ci return (status); 3091141cc406Sopenharmony_ci } 3092141cc406Sopenharmony_ci s->params.pixels_per_line = (buf[1] << 8) + buf[0]; 3093141cc406Sopenharmony_ci s->params.lines = (buf[3] << 8) + buf[2]; 3094141cc406Sopenharmony_ci s->get_params_called = 1; 3095141cc406Sopenharmony_ci } 3096141cc406Sopenharmony_ci } 3097141cc406Sopenharmony_ci 3098141cc406Sopenharmony_ci xres = s->val[OPT_X_RESOLUTION].w; 3099141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION 3100141cc406Sopenharmony_ci yres = s->val[OPT_Y_RESOLUTION].w; 3101141cc406Sopenharmony_ci#else 3102141cc406Sopenharmony_ci yres = xres; 3103141cc406Sopenharmony_ci#endif 3104141cc406Sopenharmony_ci 3105141cc406Sopenharmony_ci mode = s->val[OPT_MODE].s; 3106141cc406Sopenharmony_ci 3107141cc406Sopenharmony_ci if (strcmp (mode, M_LINEART) == 0) 3108141cc406Sopenharmony_ci { 3109141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 3110141cc406Sopenharmony_ci s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; 3111141cc406Sopenharmony_ci s->params.depth = 1; 3112141cc406Sopenharmony_ci s->modes = MODES_LINEART; 3113141cc406Sopenharmony_ci } 3114141cc406Sopenharmony_ci else if (strcmp (mode, M_GRAY) == 0) 3115141cc406Sopenharmony_ci { 3116141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 3117141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 3118141cc406Sopenharmony_ci s->params.depth = 8; 3119141cc406Sopenharmony_ci s->modes = MODES_GRAY; 3120141cc406Sopenharmony_ci } 3121141cc406Sopenharmony_ci else 3122141cc406Sopenharmony_ci { 3123141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RGB; 3124141cc406Sopenharmony_ci s->params.bytes_per_line = 3 * s->params.pixels_per_line; 3125141cc406Sopenharmony_ci s->params.depth = 8; 3126141cc406Sopenharmony_ci s->modes = MODES_COLOR; 3127141cc406Sopenharmony_ci } 3128141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 3129141cc406Sopenharmony_ci 3130141cc406Sopenharmony_ci if (params) 3131141cc406Sopenharmony_ci *params = s->params; 3132141cc406Sopenharmony_ci 3133141cc406Sopenharmony_ci DBG (10, ">>\n"); 3134141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3135141cc406Sopenharmony_ci} 3136141cc406Sopenharmony_ci 3137141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 3138141cc406Sopenharmony_ci 3139141cc406Sopenharmony_cistatic int 3140141cc406Sopenharmony_cisprint_gamma(Option_Value val, SANE_Byte *dst) 3141141cc406Sopenharmony_ci{ 3142141cc406Sopenharmony_ci int i; 3143141cc406Sopenharmony_ci SANE_Byte *p = dst; 3144141cc406Sopenharmony_ci 3145141cc406Sopenharmony_ci p += sprintf((char *) p, "%i", val.wa[0] > 255 ? 255 : val.wa[0]); 3146141cc406Sopenharmony_ci /* val.wa[i] is over 255, so val.wa[i] is limited to 255 */ 3147141cc406Sopenharmony_ci for (i = 1; i < 256; i++) 3148141cc406Sopenharmony_ci p += sprintf((char *) p, ",%i", val.wa[i] > 255 ? 255 : val.wa[i]); 3149141cc406Sopenharmony_ci return p - dst; 3150141cc406Sopenharmony_ci} 3151141cc406Sopenharmony_ci 3152141cc406Sopenharmony_cistatic SANE_Status 3153141cc406Sopenharmony_cisend_ascii_gamma_tables (SHARP_Scanner *s) 3154141cc406Sopenharmony_ci{ 3155141cc406Sopenharmony_ci SANE_Status status; 3156141cc406Sopenharmony_ci int i; 3157141cc406Sopenharmony_ci 3158141cc406Sopenharmony_ci DBG(11, "<< send_ascii_gamma_tables "); 3159141cc406Sopenharmony_ci 3160141cc406Sopenharmony_ci /* we need: 4 bytes for each gamma value (3 digits + delimiter) 3161141cc406Sopenharmony_ci + 10 bytes for the command header 3162141cc406Sopenharmony_ci i.e. 4 * 4 * 256 + 10 = 4106 bytes 3163141cc406Sopenharmony_ci */ 3164141cc406Sopenharmony_ci 3165141cc406Sopenharmony_ci if (s->dev->info.bufsize < 4106) 3166141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3167141cc406Sopenharmony_ci 3168141cc406Sopenharmony_ci memset(s->buffer, 0, 4106); 3169141cc406Sopenharmony_ci 3170141cc406Sopenharmony_ci i = sprint_gamma(s->val[OPT_GAMMA_VECTOR_R], &s->buffer[10]); 3171141cc406Sopenharmony_ci s->buffer[10+i++] = '/'; 3172141cc406Sopenharmony_ci i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_G], &s->buffer[10+i]); 3173141cc406Sopenharmony_ci s->buffer[10+i++] = '/'; 3174141cc406Sopenharmony_ci i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_B], &s->buffer[10+i]); 3175141cc406Sopenharmony_ci s->buffer[10+i++] = '/'; 3176141cc406Sopenharmony_ci i += sprint_gamma(s->val[OPT_GAMMA_VECTOR], &s->buffer[10+i]); 3177141cc406Sopenharmony_ci 3178141cc406Sopenharmony_ci DBG(11, "%s\n", &s->buffer[10]); 3179141cc406Sopenharmony_ci 3180141cc406Sopenharmony_ci s->buffer[0] = SEND; 3181141cc406Sopenharmony_ci s->buffer[2] = 0x03; 3182141cc406Sopenharmony_ci s->buffer[7] = i >> 8; 3183141cc406Sopenharmony_ci s->buffer[8] = i & 0xff; 3184141cc406Sopenharmony_ci 3185141cc406Sopenharmony_ci wait_ready(s->fd); 3186141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, s->buffer, i+10, 0, 0); 3187141cc406Sopenharmony_ci 3188141cc406Sopenharmony_ci DBG(11, ">>\n"); 3189141cc406Sopenharmony_ci 3190141cc406Sopenharmony_ci return status; 3191141cc406Sopenharmony_ci} 3192141cc406Sopenharmony_ci#endif 3193141cc406Sopenharmony_ci 3194141cc406Sopenharmony_cistatic SANE_Status 3195141cc406Sopenharmony_cisend_binary_g_table(SHARP_Scanner *s, SANE_Word *a, int dtq) 3196141cc406Sopenharmony_ci{ 3197141cc406Sopenharmony_ci SANE_Status status; 3198141cc406Sopenharmony_ci int i; 3199141cc406Sopenharmony_ci 3200141cc406Sopenharmony_ci DBG(11, "<< send_binary_g_table\n"); 3201141cc406Sopenharmony_ci 3202141cc406Sopenharmony_ci memset(s->buffer, 0, 522); 3203141cc406Sopenharmony_ci 3204141cc406Sopenharmony_ci s->buffer[0] = SEND; 3205141cc406Sopenharmony_ci s->buffer[2] = 0x03; 3206141cc406Sopenharmony_ci s->buffer[5] = dtq; 3207141cc406Sopenharmony_ci s->buffer[7] = 2; 3208141cc406Sopenharmony_ci s->buffer[8] = 0; 3209141cc406Sopenharmony_ci 3210141cc406Sopenharmony_ci for (i = 0; i < 256; i++) 3211141cc406Sopenharmony_ci { 3212141cc406Sopenharmony_ci s->buffer[2*i+11] = a[i] > 255 ? 255 : a[i]; 3213141cc406Sopenharmony_ci } 3214141cc406Sopenharmony_ci 3215141cc406Sopenharmony_ci for (i = 0; i < 256; i += 16) 3216141cc406Sopenharmony_ci { 3217141cc406Sopenharmony_ci DBG(11, "%02x %02x %02x %02x %02x %02x %02x %02x " 3218141cc406Sopenharmony_ci "%02x %02x %02x %02x %02x %02x %02x %02x\n", 3219141cc406Sopenharmony_ci a[i ], a[i+1], a[i+2], a[i+3], 3220141cc406Sopenharmony_ci a[i+4], a[i+5], a[i+6], a[i+7], 3221141cc406Sopenharmony_ci a[i+8], a[i+9], a[i+10], a[i+11], 3222141cc406Sopenharmony_ci a[i+12], a[i+13], a[i+14], a[i+15]); 3223141cc406Sopenharmony_ci } 3224141cc406Sopenharmony_ci 3225141cc406Sopenharmony_ci wait_ready(s->fd); 3226141cc406Sopenharmony_ci status = sanei_scsi_cmd (s->fd, s->buffer, 2*i+10, 0, 0); 3227141cc406Sopenharmony_ci 3228141cc406Sopenharmony_ci DBG(11, ">>\n"); 3229141cc406Sopenharmony_ci 3230141cc406Sopenharmony_ci return status; 3231141cc406Sopenharmony_ci} 3232141cc406Sopenharmony_ci 3233141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 3234141cc406Sopenharmony_cistatic SANE_Status 3235141cc406Sopenharmony_cisend_binary_gamma_tables (SHARP_Scanner *s) 3236141cc406Sopenharmony_ci{ 3237141cc406Sopenharmony_ci SANE_Status status; 3238141cc406Sopenharmony_ci 3239141cc406Sopenharmony_ci status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR].wa, 0x10); 3240141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3241141cc406Sopenharmony_ci return status; 3242141cc406Sopenharmony_ci 3243141cc406Sopenharmony_ci status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_R].wa, 0x11); 3244141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3245141cc406Sopenharmony_ci return status; 3246141cc406Sopenharmony_ci 3247141cc406Sopenharmony_ci status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_G].wa, 0x12); 3248141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3249141cc406Sopenharmony_ci return status; 3250141cc406Sopenharmony_ci 3251141cc406Sopenharmony_ci status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_B].wa, 0x13); 3252141cc406Sopenharmony_ci 3253141cc406Sopenharmony_ci return status; 3254141cc406Sopenharmony_ci} 3255141cc406Sopenharmony_ci 3256141cc406Sopenharmony_cistatic SANE_Status 3257141cc406Sopenharmony_cisend_gamma_tables (SHARP_Scanner *s) 3258141cc406Sopenharmony_ci{ 3259141cc406Sopenharmony_ci if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350) 3260141cc406Sopenharmony_ci { 3261141cc406Sopenharmony_ci return send_ascii_gamma_tables(s); 3262141cc406Sopenharmony_ci } 3263141cc406Sopenharmony_ci else 3264141cc406Sopenharmony_ci { 3265141cc406Sopenharmony_ci return send_binary_gamma_tables(s); 3266141cc406Sopenharmony_ci } 3267141cc406Sopenharmony_ci 3268141cc406Sopenharmony_ci} 3269141cc406Sopenharmony_ci#endif 3270141cc406Sopenharmony_ci 3271141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 3272141cc406Sopenharmony_cistatic SANE_Status 3273141cc406Sopenharmony_cisend_threshold_data(SHARP_Scanner *s) 3274141cc406Sopenharmony_ci{ 3275141cc406Sopenharmony_ci SANE_Status status; 3276141cc406Sopenharmony_ci SANE_Byte cmd[26] = {SEND, 0, 0x82, 0, 0, 0, 0, 0, 0, 0}; 3277141cc406Sopenharmony_ci int len; 3278141cc406Sopenharmony_ci 3279141cc406Sopenharmony_ci memset(cmd, 0, sizeof(cmd)); 3280141cc406Sopenharmony_ci /* maximum string length: 3 bytes for each number (they are 3281141cc406Sopenharmony_ci restricted to the range 0..255), 3 '/' and the null-byte, 3282141cc406Sopenharmony_ci total: 16 bytes. 3283141cc406Sopenharmony_ci */ 3284141cc406Sopenharmony_ci len = sprintf((char *) &cmd[10], "%i/%i/%i/%i", 3285141cc406Sopenharmony_ci s->val[OPT_THRESHOLD_R].w, 3286141cc406Sopenharmony_ci s->val[OPT_THRESHOLD_G].w, 3287141cc406Sopenharmony_ci s->val[OPT_THRESHOLD_B].w, 3288141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w); 3289141cc406Sopenharmony_ci cmd[8] = len; 3290141cc406Sopenharmony_ci 3291141cc406Sopenharmony_ci wait_ready(s->fd); 3292141cc406Sopenharmony_ci status = sanei_scsi_cmd(s->fd, cmd, len + 10, 0, 0); 3293141cc406Sopenharmony_ci return status; 3294141cc406Sopenharmony_ci} 3295141cc406Sopenharmony_ci#endif 3296141cc406Sopenharmony_ci 3297141cc406Sopenharmony_ci 3298141cc406Sopenharmony_ciSANE_Status 3299141cc406Sopenharmony_cisane_start (SANE_Handle handle) 3300141cc406Sopenharmony_ci{ 3301141cc406Sopenharmony_ci char *mode, *halftone, *gamma, *edge, *lightcolor, *adf_fsu; 3302141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 3303141cc406Sopenharmony_ci SANE_Status status; 3304141cc406Sopenharmony_ci size_t buf_size; 3305141cc406Sopenharmony_ci SHARP_Send ss; 3306141cc406Sopenharmony_ci window_param wp; 3307141cc406Sopenharmony_ci mode_sense_subdevice m_subdev; 3308141cc406Sopenharmony_ci 3309141cc406Sopenharmony_ci DBG (10, "<< sane_start "); 3310141cc406Sopenharmony_ci 3311141cc406Sopenharmony_ci /* First make sure we have a current parameter set. Some of the 3312141cc406Sopenharmony_ci parameters will be overwritten below, but that's OK. */ 3313141cc406Sopenharmony_ci status = sane_get_parameters (s, 0); 3314141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3315141cc406Sopenharmony_ci return status; 3316141cc406Sopenharmony_ci 3317141cc406Sopenharmony_ci s->dev->sensedat.complain_on_errors 3318141cc406Sopenharmony_ci = COMPLAIN_ON_ADF_ERROR | s->dev->info.complain_on_errors; 3319141cc406Sopenharmony_ci 3320141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED 3321141cc406Sopenharmony_ci s->dev->info.bufsize = s->dev->info.wanted_bufsize; 3322141cc406Sopenharmony_ci if (s->dev->info.bufsize < 32 * 1024) 3323141cc406Sopenharmony_ci s->dev->info.bufsize = 32 * 1024; 3324141cc406Sopenharmony_ci { 3325141cc406Sopenharmony_ci int bsize = s->dev->info.bufsize; 3326141cc406Sopenharmony_ci status = sanei_scsi_open_extended (s->dev->sane.name, &s->fd, 3327141cc406Sopenharmony_ci &sense_handler, &s->dev->sensedat, &bsize); 3328141cc406Sopenharmony_ci s->dev->info.bufsize = bsize; 3329141cc406Sopenharmony_ci } 3330141cc406Sopenharmony_ci 3331141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3332141cc406Sopenharmony_ci { 3333141cc406Sopenharmony_ci DBG (1, "open of %s failed: %s\n", 3334141cc406Sopenharmony_ci s->dev->sane.name, sane_strstatus (status)); 3335141cc406Sopenharmony_ci return (status); 3336141cc406Sopenharmony_ci } 3337141cc406Sopenharmony_ci 3338141cc406Sopenharmony_ci /* make sure that we got at least 32 kB. Even then, the scan will be 3339141cc406Sopenharmony_ci awfully slow. 3340141cc406Sopenharmony_ci 3341141cc406Sopenharmony_ci NOTE: If you need to decrease this value, remember that s->buffer 3342141cc406Sopenharmony_ci is used in send_ascii_gamma_tables (JX330/JX610) and in 3343141cc406Sopenharmony_ci send_binary_g_table (JX250/JX350). send_ascii_gamma_tables needs 4106 3344141cc406Sopenharmony_ci bytes, and send_binary_g_table needs 522 bytes. 3345141cc406Sopenharmony_ci */ 3346141cc406Sopenharmony_ci if (s->dev->info.bufsize < 32 * 1024) 3347141cc406Sopenharmony_ci { 3348141cc406Sopenharmony_ci sanei_scsi_close(s->fd); 3349141cc406Sopenharmony_ci s->fd = -1; 3350141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3351141cc406Sopenharmony_ci } 3352141cc406Sopenharmony_ci#else 3353141cc406Sopenharmony_ci status = sanei_scsi_open(s->dev->sane.name, &s->fd, &sense_handler, 3354141cc406Sopenharmony_ci &s->dev->sensedat); 3355141cc406Sopenharmony_ci if (s->dev->info.wanted_bufsize < sanei_scsi_max_request_size) 3356141cc406Sopenharmony_ci s->dev->info.bufsize = s->dev->info.wanted_bufsize; 3357141cc406Sopenharmony_ci else 3358141cc406Sopenharmony_ci s->dev->info.bufsize = sanei_scsi_max_request_size; 3359141cc406Sopenharmony_ci 3360141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3361141cc406Sopenharmony_ci { 3362141cc406Sopenharmony_ci DBG (1, "open of %s failed: %s\n", 3363141cc406Sopenharmony_ci s->dev->sane.name, sane_strstatus (status)); 3364141cc406Sopenharmony_ci return (status); 3365141cc406Sopenharmony_ci } 3366141cc406Sopenharmony_ci#endif 3367141cc406Sopenharmony_ci 3368141cc406Sopenharmony_ci s->buffer = malloc(s->dev->info.bufsize); 3369141cc406Sopenharmony_ci if (!s->buffer) { 3370141cc406Sopenharmony_ci sanei_scsi_close(s->fd); 3371141cc406Sopenharmony_ci s->fd = -1; 3372141cc406Sopenharmony_ci free(s); 3373141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3374141cc406Sopenharmony_ci } 3375141cc406Sopenharmony_ci 3376141cc406Sopenharmony_ci#ifdef USE_FORK 3377141cc406Sopenharmony_ci { 3378141cc406Sopenharmony_ci struct shmid_ds ds; 3379141cc406Sopenharmony_ci size_t n; 3380141cc406Sopenharmony_ci 3381141cc406Sopenharmony_ci s->shmid = shmget(IPC_PRIVATE, 3382141cc406Sopenharmony_ci sizeof(SHARP_rdr_ctl) 3383141cc406Sopenharmony_ci + s->dev->info.buffers * 3384141cc406Sopenharmony_ci (sizeof(SHARP_shmem_ctl) + s->dev->info.bufsize), 3385141cc406Sopenharmony_ci IPC_CREAT | 0600); 3386141cc406Sopenharmony_ci if (s->shmid == -1) 3387141cc406Sopenharmony_ci { 3388141cc406Sopenharmony_ci free(s->buffer); 3389141cc406Sopenharmony_ci s->buffer = 0; 3390141cc406Sopenharmony_ci sanei_scsi_close(s->fd); 3391141cc406Sopenharmony_ci s->fd = -1; 3392141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3393141cc406Sopenharmony_ci } 3394141cc406Sopenharmony_ci s->rdr_ctl = (SHARP_rdr_ctl*) shmat(s->shmid, 0, 0); 3395141cc406Sopenharmony_ci if (s->rdr_ctl == (void *) -1) 3396141cc406Sopenharmony_ci { 3397141cc406Sopenharmony_ci shmctl(s->shmid, IPC_RMID, &ds); 3398141cc406Sopenharmony_ci free(s->buffer); 3399141cc406Sopenharmony_ci s->buffer = 0; 3400141cc406Sopenharmony_ci sanei_scsi_close(s->fd); 3401141cc406Sopenharmony_ci s->fd = -1; 3402141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3403141cc406Sopenharmony_ci } 3404141cc406Sopenharmony_ci 3405141cc406Sopenharmony_ci s->rdr_ctl->buf_ctl = (SHARP_shmem_ctl*) &s->rdr_ctl[1]; 3406141cc406Sopenharmony_ci for (n = 0; n < s->dev->info.buffers; n++) 3407141cc406Sopenharmony_ci { 3408141cc406Sopenharmony_ci s->rdr_ctl->buf_ctl[n].buffer = 3409141cc406Sopenharmony_ci (SANE_Byte*) &s->rdr_ctl->buf_ctl[s->dev->info.buffers] 3410141cc406Sopenharmony_ci + n * s->dev->info.bufsize; 3411141cc406Sopenharmony_ci } 3412141cc406Sopenharmony_ci } 3413141cc406Sopenharmony_ci#endif /* USE_FORK */ 3414141cc406Sopenharmony_ci 3415141cc406Sopenharmony_ci DBG (5, "start: TEST_UNIT_READY\n"); 3416141cc406Sopenharmony_ci status = test_unit_ready (s->fd); 3417141cc406Sopenharmony_ci 3418141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3419141cc406Sopenharmony_ci { 3420141cc406Sopenharmony_ci DBG (1, "TEST UNIT READY failed: %s\n", sane_strstatus (status)); 3421141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3422141cc406Sopenharmony_ci s->fd = -1; 3423141cc406Sopenharmony_ci return (status); 3424141cc406Sopenharmony_ci } 3425141cc406Sopenharmony_ci 3426141cc406Sopenharmony_ci DBG (3, "start: sending MODE SELECT\n"); 3427141cc406Sopenharmony_ci status = mode_select_mud (s->fd, s->dev->info.mud); 3428141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3429141cc406Sopenharmony_ci { 3430141cc406Sopenharmony_ci DBG (1, "start: MODE_SELECT6 failed\n"); 3431141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3432141cc406Sopenharmony_ci s->fd = -1; 3433141cc406Sopenharmony_ci return (status); 3434141cc406Sopenharmony_ci } 3435141cc406Sopenharmony_ci 3436141cc406Sopenharmony_ci mode = s->val[OPT_MODE].s; 3437141cc406Sopenharmony_ci halftone = s->val[OPT_HALFTONE].s; 3438141cc406Sopenharmony_ci gamma = s->val[OPT_GAMMA].s; 3439141cc406Sopenharmony_ci edge = s->val[OPT_EDGE_EMPHASIS].s; 3440141cc406Sopenharmony_ci lightcolor = s->val[OPT_LIGHTCOLOR].s; 3441141cc406Sopenharmony_ci adf_fsu = s->val[OPT_SCANSOURCE].s; 3442141cc406Sopenharmony_ci s->speed = s->val[OPT_SPEED].w; 3443141cc406Sopenharmony_ci 3444141cc406Sopenharmony_ci s->xres = s->val[OPT_X_RESOLUTION].w; 3445141cc406Sopenharmony_ci if (s->val[OPT_PREVIEW].w == SANE_FALSE) 3446141cc406Sopenharmony_ci { 3447141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION 3448141cc406Sopenharmony_ci s->yres = s->val[OPT_Y_RESOLUTION].w; 3449141cc406Sopenharmony_ci#else 3450141cc406Sopenharmony_ci s->yres = s->val[OPT_X_RESOLUTION].w; 3451141cc406Sopenharmony_ci#endif 3452141cc406Sopenharmony_ci s->speed = s->val[OPT_SPEED].w; 3453141cc406Sopenharmony_ci } 3454141cc406Sopenharmony_ci else 3455141cc406Sopenharmony_ci { 3456141cc406Sopenharmony_ci s->yres = s->val[OPT_X_RESOLUTION].w; 3457141cc406Sopenharmony_ci s->speed = SANE_TRUE; 3458141cc406Sopenharmony_ci } 3459141cc406Sopenharmony_ci 3460141cc406Sopenharmony_ci s->ulx = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_X].w), s->dev->info.mud); 3461141cc406Sopenharmony_ci s->uly = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_Y].w), s->dev->info.mud); 3462141cc406Sopenharmony_ci s->threshold = s->val[OPT_THRESHOLD].w; 3463141cc406Sopenharmony_ci s->bpp = s->params.depth; 3464141cc406Sopenharmony_ci 3465141cc406Sopenharmony_ci s->adf_fsu_mode = SCAN_SIMPLE; /* default: scan without ADF and FSU */ 3466141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF 3467141cc406Sopenharmony_ci if (strcmp (adf_fsu, use_auto) == 0) 3468141cc406Sopenharmony_ci s->adf_fsu_mode = SCAN_ADF_FSU_AUTO; 3469141cc406Sopenharmony_ci else 3470141cc406Sopenharmony_ci#endif 3471141cc406Sopenharmony_ci if (strcmp(adf_fsu, use_fsu) == 0) 3472141cc406Sopenharmony_ci s->adf_fsu_mode = SCAN_WITH_FSU; 3473141cc406Sopenharmony_ci else if (strcmp(adf_fsu, use_adf) == 0) 3474141cc406Sopenharmony_ci s->adf_fsu_mode = SCAN_WITH_ADF; 3475141cc406Sopenharmony_ci else if (strcmp(adf_fsu, use_adf) == 0) 3476141cc406Sopenharmony_ci s->adf_fsu_mode = SCAN_SIMPLE; 3477141cc406Sopenharmony_ci 3478141cc406Sopenharmony_ci if (strcmp (mode, M_LINEART) == 0) 3479141cc406Sopenharmony_ci { 3480141cc406Sopenharmony_ci s->reverse = 0; 3481141cc406Sopenharmony_ci if (strcmp(halftone, M_BILEVEL) == 0) 3482141cc406Sopenharmony_ci { 3483141cc406Sopenharmony_ci s->halftone = 1; 3484141cc406Sopenharmony_ci s->image_composition = 0; 3485141cc406Sopenharmony_ci } 3486141cc406Sopenharmony_ci else if (strcmp(halftone, M_BAYER) == 0) 3487141cc406Sopenharmony_ci { 3488141cc406Sopenharmony_ci s->halftone = 2; 3489141cc406Sopenharmony_ci s->image_composition = 1; 3490141cc406Sopenharmony_ci } 3491141cc406Sopenharmony_ci else if (strcmp(halftone, M_SPIRAL) == 0) 3492141cc406Sopenharmony_ci { 3493141cc406Sopenharmony_ci s->halftone = 3; 3494141cc406Sopenharmony_ci s->image_composition = 1; 3495141cc406Sopenharmony_ci } 3496141cc406Sopenharmony_ci else if (strcmp(halftone, M_DISPERSED) == 0) 3497141cc406Sopenharmony_ci { 3498141cc406Sopenharmony_ci s->halftone = 4; 3499141cc406Sopenharmony_ci s->image_composition = 1; 3500141cc406Sopenharmony_ci } 3501141cc406Sopenharmony_ci else if (strcmp(halftone, M_ERRDIFFUSION) == 0) 3502141cc406Sopenharmony_ci { 3503141cc406Sopenharmony_ci s->halftone = 5; 3504141cc406Sopenharmony_ci s->image_composition = 1; 3505141cc406Sopenharmony_ci } 3506141cc406Sopenharmony_ci } 3507141cc406Sopenharmony_ci else if (strcmp (mode, M_GRAY) == 0) 3508141cc406Sopenharmony_ci { 3509141cc406Sopenharmony_ci s->image_composition = 2; 3510141cc406Sopenharmony_ci s->reverse = 1; 3511141cc406Sopenharmony_ci } 3512141cc406Sopenharmony_ci else if (strcmp (mode, M_LINEART_COLOR) == 0) 3513141cc406Sopenharmony_ci { 3514141cc406Sopenharmony_ci s->reverse = 1; 3515141cc406Sopenharmony_ci if (strcmp(halftone, M_BILEVEL) == 0) 3516141cc406Sopenharmony_ci { 3517141cc406Sopenharmony_ci s->halftone = 1; 3518141cc406Sopenharmony_ci s->image_composition = 3; 3519141cc406Sopenharmony_ci } 3520141cc406Sopenharmony_ci else if (strcmp(halftone, M_BAYER) == 0) 3521141cc406Sopenharmony_ci { 3522141cc406Sopenharmony_ci s->halftone = 2; 3523141cc406Sopenharmony_ci s->image_composition = 4; 3524141cc406Sopenharmony_ci } 3525141cc406Sopenharmony_ci else if (strcmp(halftone, M_SPIRAL) == 0) 3526141cc406Sopenharmony_ci { 3527141cc406Sopenharmony_ci s->halftone = 3; 3528141cc406Sopenharmony_ci s->image_composition = 4; 3529141cc406Sopenharmony_ci } 3530141cc406Sopenharmony_ci else if (strcmp(halftone, M_DISPERSED) == 0) 3531141cc406Sopenharmony_ci { 3532141cc406Sopenharmony_ci s->halftone = 4; 3533141cc406Sopenharmony_ci s->image_composition = 4; 3534141cc406Sopenharmony_ci } 3535141cc406Sopenharmony_ci else if (strcmp(halftone, M_ERRDIFFUSION) == 0) 3536141cc406Sopenharmony_ci { 3537141cc406Sopenharmony_ci s->halftone = 5; 3538141cc406Sopenharmony_ci s->image_composition = 4; 3539141cc406Sopenharmony_ci } 3540141cc406Sopenharmony_ci } 3541141cc406Sopenharmony_ci else if (strcmp (mode, M_COLOR) == 0) 3542141cc406Sopenharmony_ci { 3543141cc406Sopenharmony_ci s->image_composition = 5; 3544141cc406Sopenharmony_ci s->reverse = 1; 3545141cc406Sopenharmony_ci } 3546141cc406Sopenharmony_ci 3547141cc406Sopenharmony_ci if (strcmp (edge, EDGE_NONE) == 0) 3548141cc406Sopenharmony_ci { 3549141cc406Sopenharmony_ci DBG (11, "EDGE EMPHASIS NONE\n"); 3550141cc406Sopenharmony_ci s->edge = 0; 3551141cc406Sopenharmony_ci } 3552141cc406Sopenharmony_ci else if (strcmp (edge, EDGE_MIDDLE) == 0) 3553141cc406Sopenharmony_ci { 3554141cc406Sopenharmony_ci DBG (11, "EDGE EMPHASIS MIDDLE\n"); 3555141cc406Sopenharmony_ci s->edge = 1; 3556141cc406Sopenharmony_ci } 3557141cc406Sopenharmony_ci else if (strcmp (edge, EDGE_STRONG) == 0) 3558141cc406Sopenharmony_ci { 3559141cc406Sopenharmony_ci DBG (11, "EDGE EMPHASIS STRONG\n"); 3560141cc406Sopenharmony_ci s->edge = 2; 3561141cc406Sopenharmony_ci } 3562141cc406Sopenharmony_ci else if (strcmp (edge, EDGE_BLUR) == 0) 3563141cc406Sopenharmony_ci { 3564141cc406Sopenharmony_ci DBG (11, "EDGE EMPHASIS BLUR\n"); 3565141cc406Sopenharmony_ci s->edge = 3; 3566141cc406Sopenharmony_ci } 3567141cc406Sopenharmony_ci 3568141cc406Sopenharmony_ci s->lightcolor = 3; 3569141cc406Sopenharmony_ci if (strcmp(lightcolor, LIGHT_GREEN) == 0) 3570141cc406Sopenharmony_ci s->lightcolor = 0; 3571141cc406Sopenharmony_ci else if (strcmp(lightcolor, LIGHT_RED) == 0) 3572141cc406Sopenharmony_ci s->lightcolor = 1; 3573141cc406Sopenharmony_ci else if (strcmp(lightcolor, LIGHT_BLUE) == 0) 3574141cc406Sopenharmony_ci s->lightcolor = 2; 3575141cc406Sopenharmony_ci else if (strcmp(lightcolor, LIGHT_WHITE) == 0) 3576141cc406Sopenharmony_ci s->lightcolor = 3; 3577141cc406Sopenharmony_ci 3578141cc406Sopenharmony_ci s->adf_scan = 0; 3579141cc406Sopenharmony_ci if ( s->dev->sensedat.model != JX610 3580141cc406Sopenharmony_ci && s->dev->sensedat.model != JX320) 3581141cc406Sopenharmony_ci { 3582141cc406Sopenharmony_ci status = mode_select_adf_fsu(s->fd, s->adf_fsu_mode); 3583141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3584141cc406Sopenharmony_ci { 3585141cc406Sopenharmony_ci DBG (10, "sane_start: mode_select_adf_fsu failed: %s\n", sane_strstatus (status)); 3586141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3587141cc406Sopenharmony_ci s->fd = -1; 3588141cc406Sopenharmony_ci return (status); 3589141cc406Sopenharmony_ci } 3590141cc406Sopenharmony_ci /* if the ADF is selected, check if it is ready */ 3591141cc406Sopenharmony_ci memset (&m_subdev, 0, sizeof (m_subdev)); 3592141cc406Sopenharmony_ci buf_size = sizeof (m_subdev); 3593141cc406Sopenharmony_ci status = mode_sense (s->fd, &m_subdev, &buf_size, 0x20); 3594141cc406Sopenharmony_ci DBG(11, "mode sense result a_mode: %x f_mode: %x\n", 3595141cc406Sopenharmony_ci m_subdev.a_mode_type, m_subdev.f_mode_type); 3596141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3597141cc406Sopenharmony_ci { 3598141cc406Sopenharmony_ci DBG (10, "sane_start: MODE_SENSE/subdevice page failed\n"); 3599141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3600141cc406Sopenharmony_ci s->fd = -1; 3601141cc406Sopenharmony_ci return (status); 3602141cc406Sopenharmony_ci } 3603141cc406Sopenharmony_ci if (s->adf_fsu_mode == SCAN_WITH_ADF) 3604141cc406Sopenharmony_ci s->adf_scan = 1; 3605141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF 3606141cc406Sopenharmony_ci else if (s->adf_fsu_mode == SCAN_ADF_FSU_AUTO) 3607141cc406Sopenharmony_ci { 3608141cc406Sopenharmony_ci if (m_subdev.a_mode_type & 0x80) 3609141cc406Sopenharmony_ci s->adf_scan = 1; 3610141cc406Sopenharmony_ci } 3611141cc406Sopenharmony_ci#endif 3612141cc406Sopenharmony_ci } 3613141cc406Sopenharmony_ci 3614141cc406Sopenharmony_ci 3615141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 3616141cc406Sopenharmony_ci if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) 3617141cc406Sopenharmony_ci { 3618141cc406Sopenharmony_ci#endif 3619141cc406Sopenharmony_ci if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350) 3620141cc406Sopenharmony_ci { 3621141cc406Sopenharmony_ci ss.dtc = 0x03; 3622141cc406Sopenharmony_ci if (strcmp (gamma, GAMMA10) == 0) 3623141cc406Sopenharmony_ci { 3624141cc406Sopenharmony_ci ss.dtq = 0x01; 3625141cc406Sopenharmony_ci }else{ 3626141cc406Sopenharmony_ci ss.dtq = 0x02; 3627141cc406Sopenharmony_ci } 3628141cc406Sopenharmony_ci ss.length = 0; 3629141cc406Sopenharmony_ci DBG (5, "start: SEND\n"); 3630141cc406Sopenharmony_ci status = send (s->fd, &ss); 3631141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3632141cc406Sopenharmony_ci { 3633141cc406Sopenharmony_ci DBG (1, "send failed: %s\n", sane_strstatus (status)); 3634141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3635141cc406Sopenharmony_ci s->fd = -1; 3636141cc406Sopenharmony_ci return (status); 3637141cc406Sopenharmony_ci } 3638141cc406Sopenharmony_ci } 3639141cc406Sopenharmony_ci else 3640141cc406Sopenharmony_ci { 3641141cc406Sopenharmony_ci /* the JX250 does not support the "fixed gamma selection", 3642141cc406Sopenharmony_ci therefore, lets calculate & send gamma values 3643141cc406Sopenharmony_ci */ 3644141cc406Sopenharmony_ci int i; 3645141cc406Sopenharmony_ci SANE_Word gtbl[256]; 3646141cc406Sopenharmony_ci if (strcmp (gamma, GAMMA10) == 0) 3647141cc406Sopenharmony_ci for (i = 0; i < 256; i++) 3648141cc406Sopenharmony_ci gtbl[i] = i; 3649141cc406Sopenharmony_ci else 3650141cc406Sopenharmony_ci { 3651141cc406Sopenharmony_ci gtbl[0] = 0; 3652141cc406Sopenharmony_ci for (i = 1; i < 256; i++) 3653141cc406Sopenharmony_ci gtbl[i] = 255 * exp(0.45 * log(i/255.0)); 3654141cc406Sopenharmony_ci } 3655141cc406Sopenharmony_ci send_binary_g_table(s, gtbl, 0x10); 3656141cc406Sopenharmony_ci send_binary_g_table(s, gtbl, 0x11); 3657141cc406Sopenharmony_ci send_binary_g_table(s, gtbl, 0x12); 3658141cc406Sopenharmony_ci send_binary_g_table(s, gtbl, 0x13); 3659141cc406Sopenharmony_ci } 3660141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA 3661141cc406Sopenharmony_ci } 3662141cc406Sopenharmony_ci else 3663141cc406Sopenharmony_ci status = send_gamma_tables(s); 3664141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3665141cc406Sopenharmony_ci { 3666141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3667141cc406Sopenharmony_ci s->fd = -1; 3668141cc406Sopenharmony_ci return (status); 3669141cc406Sopenharmony_ci } 3670141cc406Sopenharmony_ci#endif 3671141cc406Sopenharmony_ci 3672141cc406Sopenharmony_ci if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350) 3673141cc406Sopenharmony_ci { 3674141cc406Sopenharmony_ci ss.dtc = 0x86; 3675141cc406Sopenharmony_ci ss.dtq = 0x05; 3676141cc406Sopenharmony_ci ss.length = 0; 3677141cc406Sopenharmony_ci DBG (5, "start: SEND\n"); 3678141cc406Sopenharmony_ci status = send (s->fd, &ss); 3679141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3680141cc406Sopenharmony_ci { 3681141cc406Sopenharmony_ci DBG (1, "send failed: %s\n", sane_strstatus (status)); 3682141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3683141cc406Sopenharmony_ci s->fd = -1; 3684141cc406Sopenharmony_ci return (status); 3685141cc406Sopenharmony_ci } 3686141cc406Sopenharmony_ci 3687141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD 3688141cc406Sopenharmony_ci status = send_threshold_data(s); 3689141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3690141cc406Sopenharmony_ci { 3691141cc406Sopenharmony_ci DBG (1, "send threshold data failed: %s\n", sane_strstatus (status)); 3692141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3693141cc406Sopenharmony_ci s->fd = -1; 3694141cc406Sopenharmony_ci return (status); 3695141cc406Sopenharmony_ci } 3696141cc406Sopenharmony_ci#endif 3697141cc406Sopenharmony_ci } 3698141cc406Sopenharmony_ci 3699141cc406Sopenharmony_ci memset (&wp, 0, sizeof (wp)); 3700141cc406Sopenharmony_ci /* every Sharp scanner seems to have a different 3701141cc406Sopenharmony_ci window descriptor block... 3702141cc406Sopenharmony_ci */ 3703141cc406Sopenharmony_ci if ( s->dev->sensedat.model == JX610 3704141cc406Sopenharmony_ci || s->dev->sensedat.model == JX320) 3705141cc406Sopenharmony_ci { 3706141cc406Sopenharmony_ci buf_size = sizeof(WDB); 3707141cc406Sopenharmony_ci } 3708141cc406Sopenharmony_ci else if (s->dev->sensedat.model == JX330) 3709141cc406Sopenharmony_ci { 3710141cc406Sopenharmony_ci buf_size = sizeof (WDB) + sizeof(WDBX330); 3711141cc406Sopenharmony_ci } 3712141cc406Sopenharmony_ci else 3713141cc406Sopenharmony_ci { 3714141cc406Sopenharmony_ci buf_size = sizeof (WDB) + sizeof(WDBX330) + sizeof(WDBX250); 3715141cc406Sopenharmony_ci } 3716141cc406Sopenharmony_ci 3717141cc406Sopenharmony_ci wp.wpdh.wdl[0] = buf_size >> 8; 3718141cc406Sopenharmony_ci wp.wpdh.wdl[1] = buf_size; 3719141cc406Sopenharmony_ci wp.wdb.x_res[0] = s->xres >> 8; 3720141cc406Sopenharmony_ci wp.wdb.x_res[1] = s->xres; 3721141cc406Sopenharmony_ci wp.wdb.y_res[0] = s->yres >> 8; 3722141cc406Sopenharmony_ci wp.wdb.y_res[1] = s->yres; 3723141cc406Sopenharmony_ci wp.wdb.x_ul[0] = s->ulx >> 24; 3724141cc406Sopenharmony_ci wp.wdb.x_ul[1] = s->ulx >> 16; 3725141cc406Sopenharmony_ci wp.wdb.x_ul[2] = s->ulx >> 8; 3726141cc406Sopenharmony_ci wp.wdb.x_ul[3] = s->ulx; 3727141cc406Sopenharmony_ci wp.wdb.y_ul[0] = s->uly >> 24; 3728141cc406Sopenharmony_ci wp.wdb.y_ul[1] = s->uly >> 16; 3729141cc406Sopenharmony_ci wp.wdb.y_ul[2] = s->uly >> 8; 3730141cc406Sopenharmony_ci wp.wdb.y_ul[3] = s->uly; 3731141cc406Sopenharmony_ci wp.wdb.width[0] = s->width >> 24; 3732141cc406Sopenharmony_ci wp.wdb.width[1] = s->width >> 16; 3733141cc406Sopenharmony_ci wp.wdb.width[2] = s->width >> 8; 3734141cc406Sopenharmony_ci wp.wdb.width[3] = s->width; 3735141cc406Sopenharmony_ci wp.wdb.length[0] = s->length >> 24; 3736141cc406Sopenharmony_ci wp.wdb.length[1] = s->length >> 16; 3737141cc406Sopenharmony_ci wp.wdb.length[2] = s->length >> 8; 3738141cc406Sopenharmony_ci wp.wdb.length[3] = s->length; 3739141cc406Sopenharmony_ci wp.wdb.brightness = 0; 3740141cc406Sopenharmony_ci wp.wdb.threshold = s->threshold; 3741141cc406Sopenharmony_ci wp.wdb.image_composition = s->image_composition; 3742141cc406Sopenharmony_ci if (s->image_composition <= 2 || s->image_composition >= 5) 3743141cc406Sopenharmony_ci wp.wdb.bpp = s->bpp; 3744141cc406Sopenharmony_ci else 3745141cc406Sopenharmony_ci wp.wdb.bpp = 1; 3746141cc406Sopenharmony_ci wp.wdb.ht_pattern[0] = 0; 3747141cc406Sopenharmony_ci if ( s->dev->sensedat.model == JX610 3748141cc406Sopenharmony_ci || s->dev->sensedat.model == JX320) 3749141cc406Sopenharmony_ci { 3750141cc406Sopenharmony_ci wp.wdb.ht_pattern[1] = 0; 3751141cc406Sopenharmony_ci }else{ 3752141cc406Sopenharmony_ci wp.wdb.ht_pattern[1] = s->halftone; 3753141cc406Sopenharmony_ci } 3754141cc406Sopenharmony_ci wp.wdb.rif_padding = (s->reverse * 128) + 0; 3755141cc406Sopenharmony_ci wp.wdb.eletu = (!s->speed << 2) + (s->edge << 6) + (s->lightcolor << 4); 3756141cc406Sopenharmony_ci 3757141cc406Sopenharmony_ci if (s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350) 3758141cc406Sopenharmony_ci { 3759141cc406Sopenharmony_ci wp.wdbx250.threshold_red = s->val[OPT_THRESHOLD_R].w; 3760141cc406Sopenharmony_ci wp.wdbx250.threshold_green = s->val[OPT_THRESHOLD_G].w; 3761141cc406Sopenharmony_ci wp.wdbx250.threshold_blue = s->val[OPT_THRESHOLD_B].w; 3762141cc406Sopenharmony_ci } 3763141cc406Sopenharmony_ci 3764141cc406Sopenharmony_ci 3765141cc406Sopenharmony_ci DBG (5, "wdl=%d\n", (wp.wpdh.wdl[0] << 8) + wp.wpdh.wdl[1]); 3766141cc406Sopenharmony_ci DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]); 3767141cc406Sopenharmony_ci DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]); 3768141cc406Sopenharmony_ci DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) + 3769141cc406Sopenharmony_ci (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]); 3770141cc406Sopenharmony_ci DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) + 3771141cc406Sopenharmony_ci (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]); 3772141cc406Sopenharmony_ci DBG (5, "width=%d\n", (wp.wdb.width[0] << 8) + (wp.wdb.width[1] << 16) + 3773141cc406Sopenharmony_ci (wp.wdb.width[2] << 8) + wp.wdb.width[3]); 3774141cc406Sopenharmony_ci DBG (5, "length=%d\n", (wp.wdb.length[0] << 16) + (wp.wdb.length[1] << 16) + 3775141cc406Sopenharmony_ci (wp.wdb.length[2] << 8) + wp.wdb.length[3]); 3776141cc406Sopenharmony_ci 3777141cc406Sopenharmony_ci DBG (5, "threshold=%d\n", wp.wdb.threshold); 3778141cc406Sopenharmony_ci DBG (5, "image_composition=%d\n", wp.wdb.image_composition); 3779141cc406Sopenharmony_ci DBG (5, "bpp=%d\n", wp.wdb.bpp); 3780141cc406Sopenharmony_ci DBG (5, "rif_padding=%d\n", wp.wdb.rif_padding); 3781141cc406Sopenharmony_ci DBG (5, "eletu=%d\n", wp.wdb.eletu); 3782141cc406Sopenharmony_ci 3783141cc406Sopenharmony_ci#if 0 3784141cc406Sopenharmony_ci { 3785141cc406Sopenharmony_ci unsigned char *p = (unsigned char*) &wp.wdb; 3786141cc406Sopenharmony_ci int i; 3787141cc406Sopenharmony_ci DBG(11, "set window:\n"); 3788141cc406Sopenharmony_ci for (i = 0; i < sizeof(wp.wdb) + + sizeof(wp.wdbx330) + sizeof(wp.wdbx250); i += 16) 3789141cc406Sopenharmony_ci { 3790141cc406Sopenharmony_ci DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x %2x %2x %2x %2x\n", 3791141cc406Sopenharmony_ci p[i], p[i+1], p[i+2], p[i+3], p[i+4], p[i+5], p[i+6], p[i+7], p[i+8], 3792141cc406Sopenharmony_ci p[i+9], p[i+10], p[i+11], p[i+12], p[i+13], p[i+14], p[i+15]); 3793141cc406Sopenharmony_ci } 3794141cc406Sopenharmony_ci } 3795141cc406Sopenharmony_ci#endif 3796141cc406Sopenharmony_ci 3797141cc406Sopenharmony_ci buf_size += sizeof(WPDH); 3798141cc406Sopenharmony_ci DBG (5, "start: SET WINDOW\n"); 3799141cc406Sopenharmony_ci status = set_window (s->fd, &wp, buf_size); 3800141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3801141cc406Sopenharmony_ci { 3802141cc406Sopenharmony_ci DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); 3803141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3804141cc406Sopenharmony_ci s->fd = -1; 3805141cc406Sopenharmony_ci return (status); 3806141cc406Sopenharmony_ci } 3807141cc406Sopenharmony_ci 3808141cc406Sopenharmony_ci memset (&wp, 0, buf_size); 3809141cc406Sopenharmony_ci DBG (5, "start: GET WINDOW\n"); 3810141cc406Sopenharmony_ci status = get_window (s->fd, &wp, &buf_size); 3811141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3812141cc406Sopenharmony_ci { 3813141cc406Sopenharmony_ci DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); 3814141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3815141cc406Sopenharmony_ci s->fd = -1; 3816141cc406Sopenharmony_ci return (status); 3817141cc406Sopenharmony_ci } 3818141cc406Sopenharmony_ci DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]); 3819141cc406Sopenharmony_ci DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]); 3820141cc406Sopenharmony_ci DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) + 3821141cc406Sopenharmony_ci (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]); 3822141cc406Sopenharmony_ci DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) + 3823141cc406Sopenharmony_ci (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]); 3824141cc406Sopenharmony_ci DBG (5, "width=%d\n", (wp.wdb.width[0] << 24) + (wp.wdb.width[1] << 16) + 3825141cc406Sopenharmony_ci (wp.wdb.width[2] << 8) + wp.wdb.width[3]); 3826141cc406Sopenharmony_ci DBG (5, "length=%d\n", (wp.wdb.length[0] << 24) + (wp.wdb.length[1] << 16) + 3827141cc406Sopenharmony_ci (wp.wdb.length[2] << 8) + wp.wdb.length[3]); 3828141cc406Sopenharmony_ci 3829141cc406Sopenharmony_ci if (s->adf_scan) 3830141cc406Sopenharmony_ci { 3831141cc406Sopenharmony_ci status = object_position(s->fd, LOAD_PAPER); 3832141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3833141cc406Sopenharmony_ci { 3834141cc406Sopenharmony_ci sanei_scsi_close (s->fd); 3835141cc406Sopenharmony_ci s->fd = -1; 3836141cc406Sopenharmony_ci s->busy = SANE_FALSE; 3837141cc406Sopenharmony_ci s->cancel = SANE_FALSE; 3838141cc406Sopenharmony_ci return (status); 3839141cc406Sopenharmony_ci } 3840141cc406Sopenharmony_ci } 3841141cc406Sopenharmony_ci 3842141cc406Sopenharmony_ci DBG (5, "start: SCAN\n"); 3843141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 3844141cc406Sopenharmony_ci s->busy = SANE_TRUE; 3845141cc406Sopenharmony_ci s->cancel = SANE_FALSE; 3846141cc406Sopenharmony_ci s->get_params_called = 0; 3847141cc406Sopenharmony_ci 3848141cc406Sopenharmony_ci wait_ready(s->fd); 3849141cc406Sopenharmony_ci status = scan (s->fd); 3850141cc406Sopenharmony_ci#ifdef DEBUG 3851141cc406Sopenharmony_ci { 3852141cc406Sopenharmony_ci struct timeval t; 3853141cc406Sopenharmony_ci gettimeofday(&t, 0); 3854141cc406Sopenharmony_ci DBG(2, "rd: scan started %li.%06li\n", t.tv_sec, t.tv_usec); 3855141cc406Sopenharmony_ci } 3856141cc406Sopenharmony_ci#endif 3857141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3858141cc406Sopenharmony_ci { 3859141cc406Sopenharmony_ci DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); 3860141cc406Sopenharmony_ci do_cancel(s); 3861141cc406Sopenharmony_ci return (status); 3862141cc406Sopenharmony_ci } 3863141cc406Sopenharmony_ci 3864141cc406Sopenharmony_ci /* ask the scanner for the scan size */ 3865141cc406Sopenharmony_ci /* wait_ready(s->fd); */ 3866141cc406Sopenharmony_ci#ifdef DEBUG 3867141cc406Sopenharmony_ci { 3868141cc406Sopenharmony_ci struct timeval t; 3869141cc406Sopenharmony_ci gettimeofday(&t, 0); 3870141cc406Sopenharmony_ci DBG(2, "rd: wait_ready ok %li.%06li\n", t.tv_sec, t.tv_usec); 3871141cc406Sopenharmony_ci } 3872141cc406Sopenharmony_ci#endif 3873141cc406Sopenharmony_ci sane_get_parameters(s, 0); 3874141cc406Sopenharmony_ci#ifdef DEBUG 3875141cc406Sopenharmony_ci { 3876141cc406Sopenharmony_ci struct timeval t; 3877141cc406Sopenharmony_ci gettimeofday(&t, 0); 3878141cc406Sopenharmony_ci DBG(2, "rd: get_params ok %li.%06li\n", t.tv_sec, t.tv_usec); 3879141cc406Sopenharmony_ci } 3880141cc406Sopenharmony_ci#endif 3881141cc406Sopenharmony_ci if (strcmp (mode, M_LINEART_COLOR) != 0) 3882141cc406Sopenharmony_ci s->bytes_to_read = s->params.bytes_per_line * s->params.lines; 3883141cc406Sopenharmony_ci else 3884141cc406Sopenharmony_ci { 3885141cc406Sopenharmony_ci s->bytes_to_read = (s->params.pixels_per_line+7) / 8; 3886141cc406Sopenharmony_ci s->bytes_to_read *= 3 * s->params.lines; 3887141cc406Sopenharmony_ci } 3888141cc406Sopenharmony_ci 3889141cc406Sopenharmony_ci#ifdef USE_FORK 3890141cc406Sopenharmony_ci { 3891141cc406Sopenharmony_ci size_t i; 3892141cc406Sopenharmony_ci for (i = 0; i < s->dev->info.buffers; i++) 3893141cc406Sopenharmony_ci s->rdr_ctl->buf_ctl[i].shm_status = SHM_EMPTY; 3894141cc406Sopenharmony_ci s->read_buff = 0; 3895141cc406Sopenharmony_ci s->rdr_ctl->cancel = 0; 3896141cc406Sopenharmony_ci s->rdr_ctl->running = 0; 3897141cc406Sopenharmony_ci s->rdr_ctl->status = SANE_STATUS_GOOD; 3898141cc406Sopenharmony_ci } 3899141cc406Sopenharmony_ci s->reader_pid = fork(); 3900141cc406Sopenharmony_ci#ifdef DEBUG 3901141cc406Sopenharmony_ci { 3902141cc406Sopenharmony_ci struct timeval t; 3903141cc406Sopenharmony_ci gettimeofday(&t, 0); 3904141cc406Sopenharmony_ci DBG(2, "rd: forked %li.%06li %i\n", t.tv_sec, t.tv_usec, 3905141cc406Sopenharmony_ci s->reader_pid); 3906141cc406Sopenharmony_ci } 3907141cc406Sopenharmony_ci#endif 3908141cc406Sopenharmony_ci if (s->reader_pid == 0) 3909141cc406Sopenharmony_ci { 3910141cc406Sopenharmony_ci sigset_t ignore_set; 3911141cc406Sopenharmony_ci struct SIGACTION act; 3912141cc406Sopenharmony_ci 3913141cc406Sopenharmony_ci sigfillset (&ignore_set); 3914141cc406Sopenharmony_ci sigdelset (&ignore_set, SIGTERM); 3915141cc406Sopenharmony_ci sigprocmask (SIG_SETMASK, &ignore_set, 0); 3916141cc406Sopenharmony_ci 3917141cc406Sopenharmony_ci memset (&act, 0, sizeof (act)); 3918141cc406Sopenharmony_ci sigaction (SIGTERM, &act, 0); 3919141cc406Sopenharmony_ci 3920141cc406Sopenharmony_ci /* don't use exit() since that would run the atexit() handlers... */ 3921141cc406Sopenharmony_ci _exit (reader_process (s)); 3922141cc406Sopenharmony_ci } 3923141cc406Sopenharmony_ci else if (s->reader_pid == -1) 3924141cc406Sopenharmony_ci { 3925141cc406Sopenharmony_ci s->busy = SANE_FALSE; 3926141cc406Sopenharmony_ci do_cancel(s); 3927141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3928141cc406Sopenharmony_ci } 3929141cc406Sopenharmony_ci 3930141cc406Sopenharmony_ci#endif /* USE_FORK */ 3931141cc406Sopenharmony_ci 3932141cc406Sopenharmony_ci 3933141cc406Sopenharmony_ci DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " 3934141cc406Sopenharmony_ci "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, 3935141cc406Sopenharmony_ci s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_X_RESOLUTION].w); 3936141cc406Sopenharmony_ci 3937141cc406Sopenharmony_ci s->busy = SANE_FALSE; 3938141cc406Sopenharmony_ci s->buf_used = 0; 3939141cc406Sopenharmony_ci s->buf_pos = 0; 3940141cc406Sopenharmony_ci 3941141cc406Sopenharmony_ci if (s->cancel == SANE_TRUE) 3942141cc406Sopenharmony_ci { 3943141cc406Sopenharmony_ci do_cancel(s); 3944141cc406Sopenharmony_ci DBG (10, ">>\n"); 3945141cc406Sopenharmony_ci return(SANE_STATUS_CANCELLED); 3946141cc406Sopenharmony_ci } 3947141cc406Sopenharmony_ci 3948141cc406Sopenharmony_ci DBG (10, ">>\n"); 3949141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3950141cc406Sopenharmony_ci 3951141cc406Sopenharmony_ci} 3952141cc406Sopenharmony_ci 3953141cc406Sopenharmony_cistatic SANE_Status 3954141cc406Sopenharmony_cisane_read_direct (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, 3955141cc406Sopenharmony_ci SANE_Int * len) 3956141cc406Sopenharmony_ci{ 3957141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 3958141cc406Sopenharmony_ci SANE_Status status; 3959141cc406Sopenharmony_ci size_t nread; 3960141cc406Sopenharmony_ci DBG (10, "<< sane_read_direct "); 3961141cc406Sopenharmony_ci 3962141cc406Sopenharmony_ci DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read); 3963141cc406Sopenharmony_ci *len = 0; 3964141cc406Sopenharmony_ci 3965141cc406Sopenharmony_ci if (s->bytes_to_read == 0) 3966141cc406Sopenharmony_ci { 3967141cc406Sopenharmony_ci do_cancel (s); 3968141cc406Sopenharmony_ci return (SANE_STATUS_EOF); 3969141cc406Sopenharmony_ci } 3970141cc406Sopenharmony_ci 3971141cc406Sopenharmony_ci if (!s->scanning) 3972141cc406Sopenharmony_ci return (do_cancel (s)); 3973141cc406Sopenharmony_ci nread = max_len; 3974141cc406Sopenharmony_ci if (nread > s->bytes_to_read) 3975141cc406Sopenharmony_ci nread = s->bytes_to_read; 3976141cc406Sopenharmony_ci if (nread > s->dev->info.bufsize) 3977141cc406Sopenharmony_ci nread = s->dev->info.bufsize; 3978141cc406Sopenharmony_ci#ifdef USE_FORK 3979141cc406Sopenharmony_ci status = read_data(s, dst_buf, &nread); 3980141cc406Sopenharmony_ci#else 3981141cc406Sopenharmony_ci wait_ready(s->fd); 3982141cc406Sopenharmony_ci status = read_data (s, dst_buf, &nread); 3983141cc406Sopenharmony_ci#endif 3984141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3985141cc406Sopenharmony_ci { 3986141cc406Sopenharmony_ci do_cancel (s); 3987141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 3988141cc406Sopenharmony_ci } 3989141cc406Sopenharmony_ci *len = nread; 3990141cc406Sopenharmony_ci s->bytes_to_read -= nread; 3991141cc406Sopenharmony_ci DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read); 3992141cc406Sopenharmony_ci 3993141cc406Sopenharmony_ci DBG (10, ">>\n"); 3994141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 3995141cc406Sopenharmony_ci} 3996141cc406Sopenharmony_ci 3997141cc406Sopenharmony_cistatic SANE_Status 3998141cc406Sopenharmony_cisane_read_shuffled (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, 3999141cc406Sopenharmony_ci SANE_Int * len, int eight_bit_data) 4000141cc406Sopenharmony_ci{ 4001141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 4002141cc406Sopenharmony_ci SANE_Status status; 4003141cc406Sopenharmony_ci SANE_Byte *dest, *red, *green, *blue, mask; 4004141cc406Sopenharmony_ci SANE_Int transfer; 4005141cc406Sopenharmony_ci size_t nread, ntest, pixel, max_pixel, line, max_line; 4006141cc406Sopenharmony_ci size_t start_input, bytes_per_line_in; 4007141cc406Sopenharmony_ci DBG (10, "<< sane_read_shuffled "); 4008141cc406Sopenharmony_ci 4009141cc406Sopenharmony_ci *len = 0; 4010141cc406Sopenharmony_ci if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) 4011141cc406Sopenharmony_ci { 4012141cc406Sopenharmony_ci do_cancel (s); 4013141cc406Sopenharmony_ci DBG (10, ">>\n"); 4014141cc406Sopenharmony_ci return (SANE_STATUS_EOF); 4015141cc406Sopenharmony_ci } 4016141cc406Sopenharmony_ci 4017141cc406Sopenharmony_ci if (!s->scanning) 4018141cc406Sopenharmony_ci { 4019141cc406Sopenharmony_ci DBG (10, ">>\n"); 4020141cc406Sopenharmony_ci return(do_cancel(s)); 4021141cc406Sopenharmony_ci } 4022141cc406Sopenharmony_ci 4023141cc406Sopenharmony_ci if (s->buf_pos < s->buf_used) 4024141cc406Sopenharmony_ci { 4025141cc406Sopenharmony_ci transfer = s->buf_used - s->buf_pos; 4026141cc406Sopenharmony_ci if (transfer > max_len) 4027141cc406Sopenharmony_ci transfer = max_len; 4028141cc406Sopenharmony_ci 4029141cc406Sopenharmony_ci memcpy(dst_buf, &(s->buffer[s->buf_pos]), transfer); 4030141cc406Sopenharmony_ci s->buf_pos += transfer; 4031141cc406Sopenharmony_ci max_len -= transfer; 4032141cc406Sopenharmony_ci *len = transfer; 4033141cc406Sopenharmony_ci } 4034141cc406Sopenharmony_ci 4035141cc406Sopenharmony_ci while (max_len > 0 && s->bytes_to_read > 0) 4036141cc406Sopenharmony_ci { 4037141cc406Sopenharmony_ci if (eight_bit_data) 4038141cc406Sopenharmony_ci { 4039141cc406Sopenharmony_ci nread = s->dev->info.bufsize / s->params.bytes_per_line - 1; 4040141cc406Sopenharmony_ci nread *= s->params.bytes_per_line; 4041141cc406Sopenharmony_ci if (nread > s->bytes_to_read) 4042141cc406Sopenharmony_ci nread = s->bytes_to_read; 4043141cc406Sopenharmony_ci max_line = nread / s->params.bytes_per_line; 4044141cc406Sopenharmony_ci start_input = s->params.bytes_per_line; 4045141cc406Sopenharmony_ci bytes_per_line_in = s->params.bytes_per_line; 4046141cc406Sopenharmony_ci } 4047141cc406Sopenharmony_ci else 4048141cc406Sopenharmony_ci { 4049141cc406Sopenharmony_ci bytes_per_line_in = (s->params.pixels_per_line + 7) / 8; 4050141cc406Sopenharmony_ci bytes_per_line_in *= 3; 4051141cc406Sopenharmony_ci max_line = s->params.bytes_per_line + bytes_per_line_in; 4052141cc406Sopenharmony_ci max_line = s->dev->info.bufsize / max_line; 4053141cc406Sopenharmony_ci nread = max_line * bytes_per_line_in; 4054141cc406Sopenharmony_ci if (nread > s->bytes_to_read) 4055141cc406Sopenharmony_ci { 4056141cc406Sopenharmony_ci nread = s->bytes_to_read; 4057141cc406Sopenharmony_ci max_line = nread / bytes_per_line_in; 4058141cc406Sopenharmony_ci } 4059141cc406Sopenharmony_ci start_input = s->dev->info.bufsize - nread; 4060141cc406Sopenharmony_ci } 4061141cc406Sopenharmony_ci ntest = nread; 4062141cc406Sopenharmony_ci 4063141cc406Sopenharmony_ci#ifdef USE_FORK 4064141cc406Sopenharmony_ci status = read_data (s, &(s->buffer[start_input]), &nread); 4065141cc406Sopenharmony_ci#else 4066141cc406Sopenharmony_ci wait_ready(s->fd); 4067141cc406Sopenharmony_ci status = read_data (s, &(s->buffer[start_input]), &nread); 4068141cc406Sopenharmony_ci#endif 4069141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 4070141cc406Sopenharmony_ci { 4071141cc406Sopenharmony_ci do_cancel (s); 4072141cc406Sopenharmony_ci DBG (10, ">>\n"); 4073141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 4074141cc406Sopenharmony_ci } 4075141cc406Sopenharmony_ci 4076141cc406Sopenharmony_ci if (nread != ntest) 4077141cc406Sopenharmony_ci { 4078141cc406Sopenharmony_ci /* if this happens, something is wrong in the input buffer 4079141cc406Sopenharmony_ci management... 4080141cc406Sopenharmony_ci */ 4081141cc406Sopenharmony_ci DBG(1, "Warning: could not read an integral number of scan lines\n"); 4082141cc406Sopenharmony_ci DBG(1, " image will be scrambled\n"); 4083141cc406Sopenharmony_ci } 4084141cc406Sopenharmony_ci 4085141cc406Sopenharmony_ci 4086141cc406Sopenharmony_ci s->buf_used = max_line * s->params.bytes_per_line; 4087141cc406Sopenharmony_ci s->buf_pos = 0; 4088141cc406Sopenharmony_ci s->bytes_to_read -= nread; 4089141cc406Sopenharmony_ci dest = s->buffer; 4090141cc406Sopenharmony_ci max_pixel = s->params.pixels_per_line; 4091141cc406Sopenharmony_ci 4092141cc406Sopenharmony_ci if (eight_bit_data) 4093141cc406Sopenharmony_ci for (line = 1; line <= max_line; line++) 4094141cc406Sopenharmony_ci { 4095141cc406Sopenharmony_ci red = &(s->buffer[line * s->params.bytes_per_line]); 4096141cc406Sopenharmony_ci green = &(red[max_pixel]); 4097141cc406Sopenharmony_ci blue = &(green[max_pixel]); 4098141cc406Sopenharmony_ci for (pixel = 0; pixel < max_pixel; pixel++) 4099141cc406Sopenharmony_ci { 4100141cc406Sopenharmony_ci *dest++ = *red++; 4101141cc406Sopenharmony_ci *dest++ = *green++; 4102141cc406Sopenharmony_ci *dest++ = *blue++; 4103141cc406Sopenharmony_ci } 4104141cc406Sopenharmony_ci } 4105141cc406Sopenharmony_ci else 4106141cc406Sopenharmony_ci for (line = 0; line < max_line; line++) 4107141cc406Sopenharmony_ci { 4108141cc406Sopenharmony_ci red = &(s->buffer[start_input + line * bytes_per_line_in]); 4109141cc406Sopenharmony_ci green = &(red[(max_pixel+7)/8]); 4110141cc406Sopenharmony_ci blue = &(green[(max_pixel+7)/8]); 4111141cc406Sopenharmony_ci mask = 0x80; 4112141cc406Sopenharmony_ci for (pixel = 0; pixel < max_pixel; pixel++) 4113141cc406Sopenharmony_ci { 4114141cc406Sopenharmony_ci *dest++ = (*red & mask) ? 0xff : 0; 4115141cc406Sopenharmony_ci *dest++ = (*green & mask) ? 0xff : 0; 4116141cc406Sopenharmony_ci *dest++ = (*blue & mask) ? 0xff : 0; 4117141cc406Sopenharmony_ci mask = mask >> 1; 4118141cc406Sopenharmony_ci if (mask == 0) 4119141cc406Sopenharmony_ci { 4120141cc406Sopenharmony_ci mask = 0x80; 4121141cc406Sopenharmony_ci red++; 4122141cc406Sopenharmony_ci green++; 4123141cc406Sopenharmony_ci blue++; 4124141cc406Sopenharmony_ci } 4125141cc406Sopenharmony_ci } 4126141cc406Sopenharmony_ci } 4127141cc406Sopenharmony_ci 4128141cc406Sopenharmony_ci transfer = max_len; 4129141cc406Sopenharmony_ci if (transfer > s->buf_used) 4130141cc406Sopenharmony_ci transfer = s->buf_used; 4131141cc406Sopenharmony_ci memcpy(&(dst_buf[*len]), s->buffer, transfer); 4132141cc406Sopenharmony_ci 4133141cc406Sopenharmony_ci max_len -= transfer; 4134141cc406Sopenharmony_ci s->buf_pos += transfer; 4135141cc406Sopenharmony_ci *len += transfer; 4136141cc406Sopenharmony_ci } 4137141cc406Sopenharmony_ci 4138141cc406Sopenharmony_ci if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) 4139141cc406Sopenharmony_ci do_cancel (s); 4140141cc406Sopenharmony_ci DBG (10, ">>\n"); 4141141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 4142141cc406Sopenharmony_ci} 4143141cc406Sopenharmony_ci 4144141cc406Sopenharmony_ciSANE_Status 4145141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, 4146141cc406Sopenharmony_ci SANE_Int * len) 4147141cc406Sopenharmony_ci{ 4148141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 4149141cc406Sopenharmony_ci SANE_Status status; 4150141cc406Sopenharmony_ci 4151141cc406Sopenharmony_ci s->busy = SANE_TRUE; 4152141cc406Sopenharmony_ci if (s->cancel == SANE_TRUE) 4153141cc406Sopenharmony_ci { 4154141cc406Sopenharmony_ci do_cancel(s); 4155141cc406Sopenharmony_ci *len = 0; 4156141cc406Sopenharmony_ci return (SANE_STATUS_CANCELLED); 4157141cc406Sopenharmony_ci } 4158141cc406Sopenharmony_ci 4159141cc406Sopenharmony_ci /* RGB scans with a JX 250 and bi-level color scans 4160141cc406Sopenharmony_ci must be handled differently: */ 4161141cc406Sopenharmony_ci if (s->image_composition <= 2) 4162141cc406Sopenharmony_ci status = sane_read_direct(handle, dst_buf, max_len, len); 4163141cc406Sopenharmony_ci else if (s->image_composition <= 4) 4164141cc406Sopenharmony_ci status = sane_read_shuffled(handle, dst_buf, max_len, len, 0); 4165141cc406Sopenharmony_ci else if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350 ) 4166141cc406Sopenharmony_ci status = sane_read_direct(handle, dst_buf, max_len, len); 4167141cc406Sopenharmony_ci else 4168141cc406Sopenharmony_ci status = sane_read_shuffled(handle, dst_buf, max_len, len, 1); 4169141cc406Sopenharmony_ci 4170141cc406Sopenharmony_ci s->busy = SANE_FALSE; 4171141cc406Sopenharmony_ci if (s->cancel == SANE_TRUE) 4172141cc406Sopenharmony_ci { 4173141cc406Sopenharmony_ci do_cancel(s); 4174141cc406Sopenharmony_ci return (SANE_STATUS_CANCELLED); 4175141cc406Sopenharmony_ci } 4176141cc406Sopenharmony_ci 4177141cc406Sopenharmony_ci return (status); 4178141cc406Sopenharmony_ci} 4179141cc406Sopenharmony_ci 4180141cc406Sopenharmony_civoid 4181141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 4182141cc406Sopenharmony_ci{ 4183141cc406Sopenharmony_ci SHARP_Scanner *s = handle; 4184141cc406Sopenharmony_ci DBG (10, "<< sane_cancel "); 4185141cc406Sopenharmony_ci 4186141cc406Sopenharmony_ci s->cancel = SANE_TRUE; 4187141cc406Sopenharmony_ci if (s->busy == SANE_FALSE) 4188141cc406Sopenharmony_ci do_cancel(s); 4189141cc406Sopenharmony_ci 4190141cc406Sopenharmony_ci DBG (10, ">>\n"); 4191141cc406Sopenharmony_ci} 4192141cc406Sopenharmony_ci 4193141cc406Sopenharmony_ciSANE_Status 4194141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, 4195141cc406Sopenharmony_ci SANE_Bool __sane_unused__ non_blocking) 4196141cc406Sopenharmony_ci{ 4197141cc406Sopenharmony_ci DBG (10, "<< sane_set_io_mode"); 4198141cc406Sopenharmony_ci DBG (10, ">>\n"); 4199141cc406Sopenharmony_ci 4200141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 4201141cc406Sopenharmony_ci} 4202141cc406Sopenharmony_ci 4203141cc406Sopenharmony_ciSANE_Status 4204141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, 4205141cc406Sopenharmony_ci SANE_Int __sane_unused__ * fd) 4206141cc406Sopenharmony_ci{ 4207141cc406Sopenharmony_ci DBG (10, "<< sane_get_select_fd"); 4208141cc406Sopenharmony_ci DBG (10, ">>\n"); 4209141cc406Sopenharmony_ci 4210141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 4211141cc406Sopenharmony_ci} 4212