1141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 2141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 3141cc406Sopenharmony_ci coolscan.c , version 0.4.4 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This file is part of the SANE package. 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 8141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 9141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 10141cc406Sopenharmony_ci License, or (at your option) any later version. 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 13141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 14141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15141cc406Sopenharmony_ci General Public License for more details. 16141cc406Sopenharmony_ci 17141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 18141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 21141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 24141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 25141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 26141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 27141cc406Sopenharmony_ci account of linking the SANE library code into it. 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 30141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 31141cc406Sopenharmony_ci License. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 34141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 35141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 38141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 39141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci This file implements a SANE backend for COOLSCAN flatbed scanners. */ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci/* SANE-FLOW-DIAGRAMM 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci - sane_init() : initialize backend, attach scanners 49141cc406Sopenharmony_ci . - sane_get_devices() : query list of scanner-devices 50141cc406Sopenharmony_ci . - sane_open() : open a particular scanner-device 51141cc406Sopenharmony_ci . . - sane_set_io_mode : set blocking-mode 52141cc406Sopenharmony_ci . . - sane_get_select_fd : get scanner-fd 53141cc406Sopenharmony_ci . . - sane_get_option_descriptor() : get option information 54141cc406Sopenharmony_ci . . - sane_control_option() : change option values 55141cc406Sopenharmony_ci . . 56141cc406Sopenharmony_ci . . - sane_start() : start image acquisition 57141cc406Sopenharmony_ci . . - sane_get_parameters() : returns actual scan-parameters 58141cc406Sopenharmony_ci . . - sane_read() : read image-data (from pipe) 59141cc406Sopenharmony_ci . . 60141cc406Sopenharmony_ci . . - sane_cancel() : cancel operation 61141cc406Sopenharmony_ci . - sane_close() : close opened scanner-device 62141cc406Sopenharmony_ci - sane_exit() : terminate use of backend 63141cc406Sopenharmony_ci */ 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci#ifdef _AIX 66141cc406Sopenharmony_ci# include "lalloca.h" /* MUST come first for AIX! */ 67141cc406Sopenharmony_ci#endif 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci#include "../include/sane/config.h" 70141cc406Sopenharmony_ci#include "lalloca.h" 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci#include <errno.h> 73141cc406Sopenharmony_ci#include <math.h> 74141cc406Sopenharmony_ci#include <fcntl.h> 75141cc406Sopenharmony_ci#include <limits.h> 76141cc406Sopenharmony_ci#include <signal.h> 77141cc406Sopenharmony_ci#include <stdio.h> 78141cc406Sopenharmony_ci#include <stdlib.h> 79141cc406Sopenharmony_ci#include <string.h> 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci#include <sys/types.h> 82141cc406Sopenharmony_ci#include <unistd.h> 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci#include "../include/sane/sane.h" 85141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 86141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 87141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 88141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 89141cc406Sopenharmony_ci#include "../include/sane/sanei_thread.h" 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 92141cc406Sopenharmony_ci#define COOLSCAN_CONFIG_FILE "coolscan.conf" 93141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 94141cc406Sopenharmony_ci 95141cc406Sopenharmony_ci#include "coolscan.h" 96141cc406Sopenharmony_ci#include "coolscan-scsidef.h" 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci#ifndef PATH_MAX 100141cc406Sopenharmony_ci#define PATH_MAX 1024 101141cc406Sopenharmony_ci#endif 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 104141cc406Sopenharmony_cistatic const SANE_Int resolution_list[] = 105141cc406Sopenharmony_ci{ 106141cc406Sopenharmony_ci 25, 107141cc406Sopenharmony_ci 2700, 1350, 900, 675, 540, 450, 385, 337, 300, 270, 245, 225, 207, 108141cc406Sopenharmony_ci 192, 180, 168, 158, 150, 142, 135, 128, 122, 117, 112, 108 109141cc406Sopenharmony_ci}; 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci#define coolscan_do_scsi_open(dev, fd, handler) sanei_scsi_open(dev, fd, handler) 113141cc406Sopenharmony_ci#define coolscan_do_scsi_close(fd) sanei_scsi_close(fd) 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_ci#define COOLSCAN_MAX_RETRY 25 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_cistatic SANE_Status sense_handler (int scsi_fd, unsigned char * result, void *arg); 119141cc406Sopenharmony_cistatic int coolscan_check_values (Coolscan_t * s); 120141cc406Sopenharmony_cistatic int get_internal_info (Coolscan_t *); 121141cc406Sopenharmony_cistatic void coolscan_get_inquiry_values (Coolscan_t *); 122141cc406Sopenharmony_cistatic void hexdump (int level, char *comment, unsigned char *p, int l); 123141cc406Sopenharmony_cistatic int swap_res (Coolscan_t * s); 124141cc406Sopenharmony_ci/* --------------------------- COOLSCAN_DO_SCSI_CMD ----------------------- */ 125141cc406Sopenharmony_cistatic int 126141cc406Sopenharmony_cido_scsi_cmd (int fd, unsigned char *cmd, int cmd_len, unsigned char *out, size_t out_len) 127141cc406Sopenharmony_ci{ 128141cc406Sopenharmony_ci int ret; 129141cc406Sopenharmony_ci size_t ol = out_len; 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci hexdump (20, "", cmd, cmd_len); 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ci ret = sanei_scsi_cmd (fd, cmd, cmd_len, out, &ol); 134141cc406Sopenharmony_ci if ((out_len != 0) && (out_len != ol)) 135141cc406Sopenharmony_ci { 136141cc406Sopenharmony_ci DBG (1, "sanei_scsi_cmd: asked %lu bytes, got %lu\n", 137141cc406Sopenharmony_ci (u_long) out_len, (u_long) ol); 138141cc406Sopenharmony_ci } 139141cc406Sopenharmony_ci if (ret) 140141cc406Sopenharmony_ci { 141141cc406Sopenharmony_ci DBG (1, "sanei_scsi_cmd: returning 0x%08x\n", ret); 142141cc406Sopenharmony_ci } 143141cc406Sopenharmony_ci DBG (10, "sanei_scsi_cmd: returning %lu bytes:\n", (u_long) ol); 144141cc406Sopenharmony_ci if (out != NULL && out_len != 0) 145141cc406Sopenharmony_ci hexdump (15, "", out, (out_len > 0x60) ? 0x60 : out_len); 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci return ret; 148141cc406Sopenharmony_ci} 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_cistatic int 152141cc406Sopenharmony_cirequest_sense_parse (unsigned char *sensed_data) 153141cc406Sopenharmony_ci{ 154141cc406Sopenharmony_ci int ret, sense, asc, ascq; 155141cc406Sopenharmony_ci sense = get_RS_sense_key (sensed_data); 156141cc406Sopenharmony_ci asc = get_RS_ASC (sensed_data); 157141cc406Sopenharmony_ci ascq = get_RS_ASCQ (sensed_data); 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_ci ret = SANE_STATUS_IO_ERROR; 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci switch (sense) 162141cc406Sopenharmony_ci { 163141cc406Sopenharmony_ci case 0x0: 164141cc406Sopenharmony_ci DBG (5, "\t%d/%d/%d: Scanner ready\n", sense, asc, ascq); 165141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_ci case 0x1: 168141cc406Sopenharmony_ci if ((0x37 == asc) && (0x00 == ascq)) { 169141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Rounded Parameter\n", sense, asc, ascq); 170141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 171141cc406Sopenharmony_ci } 172141cc406Sopenharmony_ci else if ((0x61 == asc) && (0x02 == ascq)) 173141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Out Of Focus\n", sense, asc, ascq); 174141cc406Sopenharmony_ci else 175141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 176141cc406Sopenharmony_ci break; 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci case 0x2: 179141cc406Sopenharmony_ci if ((0x4 == asc) && (0x1 == ascq)) { 180141cc406Sopenharmony_ci DBG (10, "\t%d/%d/%d: Logical unit is in process of becoming ready\n", 181141cc406Sopenharmony_ci sense, asc, ascq); 182141cc406Sopenharmony_ci ret = SANE_STATUS_DEVICE_BUSY; 183141cc406Sopenharmony_ci } 184141cc406Sopenharmony_ci else if ((0x3A == asc) && (0x00 == ascq)) 185141cc406Sopenharmony_ci { 186141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: No Diapo inserted\n", sense, asc, ascq); 187141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 188141cc406Sopenharmony_ci } 189141cc406Sopenharmony_ci else if ((0x60 == asc) && (0x00 == ascq)) 190141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Lamp Failure\n", sense, asc, ascq); 191141cc406Sopenharmony_ci else 192141cc406Sopenharmony_ci { 193141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 194141cc406Sopenharmony_ci ret = SANE_STATUS_GOOD; 195141cc406Sopenharmony_ci } 196141cc406Sopenharmony_ci break; 197141cc406Sopenharmony_ci 198141cc406Sopenharmony_ci case 0x3: 199141cc406Sopenharmony_ci if ((0x3b == asc) && (0xe == ascq)) 200141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Medium source element empty\n", sense, asc, ascq); 201141cc406Sopenharmony_ci else if ((0x53 == asc) && (0x00 == ascq)) 202141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Media Load of Eject Failed\n", sense, asc, ascq); 203141cc406Sopenharmony_ci else 204141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 205141cc406Sopenharmony_ci break; 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci case 0x4: 208141cc406Sopenharmony_ci if ((0x15 == asc) && (0x1 == ascq)) 209141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Mechanical Positioning Error\n", sense, asc, ascq); 210141cc406Sopenharmony_ci else 211141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 212141cc406Sopenharmony_ci break; 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci case 0x5: 215141cc406Sopenharmony_ci if ((0x00 == asc) && (0x5 == ascq)) 216141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: End-Of-Data Detected\n", sense, asc, ascq); 217141cc406Sopenharmony_ci else if ((0x1a == asc) && (0x00 == ascq)) 218141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Parameter List Length Error\n", sense, asc, ascq); 219141cc406Sopenharmony_ci else if ((0x20 == asc) && (0x00 == ascq)) 220141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid Command Operation Code\n", sense, asc, ascq); 221141cc406Sopenharmony_ci else if ((0x24 == asc) && (0x00 == ascq)) 222141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid Field In CDB\n", sense, asc, ascq); 223141cc406Sopenharmony_ci else if ((0x25 == asc) && (0x00 == ascq)) 224141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Logical Unit Not Supported\n", sense, asc, ascq); 225141cc406Sopenharmony_ci else if ((0x26 == asc) && (0x00 == ascq)) 226141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid Field in Parameter List\n", sense, asc, ascq); 227141cc406Sopenharmony_ci else if ((0x2c == asc) && (0x00 == ascq)) 228141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Command Sequence Error\n", sense, asc, ascq); 229141cc406Sopenharmony_ci else if ((0x39 == asc) && (0x00 == ascq)) 230141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Saving Parameters Not Supported\n", sense, asc, ascq); 231141cc406Sopenharmony_ci else if ((0x3d == asc) && (0x00 == ascq)) 232141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid Bits In Identify Message\n", sense, asc, ascq); 233141cc406Sopenharmony_ci else 234141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 235141cc406Sopenharmony_ci break; 236141cc406Sopenharmony_ci 237141cc406Sopenharmony_ci case 0x6: 238141cc406Sopenharmony_ci if ((0x29 == asc) && (0x0 == ascq)) 239141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Power On, Reset, or Bus Device Reset Occurred\n", sense, asc, ascq); 240141cc406Sopenharmony_ci else if ((0x2a == asc) && (0x1 == ascq)) 241141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Mode Parameters Changed\n", sense, asc, ascq); 242141cc406Sopenharmony_ci else 243141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 244141cc406Sopenharmony_ci break; 245141cc406Sopenharmony_ci 246141cc406Sopenharmony_ci case 0xb: 247141cc406Sopenharmony_ci if ((0x43 == asc) && (0x0 == ascq)) 248141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Message Error\n", sense, asc, ascq); 249141cc406Sopenharmony_ci else if ((0x47 == asc) && (0x0 == ascq)) 250141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: SCSI Parity Error\n", sense, asc, ascq); 251141cc406Sopenharmony_ci else if ((0x48 == asc) && (0x0 == ascq)) 252141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Initiator Detected Error Message Received\n", sense, asc, ascq); 253141cc406Sopenharmony_ci else if ((0x49 == asc) && (0x0 == ascq)) 254141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Invalid Message Error\n", sense, asc, ascq); 255141cc406Sopenharmony_ci else if ((0x4e == asc) && (0x0 == ascq)) 256141cc406Sopenharmony_ci DBG (1, "\t%d/%d/%d: Overlapped Commands Attempted\n", sense, asc, ascq); 257141cc406Sopenharmony_ci else 258141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 259141cc406Sopenharmony_ci break; 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci default: 262141cc406Sopenharmony_ci DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); 263141cc406Sopenharmony_ci break; 264141cc406Sopenharmony_ci } /* switch */ 265141cc406Sopenharmony_ci return ret; 266141cc406Sopenharmony_ci} 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci/* 269141cc406Sopenharmony_ci * wait_scanner should spin until TEST_UNIT_READY returns 0 (GOOD) 270141cc406Sopenharmony_ci * returns 0 on success, 271141cc406Sopenharmony_ci * returns -1 on error. 272141cc406Sopenharmony_ci */ 273141cc406Sopenharmony_cistatic int 274141cc406Sopenharmony_ciwait_scanner (Coolscan_t * s) 275141cc406Sopenharmony_ci{ 276141cc406Sopenharmony_ci int ret = -1; 277141cc406Sopenharmony_ci int cnt = 0; 278141cc406Sopenharmony_ci DBG (10, "wait_scanner: Testing if scanner is ready\n"); 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci while (ret != 0) 281141cc406Sopenharmony_ci { 282141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, test_unit_ready.cmd, 283141cc406Sopenharmony_ci test_unit_ready.size, 0, 0); 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci if (ret == SANE_STATUS_DEVICE_BUSY) 286141cc406Sopenharmony_ci { 287141cc406Sopenharmony_ci usleep (500000); /* wait 0.5 seconds */ 288141cc406Sopenharmony_ci if (cnt++ > 40) 289141cc406Sopenharmony_ci { /* 20 sec. max (prescan takes up to 15 sec. */ 290141cc406Sopenharmony_ci DBG (1, "wait_scanner: scanner does NOT get ready\n"); 291141cc406Sopenharmony_ci return -1; 292141cc406Sopenharmony_ci } 293141cc406Sopenharmony_ci } 294141cc406Sopenharmony_ci else if (ret == SANE_STATUS_GOOD) 295141cc406Sopenharmony_ci { 296141cc406Sopenharmony_ci DBG (10, "wait_scanner: scanner is ready\n"); 297141cc406Sopenharmony_ci return ret; 298141cc406Sopenharmony_ci } 299141cc406Sopenharmony_ci else 300141cc406Sopenharmony_ci { 301141cc406Sopenharmony_ci DBG (1, "wait_scanner: test unit ready failed (%s)\n", 302141cc406Sopenharmony_ci sane_strstatus (ret)); 303141cc406Sopenharmony_ci } 304141cc406Sopenharmony_ci } 305141cc406Sopenharmony_ci return 0; 306141cc406Sopenharmony_ci} 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci/* ------------------------- COOLSCAN GRAB SCANNER ----------------------------- */ 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_ci/* coolscan_grab_scanner should go through the following command sequence: 312141cc406Sopenharmony_ci * TEST UNIT READY 313141cc406Sopenharmony_ci * CHECK CONDITION \ 314141cc406Sopenharmony_ci * REQUEST SENSE > These should be handled automagically by 315141cc406Sopenharmony_ci * UNIT ATTENTION / the kernel if they happen (powerup/reset) 316141cc406Sopenharmony_ci * TEST UNIT READY 317141cc406Sopenharmony_ci * GOOD 318141cc406Sopenharmony_ci * RESERVE UNIT 319141cc406Sopenharmony_ci * GOOD 320141cc406Sopenharmony_ci * 321141cc406Sopenharmony_ci * It is then responsible for installing appropriate signal handlers 322141cc406Sopenharmony_ci * to call emergency_give_scanner() if user aborts. 323141cc406Sopenharmony_ci */ 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_cistatic int 326141cc406Sopenharmony_cicoolscan_grab_scanner (Coolscan_t * s) 327141cc406Sopenharmony_ci{ 328141cc406Sopenharmony_ci int ret; 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci DBG (10, "grabbing scanner\n"); 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci wait_scanner (s); /* wait for scanner ready, if not print 333141cc406Sopenharmony_ci sense and return 1 */ 334141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, reserve_unit.cmd, reserve_unit.size, NULL, 0); 335141cc406Sopenharmony_ci if (ret) 336141cc406Sopenharmony_ci return ret; 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci DBG (10, "scanner reserved\n"); 339141cc406Sopenharmony_ci return 0; 340141cc406Sopenharmony_ci} 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci/* 343141cc406Sopenharmony_ci * Convert a size in ilu to the units expected by the scanner 344141cc406Sopenharmony_ci */ 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_cistatic int 347141cc406Sopenharmony_ciresDivToVal (int res_div) 348141cc406Sopenharmony_ci{ 349141cc406Sopenharmony_ci if (res_div < 1 || res_div > resolution_list[0]) 350141cc406Sopenharmony_ci { 351141cc406Sopenharmony_ci DBG (1, "Invalid resolution divisor %d \n", res_div); 352141cc406Sopenharmony_ci return 2700; 353141cc406Sopenharmony_ci } 354141cc406Sopenharmony_ci else 355141cc406Sopenharmony_ci { 356141cc406Sopenharmony_ci return resolution_list[res_div]; 357141cc406Sopenharmony_ci } 358141cc406Sopenharmony_ci} 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_cistatic int 361141cc406Sopenharmony_ciresValToDiv (int res_val) 362141cc406Sopenharmony_ci{ 363141cc406Sopenharmony_ci int res_div; 364141cc406Sopenharmony_ci int max_res = resolution_list[0]; 365141cc406Sopenharmony_ci for (res_div = 1; res_div <= max_res; res_div++) 366141cc406Sopenharmony_ci { 367141cc406Sopenharmony_ci if (resolution_list[res_div] == res_val) 368141cc406Sopenharmony_ci break; 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci if (res_div > max_res) 371141cc406Sopenharmony_ci { 372141cc406Sopenharmony_ci DBG (1, "Invalid resolution value\n"); 373141cc406Sopenharmony_ci return 1; 374141cc406Sopenharmony_ci } 375141cc406Sopenharmony_ci else 376141cc406Sopenharmony_ci { 377141cc406Sopenharmony_ci return res_div; 378141cc406Sopenharmony_ci } 379141cc406Sopenharmony_ci} 380141cc406Sopenharmony_ci/* 381141cc406Sopenharmony_ci * use mode select to force a measurement divisor of 2700 382141cc406Sopenharmony_ci */ 383141cc406Sopenharmony_cistatic unsigned char mode_select[] = 384141cc406Sopenharmony_ci{ 385141cc406Sopenharmony_ci MODE_SELECT, 0x10, 0, 0, 20, 0, 386141cc406Sopenharmony_ci 0, 0, 0, 8, 387141cc406Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 1, 388141cc406Sopenharmony_ci 3, 6, 0, 0, 0xA, 0x8C, 0, 0}; 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_cistatic int 391141cc406Sopenharmony_ciselect_MUD (Coolscan_t * s) 392141cc406Sopenharmony_ci{ 393141cc406Sopenharmony_ci return do_scsi_cmd (s->sfd, mode_select, 26, NULL, 0); 394141cc406Sopenharmony_ci} 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_cistatic int 397141cc406Sopenharmony_cicoolscan_autofocus_LS30 (Coolscan_t * s) 398141cc406Sopenharmony_ci{ 399141cc406Sopenharmony_ci int x, y; 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci wait_scanner(s); 402141cc406Sopenharmony_ci memcpy(s->buffer, autofocusLS30.cmd, autofocusLS30.size); 403141cc406Sopenharmony_ci memcpy(s->buffer+ autofocusLS30.size, autofocuspos, 9); 404141cc406Sopenharmony_ci 405141cc406Sopenharmony_ci x = s->xmaxpix - (s->brx + s->tlx) / 2; 406141cc406Sopenharmony_ci y = (s->bry + s->tly) / 2; 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci DBG (10, "Attempting AutoFocus at x=%d, y=%d\n", x, y); 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, s->buffer, 411141cc406Sopenharmony_ci autofocusLS30.size + 9, NULL, 0); 412141cc406Sopenharmony_ci /* Trashes when used in combination with scsi-driver AM53C974.o */ 413141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, command_c1.cmd, 414141cc406Sopenharmony_ci command_c1.size, NULL, 0); 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci DBG (10, "\tWaiting end of Autofocus\n"); 417141cc406Sopenharmony_ci wait_scanner (s); 418141cc406Sopenharmony_ci DBG (10, "AutoFocused.\n"); 419141cc406Sopenharmony_ci return 0; 420141cc406Sopenharmony_ci} 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_cistatic int 423141cc406Sopenharmony_cicoolscan_autofocus (Coolscan_t * s) 424141cc406Sopenharmony_ci{ 425141cc406Sopenharmony_ci int x, y; 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci if(s->LS>=2) 428141cc406Sopenharmony_ci { return coolscan_autofocus_LS30(s); 429141cc406Sopenharmony_ci } 430141cc406Sopenharmony_ci 431141cc406Sopenharmony_ci wait_scanner(s); 432141cc406Sopenharmony_ci memcpy(s->buffer, autofocus.cmd, autofocus.size); 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci x = s->xmaxpix - (s->brx + s->tlx) / 2; 435141cc406Sopenharmony_ci y = (s->bry + s->tly) / 2; 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci DBG (10, "Attempting AutoFocus at x=%d, y=%d\n", x, y); 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_ci set_AF_XPoint (s->buffer, x); 440141cc406Sopenharmony_ci set_AF_YPoint (s->buffer, y); 441141cc406Sopenharmony_ci 442141cc406Sopenharmony_ci set_AF_transferlength (s->buffer, 0); /* should be 8 !*/ 443141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, s->buffer, 444141cc406Sopenharmony_ci autofocus.size + AF_Point_length, NULL, 0); 445141cc406Sopenharmony_ci 446141cc406Sopenharmony_ci sleep(5); /* autofocus takes a minimum of 5 sec. */ 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci DBG (10, "\tWaiting end of Autofocus\n"); 449141cc406Sopenharmony_ci wait_scanner (s); 450141cc406Sopenharmony_ci DBG (10, "AutoFocused.\n"); 451141cc406Sopenharmony_ci return 0; 452141cc406Sopenharmony_ci} 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci/* 455141cc406Sopenharmony_ci static int 456141cc406Sopenharmony_ci coolscan_abort_scan (Coolscan_t * s) 457141cc406Sopenharmony_ci { 458141cc406Sopenharmony_ci int ret; 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci DBG (5, "Aborting scan...\n"); 461141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, sabort.cmd, sabort.size, NULL, 0); 462141cc406Sopenharmony_ci if (ret) 463141cc406Sopenharmony_ci DBG (5, "Scan Aborted\n"); 464141cc406Sopenharmony_ci else 465141cc406Sopenharmony_ci DBG (5, "Not scanning\n"); 466141cc406Sopenharmony_ci return 0; 467141cc406Sopenharmony_ci } 468141cc406Sopenharmony_ci */ 469141cc406Sopenharmony_cistatic int 470141cc406Sopenharmony_cicoolscan_mode_sense (Coolscan_t * s) 471141cc406Sopenharmony_ci{ 472141cc406Sopenharmony_ci int ret, len; 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci DBG (10, "Mode Sense...\n"); 475141cc406Sopenharmony_ci len = 12; 476141cc406Sopenharmony_ci set_MS_DBD (mode_sense.cmd, 1); 477141cc406Sopenharmony_ci set_MS_len (mode_sense.cmd, len); 478141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, mode_sense.cmd, mode_sense.size, 479141cc406Sopenharmony_ci s->buffer, len); 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci if (ret == 0) 482141cc406Sopenharmony_ci { 483141cc406Sopenharmony_ci s->MUD = get_MS_MUD (s->buffer); 484141cc406Sopenharmony_ci DBG (10, "\tMode Sensed (MUD is %d)\n", s->MUD); 485141cc406Sopenharmony_ci } 486141cc406Sopenharmony_ci return ret; 487141cc406Sopenharmony_ci} 488141cc406Sopenharmony_ci 489141cc406Sopenharmony_cistatic int 490141cc406Sopenharmony_cicoolscan_object_discharge (Coolscan_t * s) 491141cc406Sopenharmony_ci{ 492141cc406Sopenharmony_ci int ret; 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci DBG (10, "Trying to discharge object...\n"); 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci memcpy (s->buffer, object_position.cmd, object_position.size); 497141cc406Sopenharmony_ci set_OP_autofeed (s->buffer, OP_Discharge); 498141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, s->buffer, 499141cc406Sopenharmony_ci object_position.size, NULL, 0); 500141cc406Sopenharmony_ci wait_scanner (s); 501141cc406Sopenharmony_ci DBG (10, "Object discharged.\n"); 502141cc406Sopenharmony_ci return ret; 503141cc406Sopenharmony_ci} 504141cc406Sopenharmony_ci 505141cc406Sopenharmony_cistatic int 506141cc406Sopenharmony_cicoolscan_object_feed (Coolscan_t * s) 507141cc406Sopenharmony_ci{ 508141cc406Sopenharmony_ci int ret; 509141cc406Sopenharmony_ci DBG (10, "Trying to feed object...\n"); 510141cc406Sopenharmony_ci if (!s->asf) 511141cc406Sopenharmony_ci { 512141cc406Sopenharmony_ci DBG (10, "\tAutofeeder not present.\n"); 513141cc406Sopenharmony_ci return 0; 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci memcpy (s->buffer, object_position.cmd, object_position.size); 516141cc406Sopenharmony_ci set_OP_autofeed (s->buffer, OP_Feed); 517141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, s->buffer, 518141cc406Sopenharmony_ci object_position.size, NULL, 0); 519141cc406Sopenharmony_ci wait_scanner (s); 520141cc406Sopenharmony_ci DBG (10, "Object fed.\n"); 521141cc406Sopenharmony_ci return ret; 522141cc406Sopenharmony_ci} 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_ci/* coolscan_give_scanner should go through the following sequence: 525141cc406Sopenharmony_ci * OBJECT POSITION DISCHARGE 526141cc406Sopenharmony_ci * GOOD 527141cc406Sopenharmony_ci * RELEASE UNIT 528141cc406Sopenharmony_ci * GOOD 529141cc406Sopenharmony_ci */ 530141cc406Sopenharmony_cistatic int 531141cc406Sopenharmony_cicoolscan_give_scanner (Coolscan_t * s) 532141cc406Sopenharmony_ci{ 533141cc406Sopenharmony_ci DBG (10, "trying to release scanner ...\n"); 534141cc406Sopenharmony_ci coolscan_object_discharge (s); 535141cc406Sopenharmony_ci wait_scanner (s); 536141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, release_unit.cmd, release_unit.size, NULL, 0); 537141cc406Sopenharmony_ci DBG (10, "scanner released\n"); 538141cc406Sopenharmony_ci return 0; 539141cc406Sopenharmony_ci} 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_cistatic int 543141cc406Sopenharmony_cicoolscan_set_window_param_LS20 (Coolscan_t * s, int prescan) 544141cc406Sopenharmony_ci{ 545141cc406Sopenharmony_ci unsigned char buffer_r[max_WDB_size]; 546141cc406Sopenharmony_ci int ret; 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci wait_scanner (s); 549141cc406Sopenharmony_ci memset (buffer_r, '\0', max_WDB_size); /* clear buffer */ 550141cc406Sopenharmony_ci memcpy (buffer_r, window_descriptor_block.cmd, 551141cc406Sopenharmony_ci window_descriptor_block.size); /* copy preset data */ 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_ci set_WD_wid (buffer_r, WD_wid_all); /* window identifier */ 554141cc406Sopenharmony_ci set_WD_auto (buffer_r, s->set_auto); /* 0 or 1: don't know what it is */ 555141cc406Sopenharmony_ci 556141cc406Sopenharmony_ci set_WD_negative (buffer_r, s->negative); /* Negative/positive slide */ 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci if (prescan) 559141cc406Sopenharmony_ci { 560141cc406Sopenharmony_ci set_WD_scanmode (buffer_r, WD_Prescan); 561141cc406Sopenharmony_ci } 562141cc406Sopenharmony_ci else 563141cc406Sopenharmony_ci { 564141cc406Sopenharmony_ci set_WD_scanmode (buffer_r, WD_Scan); 565141cc406Sopenharmony_ci 566141cc406Sopenharmony_ci /* geometry */ 567141cc406Sopenharmony_ci set_WD_Xres (buffer_r, resDivToVal (s->x_nres)); /* x resolution in dpi */ 568141cc406Sopenharmony_ci set_WD_Yres (buffer_r, resDivToVal (s->y_nres)); /* y resolution in dpi */ 569141cc406Sopenharmony_ci 570141cc406Sopenharmony_ci /* the coolscan uses the upper right corner as the origin of coordinates */ 571141cc406Sopenharmony_ci /* xmax and ymax are given in 1200 dpi */ 572141cc406Sopenharmony_ci set_WD_ULX (buffer_r, (s->xmaxpix - s->brx)); 573141cc406Sopenharmony_ci set_WD_ULY (buffer_r, s->tly); /* upper_edge y */ 574141cc406Sopenharmony_ci set_WD_width (buffer_r, (s->brx - s->tlx + 1)); 575141cc406Sopenharmony_ci set_WD_length (buffer_r, (s->bry - s->tly + 1)); 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci /* BTC */ 578141cc406Sopenharmony_ci if (s->brightness == 128) 579141cc406Sopenharmony_ci { 580141cc406Sopenharmony_ci set_WD_brightness (buffer_r, 0); 581141cc406Sopenharmony_ci } 582141cc406Sopenharmony_ci else 583141cc406Sopenharmony_ci { 584141cc406Sopenharmony_ci set_WD_brightness (buffer_r, s->brightness); /* brightness */ 585141cc406Sopenharmony_ci } 586141cc406Sopenharmony_ci 587141cc406Sopenharmony_ci if (s->contrast == 128) 588141cc406Sopenharmony_ci { 589141cc406Sopenharmony_ci set_WD_contrast (buffer_r, 0); 590141cc406Sopenharmony_ci } 591141cc406Sopenharmony_ci else 592141cc406Sopenharmony_ci { 593141cc406Sopenharmony_ci set_WD_contrast (buffer_r, s->contrast); /* contrast */ 594141cc406Sopenharmony_ci } 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci /* scanmode */ 597141cc406Sopenharmony_ci if (s->colormode == GREYSCALE) 598141cc406Sopenharmony_ci set_WD_composition (buffer_r, WD_comp_grey); /* GRAY composition */ 599141cc406Sopenharmony_ci else 600141cc406Sopenharmony_ci set_WD_composition (buffer_r, WD_comp_rgb_full); /* RGB composition */ 601141cc406Sopenharmony_ci 602141cc406Sopenharmony_ci set_WD_dropoutcolor (buffer_r, s->dropoutcolor); /* Which color to scan with when grayscale scan */ 603141cc406Sopenharmony_ci set_WD_transfermode (buffer_r, WD_LineSequence); 604141cc406Sopenharmony_ci set_WD_gammaselection (buffer_r, s->gammaselection); /* monitor/linear */ 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_ci set_WD_shading (buffer_r, WD_Shading_ON); /* default for non-manufacturing */ 607141cc406Sopenharmony_ci 608141cc406Sopenharmony_ci if (1 == s->LS) 609141cc406Sopenharmony_ci { /* Analog gamma reserved on LS-1000 */ 610141cc406Sopenharmony_ci set_WD_analog_gamma_R (buffer_r, 0); 611141cc406Sopenharmony_ci set_WD_analog_gamma_G (buffer_r, 0); 612141cc406Sopenharmony_ci set_WD_analog_gamma_R (buffer_r, 0); 613141cc406Sopenharmony_ci } 614141cc406Sopenharmony_ci else 615141cc406Sopenharmony_ci { 616141cc406Sopenharmony_ci /* Quote spec: "It is recommended that analog gamma bits 5, 4 and 3 be 617141cc406Sopenharmony_ci * set to 1 (OFF) when the object type of byte 48 is positive and the 618141cc406Sopenharmony_ci * gamma specification of byte 51 is linear, and to 0 (ON) in all 619141cc406Sopenharmony_ci * other cases." */ 620141cc406Sopenharmony_ci /* 621141cc406Sopenharmony_ci int foo; 622141cc406Sopenharmony_ci if ((buffer_r[48] == WD_Positive) && (buffer_r[51] == WD_Linear)) 623141cc406Sopenharmony_ci foo = WD_Analog_Gamma_OFF; 624141cc406Sopenharmony_ci else 625141cc406Sopenharmony_ci foo = WD_Analog_Gamma_ON; 626141cc406Sopenharmony_ci set_WD_analog_gamma_R (buffer_r, foo); 627141cc406Sopenharmony_ci set_WD_analog_gamma_G (buffer_r, foo); 628141cc406Sopenharmony_ci set_WD_analog_gamma_B (buffer_r, foo); 629141cc406Sopenharmony_ci */ 630141cc406Sopenharmony_ci set_WD_analog_gamma_R (buffer_r, s->analog_gamma_r); 631141cc406Sopenharmony_ci set_WD_analog_gamma_G (buffer_r, s->analog_gamma_g); 632141cc406Sopenharmony_ci set_WD_analog_gamma_B (buffer_r, s->analog_gamma_b); 633141cc406Sopenharmony_ci if (s->gamma_bind) 634141cc406Sopenharmony_ci { 635141cc406Sopenharmony_ci set_WD_LUT_R (buffer_r, 1); 636141cc406Sopenharmony_ci set_WD_LUT_G (buffer_r, 1); 637141cc406Sopenharmony_ci set_WD_LUT_B (buffer_r, 1); 638141cc406Sopenharmony_ci } 639141cc406Sopenharmony_ci else 640141cc406Sopenharmony_ci { 641141cc406Sopenharmony_ci set_WD_LUT_R (buffer_r, 1); 642141cc406Sopenharmony_ci set_WD_LUT_G (buffer_r, 2); 643141cc406Sopenharmony_ci set_WD_LUT_B (buffer_r, 3); 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci } 646141cc406Sopenharmony_ci set_WD_averaging (buffer_r, s->averaging); 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci set_WD_brightness_R (buffer_r, s->brightness_R); 649141cc406Sopenharmony_ci set_WD_brightness_G (buffer_r, s->brightness_G); 650141cc406Sopenharmony_ci set_WD_brightness_B (buffer_r, s->brightness_B); 651141cc406Sopenharmony_ci 652141cc406Sopenharmony_ci set_WD_contrast_R (buffer_r, s->contrast_R); 653141cc406Sopenharmony_ci set_WD_contrast_G (buffer_r, s->contrast_G); 654141cc406Sopenharmony_ci set_WD_contrast_B (buffer_r, s->contrast_B); 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci set_WD_exposure_R (buffer_r, s->exposure_R); 657141cc406Sopenharmony_ci set_WD_exposure_G (buffer_r, s->exposure_G); 658141cc406Sopenharmony_ci set_WD_exposure_B (buffer_r, s->exposure_B); 659141cc406Sopenharmony_ci set_WD_shift_R (buffer_r, s->shift_R); 660141cc406Sopenharmony_ci set_WD_shift_G (buffer_r, s->shift_G); 661141cc406Sopenharmony_ci set_WD_shift_B (buffer_r, s->shift_B); 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci 664141cc406Sopenharmony_ci /* FIXME: LUT-[RGB] */ 665141cc406Sopenharmony_ci /* FIXME: stop on/off */ 666141cc406Sopenharmony_ci } 667141cc406Sopenharmony_ci 668141cc406Sopenharmony_ci DBG (10, "\tx_nres=%d, y_nres=%d, upper left-x=%d, upper left-y=%d\n", 669141cc406Sopenharmony_ci s->x_nres, s->y_nres, s->tlx, s->tly); 670141cc406Sopenharmony_ci DBG (10, "\twindow width=%d, MUD=%d, brx=%d\n", 671141cc406Sopenharmony_ci s->brx - s->tlx, s->MUD, s->brx); 672141cc406Sopenharmony_ci DBG (10, "\tcolormode=%d, bits per pixel=%d\n", 673141cc406Sopenharmony_ci s->colormode, s->bits_per_color); 674141cc406Sopenharmony_ci DBG (10, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", 675141cc406Sopenharmony_ci s->negative, s->dropoutcolor, s->preview, s->transfermode, 676141cc406Sopenharmony_ci s->gammaselection); 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci /* prepare SCSI-BUFFER */ 679141cc406Sopenharmony_ci memcpy (s->buffer, set_window.cmd, set_window.size); /* SET-WINDOW cmd */ 680141cc406Sopenharmony_ci memcpy ((s->buffer + set_window.size), /* add WPDB */ 681141cc406Sopenharmony_ci window_parameter_data_block.cmd, 682141cc406Sopenharmony_ci window_parameter_data_block.size); 683141cc406Sopenharmony_ci set_WPDB_wdblen ((s->buffer + set_window.size), used_WDB_size); /* set WD_len */ 684141cc406Sopenharmony_ci memcpy (s->buffer + set_window.size + window_parameter_data_block.size, 685141cc406Sopenharmony_ci buffer_r, window_descriptor_block.size); 686141cc406Sopenharmony_ci 687141cc406Sopenharmony_ci hexdump (15, "Window set", buffer_r, s->wdb_len); 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci set_SW_xferlen (s->buffer, (window_parameter_data_block.size + 690141cc406Sopenharmony_ci window_descriptor_block.size)); 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, s->buffer, set_window.size + 693141cc406Sopenharmony_ci window_parameter_data_block.size + 694141cc406Sopenharmony_ci window_descriptor_block.size, 695141cc406Sopenharmony_ci NULL, 0); 696141cc406Sopenharmony_ci DBG (10, "window set.\n"); 697141cc406Sopenharmony_ci return ret; 698141cc406Sopenharmony_ci} 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_cistatic int 701141cc406Sopenharmony_cicoolscan_set_window_param_LS30 (Coolscan_t * s, int wid, int prescan) 702141cc406Sopenharmony_ci{ 703141cc406Sopenharmony_ci unsigned char buffer_r[max_WDB_size]; 704141cc406Sopenharmony_ci int ret; 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ci wait_scanner (s); 707141cc406Sopenharmony_ci memset (buffer_r, '\0', max_WDB_size); /* clear buffer */ 708141cc406Sopenharmony_ci memcpy (buffer_r, window_descriptor_block_LS30.cmd, 709141cc406Sopenharmony_ci window_descriptor_block_LS30.size); /* copy preset data */ 710141cc406Sopenharmony_ci 711141cc406Sopenharmony_ci set_WD_wid (buffer_r, wid); /* window identifier */ 712141cc406Sopenharmony_ci set_WD_auto (buffer_r, s->set_auto); /* 0 or 1: don't know what it is */ 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci /* geometry */ 715141cc406Sopenharmony_ci set_WD_Xres (buffer_r, resDivToVal (s->x_nres)); /* x resolution in dpi */ 716141cc406Sopenharmony_ci set_WD_Yres (buffer_r, resDivToVal (s->y_nres)); /* y resolution in dpi */ 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci if (prescan) 719141cc406Sopenharmony_ci { 720141cc406Sopenharmony_ci set_WD_scanmode_LS30 (buffer_r, WD_Prescan); 721141cc406Sopenharmony_ci set_WD_Xres (buffer_r, resDivToVal (1)); /* x res. in dpi */ 722141cc406Sopenharmony_ci set_WD_Yres (buffer_r, resDivToVal (1)); /* y res. in dpi */ 723141cc406Sopenharmony_ci buffer_r[0x29]=0x81; 724141cc406Sopenharmony_ci buffer_r[0x2a]=0x04; 725141cc406Sopenharmony_ci buffer_r[0x2b]=0x02; 726141cc406Sopenharmony_ci buffer_r[0x2c]=0x01; 727141cc406Sopenharmony_ci buffer_r[0x2d]=0xff; 728141cc406Sopenharmony_ci buffer_r[0x30]=0x00; 729141cc406Sopenharmony_ci buffer_r[0x31]=0x00; 730141cc406Sopenharmony_ci buffer_r[0x32]=0x00; 731141cc406Sopenharmony_ci buffer_r[0x33]=0x00; 732141cc406Sopenharmony_ci set_WD_width (buffer_r,(2592)); 733141cc406Sopenharmony_ci set_WD_length (buffer_r,(3894)); 734141cc406Sopenharmony_ci } 735141cc406Sopenharmony_ci else 736141cc406Sopenharmony_ci { 737141cc406Sopenharmony_ci set_WD_scanmode_LS30 (buffer_r, WD_Scan); 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci /* the coolscan LS-30 uses the upper left corner 740141cc406Sopenharmony_ci as the origin of coordinates */ 741141cc406Sopenharmony_ci /* xmax and ymax are given in 1200 dpi */ 742141cc406Sopenharmony_ci set_WD_ULX (buffer_r, s->tlx); 743141cc406Sopenharmony_ci set_WD_ULY (buffer_r, s->tly); /* upper_edge y */ 744141cc406Sopenharmony_ci set_WD_width (buffer_r, (s->brx - s->tlx+1)); 745141cc406Sopenharmony_ci set_WD_length (buffer_r, (s->bry - s->tly+1)); 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ci /* BTC */ 748141cc406Sopenharmony_ci if (s->brightness == 128) 749141cc406Sopenharmony_ci { 750141cc406Sopenharmony_ci buffer_r[0x32]=0x00; 751141cc406Sopenharmony_ci } 752141cc406Sopenharmony_ci else 753141cc406Sopenharmony_ci { 754141cc406Sopenharmony_ci buffer_r[0x32]=s->brightness; /* brightness */ 755141cc406Sopenharmony_ci } 756141cc406Sopenharmony_ci 757141cc406Sopenharmony_ci if (s->contrast == 128) 758141cc406Sopenharmony_ci { 759141cc406Sopenharmony_ci buffer_r[0x33]=0x00; 760141cc406Sopenharmony_ci } 761141cc406Sopenharmony_ci else 762141cc406Sopenharmony_ci { 763141cc406Sopenharmony_ci buffer_r[0x33]=s->contrast; /* contrast */ 764141cc406Sopenharmony_ci } 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci /* scanmode */ 767141cc406Sopenharmony_ci if (s->colormode == GREYSCALE) 768141cc406Sopenharmony_ci set_WD_composition (buffer_r, WD_comp_grey); /* GRAY composition */ 769141cc406Sopenharmony_ci else 770141cc406Sopenharmony_ci set_WD_composition (buffer_r, WD_comp_rgb_full); /* RGB composition */ 771141cc406Sopenharmony_ci 772141cc406Sopenharmony_ci set_WD_composition (buffer_r, WD_comp_rgb_full); /* always RGB composition */ 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci /* Bits per pixel */ 775141cc406Sopenharmony_ci set_WD_bitsperpixel(buffer_r, s->bits_per_color); 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci buffer_r[0x29]=0x81; 778141cc406Sopenharmony_ci buffer_r[0x2a]=0x01; 779141cc406Sopenharmony_ci buffer_r[0x2b]=0x02; 780141cc406Sopenharmony_ci buffer_r[0x2c]=0x01; 781141cc406Sopenharmony_ci buffer_r[0x2d]=0xff; 782141cc406Sopenharmony_ci buffer_r[0x30]=0x00; 783141cc406Sopenharmony_ci 784141cc406Sopenharmony_ci } 785141cc406Sopenharmony_ci set_WD_negative_LS30(buffer_r, s->negative); /* Negative/positive slide */ 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci switch(wid) 788141cc406Sopenharmony_ci { case 1: set_gain_LS30(buffer_r,(s->exposure_R*s->pretv_r)/50); 789141cc406Sopenharmony_ci break; 790141cc406Sopenharmony_ci case 2: set_gain_LS30(buffer_r,(s->exposure_G*s->pretv_g)/50); 791141cc406Sopenharmony_ci break; 792141cc406Sopenharmony_ci case 3: set_gain_LS30(buffer_r,(s->exposure_B*s->pretv_b)/50); 793141cc406Sopenharmony_ci break; 794141cc406Sopenharmony_ci } 795141cc406Sopenharmony_ci 796141cc406Sopenharmony_ci DBG (10, "\texpo_r=%d, expo_g=%d, expob=%d\n", 797141cc406Sopenharmony_ci s->exposure_R, s->exposure_G, s->exposure_B); 798141cc406Sopenharmony_ci DBG (10, "\tpre_r=%d, pre_g=%d, preb=%d\n", 799141cc406Sopenharmony_ci s->pretv_r, s->pretv_g, s->pretv_b); 800141cc406Sopenharmony_ci DBG (10, "\tx_nres=%d, y_nres=%d, upper left-x=%d, upper left-y=%d\n", 801141cc406Sopenharmony_ci s->x_nres, s->y_nres, s->tlx, s->tly); 802141cc406Sopenharmony_ci DBG (10, "\twindow width=%d, MUD=%d, brx=%d\n", 803141cc406Sopenharmony_ci s->brx - s->tlx, s->MUD, s->brx); 804141cc406Sopenharmony_ci DBG (10, "\tcolormode=%d, bits per pixel=%d\n", 805141cc406Sopenharmony_ci s->colormode, s->bits_per_color); 806141cc406Sopenharmony_ci DBG (10, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", 807141cc406Sopenharmony_ci s->negative, s->dropoutcolor, s->preview, s->transfermode, 808141cc406Sopenharmony_ci s->gammaselection); 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci /* prepare SCSI-BUFFER */ 811141cc406Sopenharmony_ci memcpy (s->buffer, set_window.cmd, set_window.size); /* SET-WINDOW cmd */ 812141cc406Sopenharmony_ci memcpy ((s->buffer + set_window.size), /* add WPDB */ 813141cc406Sopenharmony_ci window_parameter_data_block.cmd, 814141cc406Sopenharmony_ci window_parameter_data_block.size); 815141cc406Sopenharmony_ci set_WPDB_wdblen ((s->buffer + set_window.size), used_WDB_size_LS30); /* set WD_len */ 816141cc406Sopenharmony_ci memcpy (s->buffer + set_window.size + window_parameter_data_block.size, 817141cc406Sopenharmony_ci buffer_r, window_descriptor_block_LS30.size); 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci hexdump (15, "Window set", buffer_r, s->wdb_len); 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci set_SW_xferlen (s->buffer, (window_parameter_data_block.size + 822141cc406Sopenharmony_ci window_descriptor_block_LS30.size)); 823141cc406Sopenharmony_ci 824141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, s->buffer, set_window.size + 825141cc406Sopenharmony_ci window_parameter_data_block.size + 826141cc406Sopenharmony_ci window_descriptor_block_LS30.size, 827141cc406Sopenharmony_ci NULL, 0); 828141cc406Sopenharmony_ci DBG (10, "window set.\n"); 829141cc406Sopenharmony_ci return ret; 830141cc406Sopenharmony_ci} 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_cistatic int 833141cc406Sopenharmony_cicoolscan_set_window_param (Coolscan_t * s, int prescan) 834141cc406Sopenharmony_ci{ 835141cc406Sopenharmony_ci int ret; 836141cc406Sopenharmony_ci ret=0; 837141cc406Sopenharmony_ci DBG (10, "set_window_param\n"); 838141cc406Sopenharmony_ci 839141cc406Sopenharmony_ci if(s->LS<2) /* distinguish between old and new scanners */ 840141cc406Sopenharmony_ci { ret=coolscan_set_window_param_LS20 (s,prescan); 841141cc406Sopenharmony_ci } 842141cc406Sopenharmony_ci else 843141cc406Sopenharmony_ci { do_scsi_cmd (s->sfd,commande1.cmd,commande1.size,s->buffer,0x0d); 844141cc406Sopenharmony_ci wait_scanner (s); 845141cc406Sopenharmony_ci wait_scanner (s); 846141cc406Sopenharmony_ci coolscan_set_window_param_LS30(s,1,prescan); 847141cc406Sopenharmony_ci ret=coolscan_set_window_param_LS30(s,2,prescan); 848141cc406Sopenharmony_ci ret=coolscan_set_window_param_LS30(s,3,prescan); 849141cc406Sopenharmony_ci if(s->colormode&0x08) 850141cc406Sopenharmony_ci { ret=coolscan_set_window_param_LS30(s,9,prescan); 851141cc406Sopenharmony_ci } 852141cc406Sopenharmony_ci } 853141cc406Sopenharmony_ci return ret; 854141cc406Sopenharmony_ci} 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_ci 857141cc406Sopenharmony_ci/* 858141cc406Sopenharmony_ci * The only purpose of get_window is debugging. None of the return parameters 859141cc406Sopenharmony_ci * is currently used. 860141cc406Sopenharmony_ci */ 861141cc406Sopenharmony_cistatic int 862141cc406Sopenharmony_cicoolscan_get_window_param_LS30 (Coolscan_t * s, int wid,int prescanok) 863141cc406Sopenharmony_ci{ 864141cc406Sopenharmony_ci int translen; 865141cc406Sopenharmony_ci unsigned char *buf; 866141cc406Sopenharmony_ci 867141cc406Sopenharmony_ci DBG (10, "GET_WINDOW_PARAM\n"); 868141cc406Sopenharmony_ci /* wait_scanner (s); */ 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci translen = window_parameter_data_block.size + window_descriptor_block_LS30.size; 871141cc406Sopenharmony_ci 872141cc406Sopenharmony_ci /* prepare SCSI-BUFFER */ 873141cc406Sopenharmony_ci memset (s->buffer, '\0', max_WDB_size); /* clear buffer */ 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci set_SW_xferlen (get_window.cmd, translen); /* Transfer length */ 876141cc406Sopenharmony_ci get_window.cmd[5]= wid; /* window identifier */ 877141cc406Sopenharmony_ci 878141cc406Sopenharmony_ci hexdump (15, "Get window cmd", get_window.cmd, get_window.size); 879141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, get_window.cmd, get_window.size, 880141cc406Sopenharmony_ci s->buffer, translen); 881141cc406Sopenharmony_ci 882141cc406Sopenharmony_ci buf = s->buffer + window_parameter_data_block.size; 883141cc406Sopenharmony_ci hexdump (10, "Window get", buf, 117); 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_ci s->brightness = buf[0x32]; /* brightness */ 886141cc406Sopenharmony_ci s->contrast = buf[0x33]; /* contrast */ 887141cc406Sopenharmony_ci DBG (10, "\tbrightness=%d, contrast=%d\n", s->brightness, s->contrast); 888141cc406Sopenharmony_ci 889141cc406Sopenharmony_ci /* Useful? */ 890141cc406Sopenharmony_ci s->bits_per_color = get_WD_bitsperpixel (buf); /* bits/pixel (8) */ 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci DBG (10, "\tcolormode=%d, bits per pixel=%d\n", 893141cc406Sopenharmony_ci s->colormode, s->bits_per_color); 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ci if(prescanok) 896141cc406Sopenharmony_ci { switch(wid) 897141cc406Sopenharmony_ci { case 1: s->pretv_r = get_gain_LS30(buf); 898141cc406Sopenharmony_ci break; 899141cc406Sopenharmony_ci case 2: s->pretv_g = get_gain_LS30(buf); 900141cc406Sopenharmony_ci break; 901141cc406Sopenharmony_ci case 3: s->pretv_b = get_gain_LS30(buf); 902141cc406Sopenharmony_ci break; 903141cc406Sopenharmony_ci } 904141cc406Sopenharmony_ci } 905141cc406Sopenharmony_ci 906141cc406Sopenharmony_ci /* Should this one be set at all, here? */ 907141cc406Sopenharmony_ci s->transfermode = get_WD_transfermode (buf); 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci s->gammaselection = get_WD_gammaselection (buf); /* monitor/linear */ 910141cc406Sopenharmony_ci DBG (10, "\tpre_r=%d, pre_g=%d, preb=%d\n", 911141cc406Sopenharmony_ci s->pretv_r, s->pretv_g, s->pretv_b); 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci DBG (5, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", 914141cc406Sopenharmony_ci s->negative, s->dropoutcolor, s->preview, s->transfermode, 915141cc406Sopenharmony_ci s->gammaselection); 916141cc406Sopenharmony_ci 917141cc406Sopenharmony_ci DBG (10, "get_window_param - return\n"); 918141cc406Sopenharmony_ci return 0; 919141cc406Sopenharmony_ci} 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci/* 922141cc406Sopenharmony_ci * The only purpose of get_window is debugging. None of the return parameters 923141cc406Sopenharmony_ci * is currently used. 924141cc406Sopenharmony_ci */ 925141cc406Sopenharmony_cistatic int 926141cc406Sopenharmony_cicoolscan_get_window_param_LS20 (Coolscan_t * s) 927141cc406Sopenharmony_ci{ 928141cc406Sopenharmony_ci int translen; 929141cc406Sopenharmony_ci unsigned char *buf; 930141cc406Sopenharmony_ci 931141cc406Sopenharmony_ci DBG (10, "GET_WINDOW_PARAM\n"); 932141cc406Sopenharmony_ci wait_scanner (s); 933141cc406Sopenharmony_ci 934141cc406Sopenharmony_ci translen = window_parameter_data_block.size + window_descriptor_block.size; 935141cc406Sopenharmony_ci 936141cc406Sopenharmony_ci /* prepare SCSI-BUFFER */ 937141cc406Sopenharmony_ci memset (s->buffer, '\0', max_WDB_size); /* clear buffer */ 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci set_SW_xferlen (get_window.cmd, translen); /* Transfer length */ 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ci hexdump (15, "Get window cmd", get_window.cmd, get_window.size); 942141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, get_window.cmd, get_window.size, 943141cc406Sopenharmony_ci s->buffer, translen); 944141cc406Sopenharmony_ci 945141cc406Sopenharmony_ci buf = s->buffer + window_parameter_data_block.size; 946141cc406Sopenharmony_ci hexdump (10, "Window get", buf, 117); 947141cc406Sopenharmony_ci 948141cc406Sopenharmony_ci /* BTC */ 949141cc406Sopenharmony_ci s->brightness = get_WD_brightness (buf); /* brightness */ 950141cc406Sopenharmony_ci s->contrast = get_WD_contrast (buf); /* contrast */ 951141cc406Sopenharmony_ci DBG (10, "\tbrightness=%d, contrast=%d\n", s->brightness, s->contrast); 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci if (WD_comp_gray == get_WD_composition (buf)) 954141cc406Sopenharmony_ci s->colormode = GREYSCALE; 955141cc406Sopenharmony_ci else 956141cc406Sopenharmony_ci s->colormode = RGB; 957141cc406Sopenharmony_ci 958141cc406Sopenharmony_ci /* Useful? */ 959141cc406Sopenharmony_ci s->bits_per_color = get_WD_bitsperpixel (buf); /* bits/pixel (8) */ 960141cc406Sopenharmony_ci 961141cc406Sopenharmony_ci DBG (10, "\tcolormode=%d, bits per pixel=%d\n", 962141cc406Sopenharmony_ci s->colormode, s->bits_per_color); 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci s->dropoutcolor = get_WD_dropoutcolor (buf); /* Which color to scan with when grayscale scan */ 966141cc406Sopenharmony_ci 967141cc406Sopenharmony_ci /* Should this one be set at all, here? */ 968141cc406Sopenharmony_ci s->transfermode = get_WD_transfermode (buf); 969141cc406Sopenharmony_ci 970141cc406Sopenharmony_ci s->gammaselection = get_WD_gammaselection (buf); /* monitor/linear */ 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci DBG (5, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", 973141cc406Sopenharmony_ci s->negative, s->dropoutcolor, s->preview, s->transfermode, 974141cc406Sopenharmony_ci s->gammaselection); 975141cc406Sopenharmony_ci 976141cc406Sopenharmony_ci /* Should this one be set at all? */ 977141cc406Sopenharmony_ci s->shading = get_WD_shading (buf); 978141cc406Sopenharmony_ci s->averaging = get_WD_averaging (buf); 979141cc406Sopenharmony_ci DBG (10, "get_window_param - return\n"); 980141cc406Sopenharmony_ci return 0; 981141cc406Sopenharmony_ci} 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci/* 984141cc406Sopenharmony_ci * The only purpose of get_window is debugging. None of the return parameters 985141cc406Sopenharmony_ci * is currently used. 986141cc406Sopenharmony_ci */ 987141cc406Sopenharmony_cistatic int 988141cc406Sopenharmony_cicoolscan_get_window_param (Coolscan_t * s, int prescanok) 989141cc406Sopenharmony_ci{ 990141cc406Sopenharmony_ci int ret; 991141cc406Sopenharmony_ci DBG (10, "get_window_param\n"); 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci ret=0; 994141cc406Sopenharmony_ci if(s->LS<2) /* distinguish between old and new scanners */ 995141cc406Sopenharmony_ci { ret=coolscan_get_window_param_LS20 (s); 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci else 998141cc406Sopenharmony_ci { 999141cc406Sopenharmony_ci ret=coolscan_get_window_param_LS30(s,1,prescanok); 1000141cc406Sopenharmony_ci ret=coolscan_get_window_param_LS30(s,2,prescanok); 1001141cc406Sopenharmony_ci ret=coolscan_get_window_param_LS30(s,3,prescanok); 1002141cc406Sopenharmony_ci if(s->colormode&0x08) 1003141cc406Sopenharmony_ci { ret=coolscan_get_window_param_LS30(s,9,prescanok); 1004141cc406Sopenharmony_ci } 1005141cc406Sopenharmony_ci } 1006141cc406Sopenharmony_ci return ret; 1007141cc406Sopenharmony_ci} 1008141cc406Sopenharmony_ci 1009141cc406Sopenharmony_cistatic int 1010141cc406Sopenharmony_cicoolscan_start_scanLS30 (Coolscan_t * s) 1011141cc406Sopenharmony_ci{ int channels; 1012141cc406Sopenharmony_ci DBG (10, "starting scan\n"); 1013141cc406Sopenharmony_ci 1014141cc406Sopenharmony_ci channels=1; 1015141cc406Sopenharmony_ci memcpy (s->buffer, scan.cmd, scan.size); 1016141cc406Sopenharmony_ci switch(s->colormode) 1017141cc406Sopenharmony_ci { case RGB: 1018141cc406Sopenharmony_ci case GREYSCALE: 1019141cc406Sopenharmony_ci channels=s->buffer[4]=0x03; /* window 1 */ 1020141cc406Sopenharmony_ci s->buffer[6]=0x01; /* window 1 */ 1021141cc406Sopenharmony_ci s->buffer[7]=0x02; /* window 2 */ 1022141cc406Sopenharmony_ci s->buffer[8]=0x03; /* window 3 */ 1023141cc406Sopenharmony_ci 1024141cc406Sopenharmony_ci break; 1025141cc406Sopenharmony_ci case RGBI: 1026141cc406Sopenharmony_ci channels=s->buffer[4]=0x04; /* window 1 */ 1027141cc406Sopenharmony_ci s->buffer[6]=0x01; /* window 1 */ 1028141cc406Sopenharmony_ci s->buffer[7]=0x02; /* window 2 */ 1029141cc406Sopenharmony_ci s->buffer[8]=0x03; /* window 3 */ 1030141cc406Sopenharmony_ci s->buffer[9]=0x09; /* window 3 */ 1031141cc406Sopenharmony_ci break; 1032141cc406Sopenharmony_ci case IRED: 1033141cc406Sopenharmony_ci channels=s->buffer[4]=0x01; /* window 1 */ 1034141cc406Sopenharmony_ci s->buffer[8]=0x09; /* window 3 */ 1035141cc406Sopenharmony_ci break; 1036141cc406Sopenharmony_ci } 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci return do_scsi_cmd (s->sfd, s->buffer, scan.size+channels, NULL, 0); 1039141cc406Sopenharmony_ci} 1040141cc406Sopenharmony_ci 1041141cc406Sopenharmony_cistatic int 1042141cc406Sopenharmony_cicoolscan_start_scan (Coolscan_t * s) 1043141cc406Sopenharmony_ci{ 1044141cc406Sopenharmony_ci DBG (10, "starting scan\n"); 1045141cc406Sopenharmony_ci if(s->LS>=2) 1046141cc406Sopenharmony_ci { return coolscan_start_scanLS30(s); 1047141cc406Sopenharmony_ci } 1048141cc406Sopenharmony_ci return do_scsi_cmd (s->sfd, scan.cmd, scan.size, NULL, 0); 1049141cc406Sopenharmony_ci} 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci 1052141cc406Sopenharmony_cistatic int 1053141cc406Sopenharmony_ciprescan (Coolscan_t * s) 1054141cc406Sopenharmony_ci{ 1055141cc406Sopenharmony_ci int ret; 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci DBG (10, "Starting prescan...\n"); 1058141cc406Sopenharmony_ci if(s->LS<2) 1059141cc406Sopenharmony_ci { coolscan_set_window_param (s, 1); 1060141cc406Sopenharmony_ci } 1061141cc406Sopenharmony_ci else 1062141cc406Sopenharmony_ci { 1063141cc406Sopenharmony_ci do_scsi_cmd (s->sfd,commande1.cmd,commande1.size,s->buffer,0x0d); 1064141cc406Sopenharmony_ci wait_scanner (s); 1065141cc406Sopenharmony_ci wait_scanner (s); 1066141cc406Sopenharmony_ci coolscan_set_window_param_LS30 (s,1,1); 1067141cc406Sopenharmony_ci coolscan_set_window_param_LS30 (s,2,1); 1068141cc406Sopenharmony_ci coolscan_set_window_param_LS30 (s,3,1); 1069141cc406Sopenharmony_ci 1070141cc406Sopenharmony_ci } 1071141cc406Sopenharmony_ci ret = coolscan_start_scan(s); 1072141cc406Sopenharmony_ci 1073141cc406Sopenharmony_ci sleep(8); /* prescan takes a minimum of 10 sec. */ 1074141cc406Sopenharmony_ci wait_scanner (s); 1075141cc406Sopenharmony_ci DBG (10, "Prescan done\n"); 1076141cc406Sopenharmony_ci return ret; 1077141cc406Sopenharmony_ci} 1078141cc406Sopenharmony_ci 1079141cc406Sopenharmony_cistatic SANE_Status 1080141cc406Sopenharmony_cido_prescan_now (Coolscan_t * scanner) 1081141cc406Sopenharmony_ci{ 1082141cc406Sopenharmony_ci 1083141cc406Sopenharmony_ci DBG (10, "do_prescan_now \n"); 1084141cc406Sopenharmony_ci if (scanner->scanning == SANE_TRUE) 1085141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1086141cc406Sopenharmony_ci 1087141cc406Sopenharmony_ci if (scanner->sfd < 0) 1088141cc406Sopenharmony_ci { /* first call */ 1089141cc406Sopenharmony_ci if (sanei_scsi_open (scanner->sane.name, 1090141cc406Sopenharmony_ci &(scanner->sfd), 1091141cc406Sopenharmony_ci sense_handler, 0) != SANE_STATUS_GOOD) 1092141cc406Sopenharmony_ci { 1093141cc406Sopenharmony_ci DBG (1, "do_prescan_now: open of %s failed:\n", 1094141cc406Sopenharmony_ci scanner->sane.name); 1095141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1096141cc406Sopenharmony_ci } 1097141cc406Sopenharmony_ci } 1098141cc406Sopenharmony_ci scanner->scanning = SANE_TRUE; 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci 1101141cc406Sopenharmony_ci if (coolscan_check_values (scanner) != 0) 1102141cc406Sopenharmony_ci { /* Verify values */ 1103141cc406Sopenharmony_ci DBG (1, "ERROR: invalid scan-values\n"); 1104141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1105141cc406Sopenharmony_ci coolscan_give_scanner (scanner); 1106141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 1107141cc406Sopenharmony_ci scanner->sfd = -1; 1108141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1109141cc406Sopenharmony_ci } 1110141cc406Sopenharmony_ci 1111141cc406Sopenharmony_ci if (coolscan_grab_scanner (scanner)) 1112141cc406Sopenharmony_ci { 1113141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 1114141cc406Sopenharmony_ci scanner->sfd = -1; 1115141cc406Sopenharmony_ci DBG (5, "WARNING: unable to reserve scanner: device busy\n"); 1116141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1117141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1118141cc406Sopenharmony_ci } 1119141cc406Sopenharmony_ci 1120141cc406Sopenharmony_ci prescan (scanner); 1121141cc406Sopenharmony_ci if(scanner->LS<2) 1122141cc406Sopenharmony_ci { get_internal_info(scanner); 1123141cc406Sopenharmony_ci } 1124141cc406Sopenharmony_ci coolscan_get_window_param (scanner,1); 1125141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 1126141cc406Sopenharmony_ci coolscan_give_scanner (scanner); 1127141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1128141cc406Sopenharmony_ci} 1129141cc406Sopenharmony_ci 1130141cc406Sopenharmony_ci 1131141cc406Sopenharmony_cistatic int 1132141cc406Sopenharmony_cisend_one_LUT (Coolscan_t * s, SANE_Word * LUT, int reg) 1133141cc406Sopenharmony_ci{ 1134141cc406Sopenharmony_ci int i; 1135141cc406Sopenharmony_ci short lutval; 1136141cc406Sopenharmony_ci short bytesperval; 1137141cc406Sopenharmony_ci unsigned char *gamma, *gamma_p; 1138141cc406Sopenharmony_ci unsigned short *gamma_s; 1139141cc406Sopenharmony_ci 1140141cc406Sopenharmony_ci DBG (10, "send LUT\n"); 1141141cc406Sopenharmony_ci 1142141cc406Sopenharmony_ci if(s->LS<2) 1143141cc406Sopenharmony_ci { set_S_datatype_code (send.cmd, R_user_reg_gamma); 1144141cc406Sopenharmony_ci bytesperval=1; 1145141cc406Sopenharmony_ci } 1146141cc406Sopenharmony_ci else 1147141cc406Sopenharmony_ci { 1148141cc406Sopenharmony_ci send.cmd[0x02]=3; 1149141cc406Sopenharmony_ci send.cmd[0x05]=1; 1150141cc406Sopenharmony_ci bytesperval=2; 1151141cc406Sopenharmony_ci } 1152141cc406Sopenharmony_ci 1153141cc406Sopenharmony_ci set_S_xfer_length (send.cmd, s->lutlength*bytesperval); 1154141cc406Sopenharmony_ci set_S_datatype_qual_upper (send.cmd, reg); 1155141cc406Sopenharmony_ci 1156141cc406Sopenharmony_ci gamma = alloca (send.size + s->lutlength*2); 1157141cc406Sopenharmony_ci memcpy (gamma, send.cmd, send.size); 1158141cc406Sopenharmony_ci if(s->LS<2) 1159141cc406Sopenharmony_ci { gamma_p = &gamma[send.size]; 1160141cc406Sopenharmony_ci for (i = 0; i < s->lutlength; i++) 1161141cc406Sopenharmony_ci { 1162141cc406Sopenharmony_ci if (LUT[i] > 255) 1163141cc406Sopenharmony_ci LUT[i] = 255; /* broken gtk */ 1164141cc406Sopenharmony_ci *gamma_p++ = (unsigned char) LUT[i]; 1165141cc406Sopenharmony_ci } 1166141cc406Sopenharmony_ci } 1167141cc406Sopenharmony_ci else if(s->LS==2) 1168141cc406Sopenharmony_ci { gamma_s = (unsigned short*)( &gamma[send.size]); 1169141cc406Sopenharmony_ci for (i = 0; i < s->lutlength; i++) 1170141cc406Sopenharmony_ci { 1171141cc406Sopenharmony_ci if(s->negative) 1172141cc406Sopenharmony_ci { 1173141cc406Sopenharmony_ci lutval=(unsigned short)(LUT[(s->lutlength-i)]); 1174141cc406Sopenharmony_ci } 1175141cc406Sopenharmony_ci else 1176141cc406Sopenharmony_ci { 1177141cc406Sopenharmony_ci lutval=(unsigned short)(LUT[i]); 1178141cc406Sopenharmony_ci } 1179141cc406Sopenharmony_ci if (LUT[i] >= s->max_lut_val) 1180141cc406Sopenharmony_ci LUT[i] = s->max_lut_val-1; /* broken gtk */ 1181141cc406Sopenharmony_ci if(s->low_byte_first) /* if on little endian machine: */ 1182141cc406Sopenharmony_ci { 1183141cc406Sopenharmony_ci lutval=((lutval&0x00ff)<<8)+((lutval&0xff00)>>8); /* inverse byteorder */ 1184141cc406Sopenharmony_ci } 1185141cc406Sopenharmony_ci *gamma_s++ = lutval; 1186141cc406Sopenharmony_ci } 1187141cc406Sopenharmony_ci } 1188141cc406Sopenharmony_ci else if(s->LS==3) 1189141cc406Sopenharmony_ci { gamma_s = (unsigned short*)( &gamma[send.size]); 1190141cc406Sopenharmony_ci for (i = 0; i < s->lutlength; i++) 1191141cc406Sopenharmony_ci { 1192141cc406Sopenharmony_ci if(s->negative) 1193141cc406Sopenharmony_ci { 1194141cc406Sopenharmony_ci lutval=(unsigned short)(LUT[s->lutlength-i]); 1195141cc406Sopenharmony_ci } 1196141cc406Sopenharmony_ci else 1197141cc406Sopenharmony_ci { 1198141cc406Sopenharmony_ci lutval=(unsigned short)(LUT[i]); 1199141cc406Sopenharmony_ci } 1200141cc406Sopenharmony_ci if (LUT[i] >= s->max_lut_val) 1201141cc406Sopenharmony_ci LUT[i] = s->max_lut_val-1; /* broken gtk */ 1202141cc406Sopenharmony_ci if(s->low_byte_first) /* if on little endian machine: */ 1203141cc406Sopenharmony_ci { lutval=((lutval&0x00ff)<<8)+((lutval&0xff00)>>8); /* inverse byteorder */ 1204141cc406Sopenharmony_ci } 1205141cc406Sopenharmony_ci *gamma_s++ = lutval; 1206141cc406Sopenharmony_ci } 1207141cc406Sopenharmony_ci } 1208141cc406Sopenharmony_ci return do_scsi_cmd (s->sfd, gamma, send.size + s->lutlength*bytesperval, NULL, 0); 1209141cc406Sopenharmony_ci} 1210141cc406Sopenharmony_ci 1211141cc406Sopenharmony_ci 1212141cc406Sopenharmony_cistatic int 1213141cc406Sopenharmony_cisend_LUT (Coolscan_t * s) 1214141cc406Sopenharmony_ci{ 1215141cc406Sopenharmony_ci wait_scanner (s); 1216141cc406Sopenharmony_ci if (s->gamma_bind) 1217141cc406Sopenharmony_ci { 1218141cc406Sopenharmony_ci send_one_LUT (s, s->gamma, S_DQ_Reg1); 1219141cc406Sopenharmony_ci if(s->LS>=2) 1220141cc406Sopenharmony_ci { send_one_LUT (s, s->gamma, S_DQ_Reg2); 1221141cc406Sopenharmony_ci send_one_LUT (s, s->gamma, S_DQ_Reg3); 1222141cc406Sopenharmony_ci if(s->colormode&0x08) 1223141cc406Sopenharmony_ci { send_one_LUT (s, s->gamma, S_DQ_Reg9); 1224141cc406Sopenharmony_ci } 1225141cc406Sopenharmony_ci 1226141cc406Sopenharmony_ci } 1227141cc406Sopenharmony_ci } 1228141cc406Sopenharmony_ci else 1229141cc406Sopenharmony_ci { 1230141cc406Sopenharmony_ci send_one_LUT (s, s->gamma_r, S_DQ_Reg1); 1231141cc406Sopenharmony_ci send_one_LUT (s, s->gamma_g, S_DQ_Reg2); 1232141cc406Sopenharmony_ci send_one_LUT (s, s->gamma_b, S_DQ_Reg3); 1233141cc406Sopenharmony_ci if(s->colormode&0x08) 1234141cc406Sopenharmony_ci { send_one_LUT (s, s->gamma_r, S_DQ_Reg9); 1235141cc406Sopenharmony_ci } 1236141cc406Sopenharmony_ci } 1237141cc406Sopenharmony_ci return 0; 1238141cc406Sopenharmony_ci} 1239141cc406Sopenharmony_ci 1240141cc406Sopenharmony_ci 1241141cc406Sopenharmony_cistatic int 1242141cc406Sopenharmony_cicoolscan_read_data_block (Coolscan_t * s, unsigned int datatype, unsigned int length) 1243141cc406Sopenharmony_ci{ 1244141cc406Sopenharmony_ci int r; 1245141cc406Sopenharmony_ci 1246141cc406Sopenharmony_ci DBG (10, "read_data_block (type= %x length = %d)\n",datatype,length); 1247141cc406Sopenharmony_ci /*wait_scanner(s); */ 1248141cc406Sopenharmony_ci 1249141cc406Sopenharmony_ci set_R_datatype_code (sread.cmd, datatype); 1250141cc406Sopenharmony_ci sread.cmd[4]=00; 1251141cc406Sopenharmony_ci sread.cmd[5]=00; 1252141cc406Sopenharmony_ci set_R_xfer_length (sread.cmd, length); 1253141cc406Sopenharmony_ci 1254141cc406Sopenharmony_ci r = do_scsi_cmd (s->sfd, sread.cmd, sread.size, s->buffer, length); 1255141cc406Sopenharmony_ci return ((r != 0) ? -1 : (int) length); 1256141cc406Sopenharmony_ci} 1257141cc406Sopenharmony_ci 1258141cc406Sopenharmony_ci 1259141cc406Sopenharmony_cistatic void 1260141cc406Sopenharmony_cicoolscan_do_inquiry (Coolscan_t * s) 1261141cc406Sopenharmony_ci{ 1262141cc406Sopenharmony_ci int size; 1263141cc406Sopenharmony_ci 1264141cc406Sopenharmony_ci DBG (10, "do_inquiry\n"); 1265141cc406Sopenharmony_ci memset (s->buffer, '\0', 256); /* clear buffer */ 1266141cc406Sopenharmony_ci size = 36; /* Hardcoded, and as specified by Nikon */ 1267141cc406Sopenharmony_ci /* then get inquiry with actual size */ 1268141cc406Sopenharmony_ci set_inquiry_return_size (inquiry.cmd, size); 1269141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size, s->buffer, size); 1270141cc406Sopenharmony_ci} 1271141cc406Sopenharmony_ci 1272141cc406Sopenharmony_cistatic int 1273141cc406Sopenharmony_cicoolscan_identify_scanner (Coolscan_t * s) 1274141cc406Sopenharmony_ci{ 1275141cc406Sopenharmony_ci unsigned char vendor[9]; 1276141cc406Sopenharmony_ci unsigned char product[0x11]; 1277141cc406Sopenharmony_ci unsigned char version[5]; 1278141cc406Sopenharmony_ci unsigned char *pp; 1279141cc406Sopenharmony_ci int i; 1280141cc406Sopenharmony_ci 1281141cc406Sopenharmony_ci vendor[8] = product[0x10] = version[4] = 0; 1282141cc406Sopenharmony_ci DBG (10, "identify_scanner\n"); 1283141cc406Sopenharmony_ci coolscan_do_inquiry (s); /* get inquiry */ 1284141cc406Sopenharmony_ci if (get_inquiry_periph_devtype (s->buffer) != IN_periph_devtype_scanner) 1285141cc406Sopenharmony_ci { 1286141cc406Sopenharmony_ci DBG (5, "identify_scanner: not a scanner\n"); 1287141cc406Sopenharmony_ci return 1; 1288141cc406Sopenharmony_ci } /* no, continue searching */ 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci coolscan_get_inquiry_values (s); 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci get_inquiry_vendor ((char *)s->buffer, (char *)vendor); 1293141cc406Sopenharmony_ci get_inquiry_product ((char *)s->buffer, (char *)product); 1294141cc406Sopenharmony_ci get_inquiry_version ((char *)s->buffer, (char *)version); 1295141cc406Sopenharmony_ci 1296141cc406Sopenharmony_ci if (strncmp ("Nikon ", (char *)vendor, 8)) 1297141cc406Sopenharmony_ci { 1298141cc406Sopenharmony_ci DBG (5, "identify_scanner: \"%s\" isn't a Nikon product\n", vendor); 1299141cc406Sopenharmony_ci return 1; 1300141cc406Sopenharmony_ci } /* Not a Nikon product */ 1301141cc406Sopenharmony_ci 1302141cc406Sopenharmony_ci pp = &vendor[8]; 1303141cc406Sopenharmony_ci vendor[8] = ' '; 1304141cc406Sopenharmony_ci while (*pp == ' ') 1305141cc406Sopenharmony_ci { 1306141cc406Sopenharmony_ci *pp-- = '\0'; 1307141cc406Sopenharmony_ci } 1308141cc406Sopenharmony_ci 1309141cc406Sopenharmony_ci pp = &product[0x10]; 1310141cc406Sopenharmony_ci product[0x10] = ' '; 1311141cc406Sopenharmony_ci while (*(pp - 1) == ' ') 1312141cc406Sopenharmony_ci { 1313141cc406Sopenharmony_ci *pp-- = '\0'; 1314141cc406Sopenharmony_ci } /* leave one blank at the end! */ 1315141cc406Sopenharmony_ci 1316141cc406Sopenharmony_ci pp = &version[4]; 1317141cc406Sopenharmony_ci version[4] = ' '; 1318141cc406Sopenharmony_ci while (*pp == ' ') 1319141cc406Sopenharmony_ci { 1320141cc406Sopenharmony_ci *pp-- = '\0'; 1321141cc406Sopenharmony_ci } 1322141cc406Sopenharmony_ci 1323141cc406Sopenharmony_ci DBG (10, "Found Nikon scanner %sversion %s on device %s\n", 1324141cc406Sopenharmony_ci product, version, s->devicename); 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci /* look for scanners that do not give all inquiry-informations */ 1327141cc406Sopenharmony_ci /* and if possible use driver-known inquiry-data */ 1328141cc406Sopenharmony_ci if (get_inquiry_additional_length (s->buffer) >= 0x1f) 1329141cc406Sopenharmony_ci { 1330141cc406Sopenharmony_ci /* Now identify full supported scanners */ 1331141cc406Sopenharmony_ci for (i = 0; i < known_scanners; i++) 1332141cc406Sopenharmony_ci { 1333141cc406Sopenharmony_ci if (!strncmp ((char *)product, scanner_str[i], strlen (scanner_str[i]))) 1334141cc406Sopenharmony_ci { 1335141cc406Sopenharmony_ci s->LS = i; 1336141cc406Sopenharmony_ci return 0; 1337141cc406Sopenharmony_ci } 1338141cc406Sopenharmony_ci } 1339141cc406Sopenharmony_ci if (s->cont) 1340141cc406Sopenharmony_ci return 0; 1341141cc406Sopenharmony_ci else 1342141cc406Sopenharmony_ci return 1; 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci else 1345141cc406Sopenharmony_ci return 1; 1346141cc406Sopenharmony_ci} 1347141cc406Sopenharmony_ci 1348141cc406Sopenharmony_cistatic int 1349141cc406Sopenharmony_cipixels_per_line (Coolscan_t * s) 1350141cc406Sopenharmony_ci{ 1351141cc406Sopenharmony_ci int pic_dot; 1352141cc406Sopenharmony_ci if(s->LS<2) 1353141cc406Sopenharmony_ci { pic_dot = (s->brx - s->tlx + s->x_nres) / s->x_nres; 1354141cc406Sopenharmony_ci } 1355141cc406Sopenharmony_ci else 1356141cc406Sopenharmony_ci { pic_dot = (s->brx - s->tlx + 1) / s->x_nres; 1357141cc406Sopenharmony_ci } 1358141cc406Sopenharmony_ci DBG (10, "pic_dot=%d\n", pic_dot); 1359141cc406Sopenharmony_ci return pic_dot; 1360141cc406Sopenharmony_ci} 1361141cc406Sopenharmony_ci 1362141cc406Sopenharmony_cistatic int 1363141cc406Sopenharmony_cilines_per_scan (Coolscan_t * s) 1364141cc406Sopenharmony_ci{ 1365141cc406Sopenharmony_ci int pic_line; 1366141cc406Sopenharmony_ci if(s->LS<2) 1367141cc406Sopenharmony_ci { pic_line = (s->bry - s->tly + s->y_nres) / s->y_nres; 1368141cc406Sopenharmony_ci } 1369141cc406Sopenharmony_ci else 1370141cc406Sopenharmony_ci { pic_line = (( s->bry - s->tly + 1.0 ) / s->y_nres); 1371141cc406Sopenharmony_ci } 1372141cc406Sopenharmony_ci DBG (10, "pic_line=%d\n", pic_line); 1373141cc406Sopenharmony_ci return pic_line; 1374141cc406Sopenharmony_ci} 1375141cc406Sopenharmony_ci 1376141cc406Sopenharmony_cistatic int 1377141cc406Sopenharmony_ciscan_bytes_per_line (Coolscan_t * s) 1378141cc406Sopenharmony_ci{ int bpl; 1379141cc406Sopenharmony_ci switch(s->colormode) 1380141cc406Sopenharmony_ci { case RGB: 1381141cc406Sopenharmony_ci case GREYSCALE: 1382141cc406Sopenharmony_ci bpl=pixels_per_line (s) * 3; 1383141cc406Sopenharmony_ci if(s->bits_per_color>8) bpl=bpl*2; 1384141cc406Sopenharmony_ci return bpl; 1385141cc406Sopenharmony_ci break; 1386141cc406Sopenharmony_ci case RGBI: 1387141cc406Sopenharmony_ci case IRED: 1388141cc406Sopenharmony_ci bpl=pixels_per_line (s) * 4; 1389141cc406Sopenharmony_ci if(s->bits_per_color>8) bpl=bpl*2; 1390141cc406Sopenharmony_ci return bpl; 1391141cc406Sopenharmony_ci break; 1392141cc406Sopenharmony_ci } 1393141cc406Sopenharmony_ci return 0; 1394141cc406Sopenharmony_ci} 1395141cc406Sopenharmony_ci 1396141cc406Sopenharmony_cistatic int 1397141cc406Sopenharmony_ciwrite_bytes_per_line (Coolscan_t * s) 1398141cc406Sopenharmony_ci{ int bpl; 1399141cc406Sopenharmony_ci switch(s->colormode) 1400141cc406Sopenharmony_ci { case RGB: 1401141cc406Sopenharmony_ci bpl=pixels_per_line (s) * 3; 1402141cc406Sopenharmony_ci if(s->bits_per_color>8) bpl=bpl*2; 1403141cc406Sopenharmony_ci return bpl; 1404141cc406Sopenharmony_ci break; 1405141cc406Sopenharmony_ci case RGBI: 1406141cc406Sopenharmony_ci bpl=pixels_per_line (s) * 4; 1407141cc406Sopenharmony_ci if(s->bits_per_color>8) bpl=bpl*2; 1408141cc406Sopenharmony_ci return bpl; 1409141cc406Sopenharmony_ci break; 1410141cc406Sopenharmony_ci case IRED: 1411141cc406Sopenharmony_ci case GREYSCALE: 1412141cc406Sopenharmony_ci bpl= pixels_per_line (s) ; 1413141cc406Sopenharmony_ci if(s->bits_per_color>8) bpl=bpl*2; 1414141cc406Sopenharmony_ci return bpl; 1415141cc406Sopenharmony_ci break; 1416141cc406Sopenharmony_ci } 1417141cc406Sopenharmony_ci return 0; 1418141cc406Sopenharmony_ci} 1419141cc406Sopenharmony_ci 1420141cc406Sopenharmony_ci 1421141cc406Sopenharmony_cistatic void 1422141cc406Sopenharmony_cicoolscan_trim_rowbufsize (Coolscan_t * s) 1423141cc406Sopenharmony_ci{ 1424141cc406Sopenharmony_ci unsigned int row_len; 1425141cc406Sopenharmony_ci row_len = scan_bytes_per_line (s); 1426141cc406Sopenharmony_ci s->row_bufsize = (s->row_bufsize < row_len) ? s->row_bufsize 1427141cc406Sopenharmony_ci : s->row_bufsize - (s->row_bufsize % row_len); 1428141cc406Sopenharmony_ci DBG (10, "trim_bufsize to %d\n", s->row_bufsize); 1429141cc406Sopenharmony_ci} 1430141cc406Sopenharmony_ci 1431141cc406Sopenharmony_cistatic int 1432141cc406Sopenharmony_cicoolscan_check_values (Coolscan_t * s) 1433141cc406Sopenharmony_ci{ 1434141cc406Sopenharmony_ci DBG (10, "check_values\n"); 1435141cc406Sopenharmony_ci /* -------------------------- asf --------------------------------- */ 1436141cc406Sopenharmony_ci if (s->asf != 0) 1437141cc406Sopenharmony_ci { 1438141cc406Sopenharmony_ci if (s->autofeeder == 0) 1439141cc406Sopenharmony_ci { 1440141cc406Sopenharmony_ci DBG (1, "ERROR: ASF-MODE NOT SUPPORTED BY SCANNER, ABORTING\n"); 1441141cc406Sopenharmony_ci return (1); 1442141cc406Sopenharmony_ci } 1443141cc406Sopenharmony_ci } 1444141cc406Sopenharmony_ci 1445141cc406Sopenharmony_ci return (0); 1446141cc406Sopenharmony_ci} 1447141cc406Sopenharmony_ci 1448141cc406Sopenharmony_ci/* test_little_endian */ 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_cistatic SANE_Bool 1451141cc406Sopenharmony_cicoolscan_test_little_endian(void) 1452141cc406Sopenharmony_ci{ 1453141cc406Sopenharmony_ci SANE_Int testvalue = 255; 1454141cc406Sopenharmony_ci unsigned char *firstbyte = (unsigned char *) &testvalue; 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ci if (*firstbyte == 255) 1457141cc406Sopenharmony_ci { return SANE_TRUE; 1458141cc406Sopenharmony_ci } 1459141cc406Sopenharmony_ci return SANE_FALSE; 1460141cc406Sopenharmony_ci} 1461141cc406Sopenharmony_ci 1462141cc406Sopenharmony_cistatic int 1463141cc406Sopenharmony_ciget_inquiery_part_LS30 (Coolscan_t * s, unsigned char part) 1464141cc406Sopenharmony_ci{ 1465141cc406Sopenharmony_ci int size; 1466141cc406Sopenharmony_ci 1467141cc406Sopenharmony_ci /* Get length of response */ 1468141cc406Sopenharmony_ci inquiry.cmd[1]=0x01; 1469141cc406Sopenharmony_ci inquiry.cmd[2]=part; 1470141cc406Sopenharmony_ci size=4; 1471141cc406Sopenharmony_ci set_inquiry_return_size (inquiry.cmd, size); 1472141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size, 1473141cc406Sopenharmony_ci s->buffer, size); 1474141cc406Sopenharmony_ci size=get_inquiry_length(s->buffer); 1475141cc406Sopenharmony_ci size+=4; 1476141cc406Sopenharmony_ci /* then get inquiry with actual size */ 1477141cc406Sopenharmony_ci set_inquiry_return_size (inquiry.cmd, size); 1478141cc406Sopenharmony_ci do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size, 1479141cc406Sopenharmony_ci s->buffer, size); 1480141cc406Sopenharmony_ci return size; 1481141cc406Sopenharmony_ci} 1482141cc406Sopenharmony_ci 1483141cc406Sopenharmony_cistatic int 1484141cc406Sopenharmony_cicoolscan_read_var_data_block (Coolscan_t * s,int datatype) 1485141cc406Sopenharmony_ci{ 1486141cc406Sopenharmony_ci int r; 1487141cc406Sopenharmony_ci int size; 1488141cc406Sopenharmony_ci 1489141cc406Sopenharmony_ci DBG (10, "read_data_block (type= %x)\n",datatype); 1490141cc406Sopenharmony_ci /*wait_scanner(s); */ 1491141cc406Sopenharmony_ci 1492141cc406Sopenharmony_ci sread.cmd[2]=datatype; 1493141cc406Sopenharmony_ci sread.cmd[4]=00; 1494141cc406Sopenharmony_ci sread.cmd[5]=03; 1495141cc406Sopenharmony_ci size=6; 1496141cc406Sopenharmony_ci set_R_xfer_length (sread.cmd, size); 1497141cc406Sopenharmony_ci r = do_scsi_cmd (s->sfd, sread.cmd, sread.size, 1498141cc406Sopenharmony_ci s->buffer, size); 1499141cc406Sopenharmony_ci size=s->buffer[5]; 1500141cc406Sopenharmony_ci set_R_xfer_length (sread.cmd, size); 1501141cc406Sopenharmony_ci r = do_scsi_cmd (s->sfd, sread.cmd, sread.size, 1502141cc406Sopenharmony_ci s->buffer, size); 1503141cc406Sopenharmony_ci return ((r != 0) ? -1 : size); 1504141cc406Sopenharmony_ci} 1505141cc406Sopenharmony_ci 1506141cc406Sopenharmony_cistatic int 1507141cc406Sopenharmony_ciget_inquiery_LS30 (Coolscan_t * s) 1508141cc406Sopenharmony_ci{ 1509141cc406Sopenharmony_ci unsigned char part; 1510141cc406Sopenharmony_ci unsigned char parts[5]; 1511141cc406Sopenharmony_ci int i; 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_ci /* Get vector of inquiery parts */ 1514141cc406Sopenharmony_ci get_inquiery_part_LS30(s, (unsigned char) 0); 1515141cc406Sopenharmony_ci /* Get the parts of inquiery */ 1516141cc406Sopenharmony_ci for(i=0;i<5;i++) 1517141cc406Sopenharmony_ci { parts[i]=((unsigned char *)s->buffer)[4+11+i]; 1518141cc406Sopenharmony_ci } 1519141cc406Sopenharmony_ci for(i=0;i<5;i++) 1520141cc406Sopenharmony_ci { part=parts[i]; 1521141cc406Sopenharmony_ci get_inquiery_part_LS30 (s, part); 1522141cc406Sopenharmony_ci switch(part) 1523141cc406Sopenharmony_ci { case 0x0c1:/* max size and resolution */ 1524141cc406Sopenharmony_ci s->adbits = 8; 1525141cc406Sopenharmony_ci s->outputbits = 8; 1526141cc406Sopenharmony_ci s->maxres = getnbyte(s->buffer+0x12,2)-1; 1527141cc406Sopenharmony_ci s->xmaxpix = getnbyte(s->buffer+0x53,2)-1; 1528141cc406Sopenharmony_ci s->ymaxpix = getnbyte(s->buffer+0x3c,2)-1; 1529141cc406Sopenharmony_ci break; 1530141cc406Sopenharmony_ci case 0x0d1: 1531141cc406Sopenharmony_ci break; 1532141cc406Sopenharmony_ci case 0x0e1: 1533141cc406Sopenharmony_ci break; 1534141cc406Sopenharmony_ci case 0x0f0: 1535141cc406Sopenharmony_ci break; 1536141cc406Sopenharmony_ci case 0x0f8: 1537141cc406Sopenharmony_ci break; 1538141cc406Sopenharmony_ci } 1539141cc406Sopenharmony_ci } 1540141cc406Sopenharmony_ci 1541141cc406Sopenharmony_ci /* get windows */ 1542141cc406Sopenharmony_ci coolscan_get_window_param_LS30 (s,0,0); 1543141cc406Sopenharmony_ci s->xmax = get_WD_width(s->buffer); 1544141cc406Sopenharmony_ci s->ymax = get_WD_length(s->buffer); 1545141cc406Sopenharmony_ci coolscan_get_window_param_LS30 (s,1,0); 1546141cc406Sopenharmony_ci coolscan_get_window_param_LS30 (s,2,0); 1547141cc406Sopenharmony_ci coolscan_get_window_param_LS30 (s,3,0); 1548141cc406Sopenharmony_ci coolscan_get_window_param_LS30 (s,4,0); 1549141cc406Sopenharmony_ci coolscan_get_window_param_LS30 (s,9,0); 1550141cc406Sopenharmony_ci 1551141cc406Sopenharmony_ci s->analoggamma = 0; 1552141cc406Sopenharmony_ci return 1; 1553141cc406Sopenharmony_ci} 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_cistatic int 1556141cc406Sopenharmony_ciget_feeder_type_LS30 (Coolscan_t * s) 1557141cc406Sopenharmony_ci{ 1558141cc406Sopenharmony_ci int size; 1559141cc406Sopenharmony_ci unsigned char *ptr; 1560141cc406Sopenharmony_ci int ima; 1561141cc406Sopenharmony_ci 1562141cc406Sopenharmony_ci /* find out about Film-strip-feeder or Mount-Feeder */ 1563141cc406Sopenharmony_ci size=get_inquiery_part_LS30(s, (unsigned char) 1); 1564141cc406Sopenharmony_ci if(strncmp((char *)s->buffer+5,"Strip",5)==0) 1565141cc406Sopenharmony_ci { s->feeder=STRIP_FEEDER; 1566141cc406Sopenharmony_ci s->autofeeder = 1; 1567141cc406Sopenharmony_ci } 1568141cc406Sopenharmony_ci if(strncmp((char *)s->buffer+5,"Mount",5)==0) 1569141cc406Sopenharmony_ci { s->feeder=MOUNT_FEEDER; 1570141cc406Sopenharmony_ci } 1571141cc406Sopenharmony_ci /* find out about Film-strip-feeder positions*/ 1572141cc406Sopenharmony_ci if(s->feeder==STRIP_FEEDER) 1573141cc406Sopenharmony_ci { size=coolscan_read_var_data_block (s,(int)0x88); 1574141cc406Sopenharmony_ci if(size>=4) 1575141cc406Sopenharmony_ci { s->numima=s->buffer[3]; 1576141cc406Sopenharmony_ci if(s->numima>6) s->numima=6; /* limit to 6 images for now */ 1577141cc406Sopenharmony_ci if(s->numima>(size-4)/16) s->numima=(size-4)/16; 1578141cc406Sopenharmony_ci ptr=s->buffer+4; 1579141cc406Sopenharmony_ci for(ima=0;ima<s->numima;ima++) 1580141cc406Sopenharmony_ci { s->ipos[ima].start=getnbyte(ptr,4); 1581141cc406Sopenharmony_ci s->ipos[ima].offset=getnbyte(ptr+4,4); 1582141cc406Sopenharmony_ci s->ipos[ima].end=getnbyte(ptr+8,4); 1583141cc406Sopenharmony_ci s->ipos[ima].height=getnbyte(ptr+12,4); 1584141cc406Sopenharmony_ci ptr+=16; 1585141cc406Sopenharmony_ci } 1586141cc406Sopenharmony_ci } 1587141cc406Sopenharmony_ci s->posima=0; 1588141cc406Sopenharmony_ci } 1589141cc406Sopenharmony_ci return 1; 1590141cc406Sopenharmony_ci} 1591141cc406Sopenharmony_ci 1592141cc406Sopenharmony_ci 1593141cc406Sopenharmony_cistatic int 1594141cc406Sopenharmony_ciget_internal_info_LS20 (Coolscan_t * s) 1595141cc406Sopenharmony_ci{ 1596141cc406Sopenharmony_ci int ret; 1597141cc406Sopenharmony_ci 1598141cc406Sopenharmony_ci DBG (10, "get_internal_info\n"); 1599141cc406Sopenharmony_ci wait_scanner (s); 1600141cc406Sopenharmony_ci memset (s->buffer, '\0', DI_length); /* clear buffer */ 1601141cc406Sopenharmony_ci 1602141cc406Sopenharmony_ci set_R_datatype_code (sread.cmd, R_device_internal_info); 1603141cc406Sopenharmony_ci set_R_datatype_qual_upper (sread.cmd, R_DQ_none); 1604141cc406Sopenharmony_ci set_R_xfer_length (sread.cmd, DI_length); 1605141cc406Sopenharmony_ci /* then get inquiry with actual size */ 1606141cc406Sopenharmony_ci ret = do_scsi_cmd (s->sfd, sread.cmd, sread.size, 1607141cc406Sopenharmony_ci s->buffer, DI_length); 1608141cc406Sopenharmony_ci 1609141cc406Sopenharmony_ci s->adbits = get_DI_ADbits (s->buffer); 1610141cc406Sopenharmony_ci s->outputbits = get_DI_Outputbits (s->buffer); 1611141cc406Sopenharmony_ci s->maxres = get_DI_MaxResolution (s->buffer); 1612141cc406Sopenharmony_ci s->xmax = get_DI_Xmax (s->buffer); 1613141cc406Sopenharmony_ci s->ymax = get_DI_Ymax (s->buffer); 1614141cc406Sopenharmony_ci s->xmaxpix = get_DI_Xmaxpixel (s->buffer); 1615141cc406Sopenharmony_ci s->ymaxpix = get_DI_Ymaxpixel (s->buffer); 1616141cc406Sopenharmony_ci s->ycurrent = get_DI_currentY (s->buffer); 1617141cc406Sopenharmony_ci s->currentfocus = get_DI_currentFocus (s->buffer); 1618141cc406Sopenharmony_ci s->currentscanpitch = get_DI_currentscanpitch (s->buffer); 1619141cc406Sopenharmony_ci s->autofeeder = get_DI_autofeeder (s->buffer); 1620141cc406Sopenharmony_ci s->analoggamma = get_DI_analoggamma (s->buffer); 1621141cc406Sopenharmony_ci s->derr[0] = get_DI_deviceerror0 (s->buffer); 1622141cc406Sopenharmony_ci s->derr[1] = get_DI_deviceerror1 (s->buffer); 1623141cc406Sopenharmony_ci s->derr[2] = get_DI_deviceerror2 (s->buffer); 1624141cc406Sopenharmony_ci s->derr[3] = get_DI_deviceerror3 (s->buffer); 1625141cc406Sopenharmony_ci s->derr[4] = get_DI_deviceerror4 (s->buffer); 1626141cc406Sopenharmony_ci s->derr[5] = get_DI_deviceerror5 (s->buffer); 1627141cc406Sopenharmony_ci s->derr[6] = get_DI_deviceerror6 (s->buffer); 1628141cc406Sopenharmony_ci s->derr[7] = get_DI_deviceerror7 (s->buffer); 1629141cc406Sopenharmony_ci s->wbetr_r = get_DI_WBETR_R (s->buffer); 1630141cc406Sopenharmony_ci s->webtr_g = get_DI_WBETR_G (s->buffer); 1631141cc406Sopenharmony_ci s->webtr_b = get_DI_WBETR_B (s->buffer); 1632141cc406Sopenharmony_ci s->pretv_r = get_DI_PRETV_R (s->buffer); 1633141cc406Sopenharmony_ci s->pretv_g = get_DI_PRETV_G (s->buffer); 1634141cc406Sopenharmony_ci s->pretv_r = get_DI_PRETV_R (s->buffer); 1635141cc406Sopenharmony_ci s->cetv_r = get_DI_CETV_R (s->buffer); 1636141cc406Sopenharmony_ci s->cetv_g = get_DI_CETV_G (s->buffer); 1637141cc406Sopenharmony_ci s->cetv_b = get_DI_CETV_B (s->buffer); 1638141cc406Sopenharmony_ci s->ietu_r = get_DI_IETU_R (s->buffer); 1639141cc406Sopenharmony_ci s->ietu_g = get_DI_IETU_G (s->buffer); 1640141cc406Sopenharmony_ci s->ietu_b = get_DI_IETU_B (s->buffer); 1641141cc406Sopenharmony_ci s->limitcondition = get_DI_limitcondition (s->buffer); 1642141cc406Sopenharmony_ci s->offsetdata_r = get_DI_offsetdata_R (s->buffer); 1643141cc406Sopenharmony_ci s->offsetdata_g = get_DI_offsetdata_G (s->buffer); 1644141cc406Sopenharmony_ci s->offsetdata_b = get_DI_offsetdata_B (s->buffer); 1645141cc406Sopenharmony_ci get_DI_poweron_errors (s->buffer, s->power_on_errors); 1646141cc406Sopenharmony_ci 1647141cc406Sopenharmony_ci DBG (10, 1648141cc406Sopenharmony_ci "\tadbits=%d\toutputbits=%d\tmaxres=%d\txmax=%d\tymax=%d\n" 1649141cc406Sopenharmony_ci "\txmaxpix=%d\tymaxpix=%d\tycurrent=%d\tcurrentfocus=%d\n" 1650141cc406Sopenharmony_ci "\tautofeeder=%s\tanaloggamma=%s\tcurrentscanpitch=%d\n", 1651141cc406Sopenharmony_ci s->adbits, s->outputbits, s->maxres, s->xmax, s->ymax, 1652141cc406Sopenharmony_ci s->xmaxpix, s->ymaxpix, s->ycurrent, s->currentfocus, 1653141cc406Sopenharmony_ci s->autofeeder ? "Yes" : "No", s->analoggamma ? "Yes" : "No", 1654141cc406Sopenharmony_ci s->currentscanpitch); 1655141cc406Sopenharmony_ci DBG (10, 1656141cc406Sopenharmony_ci "\tWhite balance exposure time var [RGB]=\t%d %d %d\n" 1657141cc406Sopenharmony_ci "\tPrescan result exposure time var [RGB]=\t%d %d %d\n" 1658141cc406Sopenharmony_ci "\tCurrent exposure time var.[RGB]=\t%d %d %d\n" 1659141cc406Sopenharmony_ci "\tInternal exposure time unit[RGB]=\t%d %d %d\n", 1660141cc406Sopenharmony_ci s->wbetr_r, s->webtr_g, s->webtr_b, s->pretv_r, s->pretv_g, 1661141cc406Sopenharmony_ci s->pretv_r, s->cetv_r, s->cetv_g, s->cetv_b, s->ietu_r, 1662141cc406Sopenharmony_ci s->ietu_g, s->ietu_b); 1663141cc406Sopenharmony_ci DBG (10, 1664141cc406Sopenharmony_ci "\toffsetdata_[rgb]=\t0x%x 0x%x 0x%x\n" 1665141cc406Sopenharmony_ci "\tlimitcondition=0x%x\n" 1666141cc406Sopenharmony_ci "\tdevice error code = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n" 1667141cc406Sopenharmony_ci "\tpower-on errors = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", 1668141cc406Sopenharmony_ci s->offsetdata_r, s->offsetdata_g, s->offsetdata_b, 1669141cc406Sopenharmony_ci s->limitcondition, 1670141cc406Sopenharmony_ci s->derr[0], s->derr[1], s->derr[2], s->derr[3], s->derr[4], 1671141cc406Sopenharmony_ci s->derr[5], s->derr[6], s->derr[7], 1672141cc406Sopenharmony_ci s->power_on_errors[0], s->power_on_errors[1], 1673141cc406Sopenharmony_ci s->power_on_errors[2], s->power_on_errors[3], 1674141cc406Sopenharmony_ci s->power_on_errors[4], s->power_on_errors[5], 1675141cc406Sopenharmony_ci s->power_on_errors[6], s->power_on_errors[7]); 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci return ret; 1678141cc406Sopenharmony_ci} 1679141cc406Sopenharmony_ci 1680141cc406Sopenharmony_cistatic int 1681141cc406Sopenharmony_ciget_internal_info (Coolscan_t * s) 1682141cc406Sopenharmony_ci{ 1683141cc406Sopenharmony_ci int ret; 1684141cc406Sopenharmony_ci 1685141cc406Sopenharmony_ci DBG (10, "get_internal_info\n"); 1686141cc406Sopenharmony_ci 1687141cc406Sopenharmony_ci if(s->LS<2) /* distinguish between old and new scanners */ 1688141cc406Sopenharmony_ci { ret=get_internal_info_LS20 (s); 1689141cc406Sopenharmony_ci } 1690141cc406Sopenharmony_ci else 1691141cc406Sopenharmony_ci { ret=get_inquiery_LS30 (s); 1692141cc406Sopenharmony_ci } 1693141cc406Sopenharmony_ci return ret; 1694141cc406Sopenharmony_ci} 1695141cc406Sopenharmony_ci 1696141cc406Sopenharmony_cistatic void 1697141cc406Sopenharmony_cicoolscan_get_inquiry_values (Coolscan_t * s) 1698141cc406Sopenharmony_ci{ 1699141cc406Sopenharmony_ci unsigned char *inquiry_block; 1700141cc406Sopenharmony_ci 1701141cc406Sopenharmony_ci DBG (10, "get_inquiry_values\n"); 1702141cc406Sopenharmony_ci 1703141cc406Sopenharmony_ci inquiry_block = (unsigned char *) s->buffer; 1704141cc406Sopenharmony_ci s->inquiry_len = 36; 1705141cc406Sopenharmony_ci 1706141cc406Sopenharmony_ci get_inquiry_vendor ((char *)inquiry_block, (char *)s->vendor); 1707141cc406Sopenharmony_ci s->vendor[8] = '\0'; 1708141cc406Sopenharmony_ci get_inquiry_product ((char *)inquiry_block, (char *)s->product); 1709141cc406Sopenharmony_ci s->product[16] = '\0'; 1710141cc406Sopenharmony_ci get_inquiry_version ((char *)inquiry_block, (char *)s->version); 1711141cc406Sopenharmony_ci s->version[4] = '\0'; 1712141cc406Sopenharmony_ci 1713141cc406Sopenharmony_ci if (s->inquiry_len < 36) 1714141cc406Sopenharmony_ci { 1715141cc406Sopenharmony_ci DBG (1, "WARNING: inquiry return block is unexpected short (%d instead of 36).\n", s->inquiry_len); 1716141cc406Sopenharmony_ci } 1717141cc406Sopenharmony_ci s->inquiry_wdb_len = 117; 1718141cc406Sopenharmony_ci return; 1719141cc406Sopenharmony_ci} 1720141cc406Sopenharmony_ci 1721141cc406Sopenharmony_cistatic void 1722141cc406Sopenharmony_cicoolscan_initialize_values (Coolscan_t * s) 1723141cc406Sopenharmony_ci{ 1724141cc406Sopenharmony_ci int i; 1725141cc406Sopenharmony_ci DBG (10, "initialize_values\n"); 1726141cc406Sopenharmony_ci /* Initialize us structure */ 1727141cc406Sopenharmony_ci if(s->LS<2) /* LS-20 or LS-10000 */ 1728141cc406Sopenharmony_ci { select_MUD (s); /* must be before mode_sense - not for LS-30*/ 1729141cc406Sopenharmony_ci coolscan_mode_sense (s); /* Obtain MUD (Measurement Unit Divisor) */ 1730141cc406Sopenharmony_ci get_internal_info (s); /* MUST be called first. */ 1731141cc406Sopenharmony_ci s->wdb_len = 117; 1732141cc406Sopenharmony_ci } 1733141cc406Sopenharmony_ci if(s->LS>=2) /* LS-30 */ 1734141cc406Sopenharmony_ci { 1735141cc406Sopenharmony_ci get_inquiery_LS30(s); /* Info about scanner*/ 1736141cc406Sopenharmony_ci select_MUD (s); /* must be before mode_sense */ 1737141cc406Sopenharmony_ci get_feeder_type_LS30(s); 1738141cc406Sopenharmony_ci s->wdb_len = 117; 1739141cc406Sopenharmony_ci } 1740141cc406Sopenharmony_ci 1741141cc406Sopenharmony_ci s->cont = 0; /* do not continue if scanner is unknown */ 1742141cc406Sopenharmony_ci s->verbose = 2; /* 1=verbose,2=very verbose */ 1743141cc406Sopenharmony_ci 1744141cc406Sopenharmony_ci 1745141cc406Sopenharmony_ci s->x_nres = s->y_nres = 2; /* 2 => 1350 dpi */ 1746141cc406Sopenharmony_ci s->x_p_nres = s->y_p_nres = 9; /* 9 => 300 dpi */ 1747141cc406Sopenharmony_ci s->tlx = 0; 1748141cc406Sopenharmony_ci s->tly = 0; 1749141cc406Sopenharmony_ci s->brx = s->xmaxpix; /* 2700 / 1200; */ 1750141cc406Sopenharmony_ci s->bry = s->ymaxpix; /* 2700 / 1200; */ 1751141cc406Sopenharmony_ci 1752141cc406Sopenharmony_ci 1753141cc406Sopenharmony_ci s->set_auto = 0; /* Always 0 on Nikon LS-{100|2}0 */ 1754141cc406Sopenharmony_ci s->preview = 0; /* 1 for preview */ 1755141cc406Sopenharmony_ci s->colormode = RGB; /* GREYSCALE or RGB */ 1756141cc406Sopenharmony_ci s->colormode_p = RGB; /* GREYSCALE or RGB for preview*/ 1757141cc406Sopenharmony_ci s->asf = 0; /* 1 if asf shall be used */ 1758141cc406Sopenharmony_ci s->gammaselection = WD_Linear; 1759141cc406Sopenharmony_ci 1760141cc406Sopenharmony_ci s->brightness = 128; 1761141cc406Sopenharmony_ci s->brightness_R = 128; 1762141cc406Sopenharmony_ci s->brightness_G = 128; 1763141cc406Sopenharmony_ci s->brightness_B = 128; 1764141cc406Sopenharmony_ci s->contrast = 128; 1765141cc406Sopenharmony_ci s->contrast_R = 128; 1766141cc406Sopenharmony_ci s->contrast_G = 128; 1767141cc406Sopenharmony_ci s->contrast_B = 128; 1768141cc406Sopenharmony_ci 1769141cc406Sopenharmony_ci s->exposure_R = 50; 1770141cc406Sopenharmony_ci s->exposure_G = 50; 1771141cc406Sopenharmony_ci s->exposure_B = 50; 1772141cc406Sopenharmony_ci 1773141cc406Sopenharmony_ci s->pretv_r=40000; 1774141cc406Sopenharmony_ci s->pretv_g=40000; 1775141cc406Sopenharmony_ci s->pretv_b=40000; 1776141cc406Sopenharmony_ci 1777141cc406Sopenharmony_ci s->shift_R = 128; 1778141cc406Sopenharmony_ci s->shift_G = 128; 1779141cc406Sopenharmony_ci s->shift_B = 128; 1780141cc406Sopenharmony_ci 1781141cc406Sopenharmony_ci s->ired_red=60; 1782141cc406Sopenharmony_ci s->ired_green=1; 1783141cc406Sopenharmony_ci s->ired_blue=1; 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci s->prescan = 1; 1786141cc406Sopenharmony_ci s->bits_per_color = 8; 1787141cc406Sopenharmony_ci s->rgb_control = 0; 1788141cc406Sopenharmony_ci s->gamma_bind = 1; 1789141cc406Sopenharmony_ci switch(s->LS) 1790141cc406Sopenharmony_ci { case 0:s->lutlength=2048; 1791141cc406Sopenharmony_ci s->max_lut_val=256; 1792141cc406Sopenharmony_ci break; 1793141cc406Sopenharmony_ci case 1:s->lutlength=512; 1794141cc406Sopenharmony_ci s->max_lut_val=512; 1795141cc406Sopenharmony_ci break; 1796141cc406Sopenharmony_ci case 2:s->lutlength=1024; 1797141cc406Sopenharmony_ci s->max_lut_val=1024; 1798141cc406Sopenharmony_ci break; 1799141cc406Sopenharmony_ci case 3:s->lutlength=4096; 1800141cc406Sopenharmony_ci s->max_lut_val=4096; 1801141cc406Sopenharmony_ci break; 1802141cc406Sopenharmony_ci } 1803141cc406Sopenharmony_ci for (i = 0; i < s->lutlength; i++) 1804141cc406Sopenharmony_ci { 1805141cc406Sopenharmony_ci s->gamma[i] =((short)((((double)i)/s->lutlength)*s->max_lut_val)); 1806141cc406Sopenharmony_ci s->gamma_r[i] = s->gamma[i]; 1807141cc406Sopenharmony_ci s->gamma_g[i] = s->gamma[i]; 1808141cc406Sopenharmony_ci s->gamma_b[i] = s->gamma[i]; 1809141cc406Sopenharmony_ci } 1810141cc406Sopenharmony_ci 1811141cc406Sopenharmony_ci if (coolscan_test_little_endian() == SANE_TRUE) 1812141cc406Sopenharmony_ci { 1813141cc406Sopenharmony_ci s->low_byte_first = 1; /* in 2 byte mode send lowbyte first */ 1814141cc406Sopenharmony_ci DBG(10,"backend runs on little endian machine\n"); 1815141cc406Sopenharmony_ci } 1816141cc406Sopenharmony_ci else 1817141cc406Sopenharmony_ci { 1818141cc406Sopenharmony_ci s->low_byte_first = 0; /* in 2 byte mode send highbyte first */ 1819141cc406Sopenharmony_ci DBG(10,"backend runs on big endian machine\n"); 1820141cc406Sopenharmony_ci } 1821141cc406Sopenharmony_ci} 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_cistatic void 1824141cc406Sopenharmony_cihexdump (int level, char *comment, unsigned char *p, int l) 1825141cc406Sopenharmony_ci{ 1826141cc406Sopenharmony_ci int i; 1827141cc406Sopenharmony_ci char line[128]; 1828141cc406Sopenharmony_ci char *ptr; 1829141cc406Sopenharmony_ci 1830141cc406Sopenharmony_ci DBG (level, "%s\n", comment); 1831141cc406Sopenharmony_ci ptr = line; 1832141cc406Sopenharmony_ci for (i = 0; i < l; i++, p++) 1833141cc406Sopenharmony_ci { 1834141cc406Sopenharmony_ci if ((i % 16) == 0) 1835141cc406Sopenharmony_ci { 1836141cc406Sopenharmony_ci if (ptr != line) 1837141cc406Sopenharmony_ci { 1838141cc406Sopenharmony_ci *ptr = '\0'; 1839141cc406Sopenharmony_ci DBG (level, "%s\n", line); 1840141cc406Sopenharmony_ci ptr = line; 1841141cc406Sopenharmony_ci } 1842141cc406Sopenharmony_ci sprintf (ptr, "%3.3d:", i); 1843141cc406Sopenharmony_ci ptr += 4; 1844141cc406Sopenharmony_ci } 1845141cc406Sopenharmony_ci sprintf (ptr, " %2.2x", *p); 1846141cc406Sopenharmony_ci ptr += 3; 1847141cc406Sopenharmony_ci } 1848141cc406Sopenharmony_ci *ptr = '\0'; 1849141cc406Sopenharmony_ci DBG (level, "%s\n", line); 1850141cc406Sopenharmony_ci} 1851141cc406Sopenharmony_ci 1852141cc406Sopenharmony_ci 1853141cc406Sopenharmony_cistatic SANE_Status 1854141cc406Sopenharmony_cisense_handler (int scsi_fd, unsigned char * result, void *arg) 1855141cc406Sopenharmony_ci{ 1856141cc406Sopenharmony_ci (void) scsi_fd; 1857141cc406Sopenharmony_ci (void) arg; 1858141cc406Sopenharmony_ci 1859141cc406Sopenharmony_ci if (result[0] != 0x70) 1860141cc406Sopenharmony_ci { 1861141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; /* we only know about this one */ 1862141cc406Sopenharmony_ci } 1863141cc406Sopenharmony_ci return request_sense_parse(result); 1864141cc406Sopenharmony_ci 1865141cc406Sopenharmony_ci} 1866141cc406Sopenharmony_ci 1867141cc406Sopenharmony_ci 1868141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 1869141cc406Sopenharmony_ci 1870141cc406Sopenharmony_ci 1871141cc406Sopenharmony_ci/* ilu per mm */ 1872141cc406Sopenharmony_ci 1873141cc406Sopenharmony_ci#define length_quant SANE_UNFIX(SANE_FIX(MM_PER_INCH / 2700.0)) 1874141cc406Sopenharmony_ci#define mmToIlu(mm) ((mm) / length_quant) 1875141cc406Sopenharmony_ci#define iluToMm(ilu) ((ilu) * length_quant) 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci#define P_200_TO_255(per) SANE_UNFIX((per + 100) * 255/200 ) 1878141cc406Sopenharmony_ci#define P_100_TO_255(per) SANE_UNFIX(per * 255/100 ) 1879141cc406Sopenharmony_ci 1880141cc406Sopenharmony_cistatic const char negativeStr[] = "Negative"; 1881141cc406Sopenharmony_cistatic const char positiveStr[] = "Positive"; 1882141cc406Sopenharmony_cistatic SANE_String_Const type_list[] = 1883141cc406Sopenharmony_ci{ 1884141cc406Sopenharmony_ci positiveStr, 1885141cc406Sopenharmony_ci negativeStr, 1886141cc406Sopenharmony_ci 0 1887141cc406Sopenharmony_ci}; 1888141cc406Sopenharmony_ci 1889141cc406Sopenharmony_cistatic const char colorStr[] = SANE_VALUE_SCAN_MODE_COLOR; 1890141cc406Sopenharmony_cistatic const char grayStr[] = SANE_VALUE_SCAN_MODE_GRAY; 1891141cc406Sopenharmony_cistatic const char rgbiStr[] = "RGBI"; 1892141cc406Sopenharmony_cistatic const char iredStr[] = "Infrared"; 1893141cc406Sopenharmony_ci 1894141cc406Sopenharmony_cistatic SANE_String_Const scan_mode_list_LS20[] = 1895141cc406Sopenharmony_ci{ 1896141cc406Sopenharmony_ci colorStr, 1897141cc406Sopenharmony_ci grayStr, 1898141cc406Sopenharmony_ci NULL 1899141cc406Sopenharmony_ci}; 1900141cc406Sopenharmony_ci 1901141cc406Sopenharmony_cistatic SANE_String_Const scan_mode_list_LS30[] = 1902141cc406Sopenharmony_ci{ 1903141cc406Sopenharmony_ci colorStr, 1904141cc406Sopenharmony_ci grayStr, 1905141cc406Sopenharmony_ci#ifdef HAS_IRED 1906141cc406Sopenharmony_ci rgbiStr, 1907141cc406Sopenharmony_ci#endif /* HAS_IRED */ 1908141cc406Sopenharmony_ci NULL 1909141cc406Sopenharmony_ci}; 1910141cc406Sopenharmony_ci 1911141cc406Sopenharmony_cistatic SANE_Int bit_depth_list[9]; 1912141cc406Sopenharmony_ci 1913141cc406Sopenharmony_cistatic const char neverStr[] = "never"; 1914141cc406Sopenharmony_cistatic const char previewStr[] = "before preview"; 1915141cc406Sopenharmony_cistatic const char scanStr[] = "before scan"; 1916141cc406Sopenharmony_cistatic const char preandscanStr[] = "before preview and scan"; 1917141cc406Sopenharmony_cistatic SANE_String_Const autofocus_mode_list[] = 1918141cc406Sopenharmony_ci{ 1919141cc406Sopenharmony_ci neverStr, 1920141cc406Sopenharmony_ci previewStr, 1921141cc406Sopenharmony_ci scanStr, 1922141cc406Sopenharmony_ci preandscanStr, 1923141cc406Sopenharmony_ci NULL 1924141cc406Sopenharmony_ci}; 1925141cc406Sopenharmony_ci 1926141cc406Sopenharmony_cistatic SANE_String_Const source_list[4] = 1927141cc406Sopenharmony_ci{NULL, NULL, NULL, NULL}; 1928141cc406Sopenharmony_ci 1929141cc406Sopenharmony_cistatic const SANE_Range gamma_range_8 = 1930141cc406Sopenharmony_ci{ 1931141cc406Sopenharmony_ci 0, /* minimum */ 1932141cc406Sopenharmony_ci 255, /* maximum */ 1933141cc406Sopenharmony_ci 1 /* quantization */ 1934141cc406Sopenharmony_ci}; 1935141cc406Sopenharmony_ci 1936141cc406Sopenharmony_ci 1937141cc406Sopenharmony_cistatic const SANE_Range gamma_range_9 = 1938141cc406Sopenharmony_ci{ 1939141cc406Sopenharmony_ci 0, /* minimum */ 1940141cc406Sopenharmony_ci 511, /* maximum */ 1941141cc406Sopenharmony_ci 1 /* quantization */ 1942141cc406Sopenharmony_ci}; 1943141cc406Sopenharmony_ci 1944141cc406Sopenharmony_cistatic const SANE_Range gamma_range_10 = 1945141cc406Sopenharmony_ci{ 1946141cc406Sopenharmony_ci 0, /* minimum */ 1947141cc406Sopenharmony_ci 1023, /* maximum */ 1948141cc406Sopenharmony_ci 1 /* quantization */ 1949141cc406Sopenharmony_ci}; 1950141cc406Sopenharmony_ci 1951141cc406Sopenharmony_cistatic const SANE_Range gamma_range_12 = 1952141cc406Sopenharmony_ci{ 1953141cc406Sopenharmony_ci 0, /* minimum */ 1954141cc406Sopenharmony_ci 4096, /* maximum */ 1955141cc406Sopenharmony_ci 1 /* quantization */ 1956141cc406Sopenharmony_ci}; 1957141cc406Sopenharmony_ci 1958141cc406Sopenharmony_cistatic const SANE_Range brightness_range = 1959141cc406Sopenharmony_ci{ 1960141cc406Sopenharmony_ci -5, 1961141cc406Sopenharmony_ci +5, 1962141cc406Sopenharmony_ci 1 1963141cc406Sopenharmony_ci}; 1964141cc406Sopenharmony_ci 1965141cc406Sopenharmony_cistatic const SANE_Range contrast_range = 1966141cc406Sopenharmony_ci{ 1967141cc406Sopenharmony_ci -5, 1968141cc406Sopenharmony_ci +5, 1969141cc406Sopenharmony_ci 0 1970141cc406Sopenharmony_ci}; 1971141cc406Sopenharmony_ci 1972141cc406Sopenharmony_cistatic const SANE_Range exposure_range = 1973141cc406Sopenharmony_ci{ 1974141cc406Sopenharmony_ci 24, 1975141cc406Sopenharmony_ci 400, 1976141cc406Sopenharmony_ci 2 1977141cc406Sopenharmony_ci}; 1978141cc406Sopenharmony_ci 1979141cc406Sopenharmony_cistatic const SANE_Range shift_range = 1980141cc406Sopenharmony_ci{ 1981141cc406Sopenharmony_ci -15, 1982141cc406Sopenharmony_ci +15, 1983141cc406Sopenharmony_ci 0 1984141cc406Sopenharmony_ci}; 1985141cc406Sopenharmony_ci 1986141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 1987141cc406Sopenharmony_cistatic int num_devices; 1988141cc406Sopenharmony_cistatic Coolscan_t *first_dev; 1989141cc406Sopenharmony_ci 1990141cc406Sopenharmony_ci 1991141cc406Sopenharmony_cistatic size_t 1992141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 1993141cc406Sopenharmony_ci{ 1994141cc406Sopenharmony_ci size_t size, max_size = 0; 1995141cc406Sopenharmony_ci int i; 1996141cc406Sopenharmony_ci 1997141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 1998141cc406Sopenharmony_ci { 1999141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 2000141cc406Sopenharmony_ci if (size > max_size) 2001141cc406Sopenharmony_ci max_size = size; 2002141cc406Sopenharmony_ci } 2003141cc406Sopenharmony_ci return max_size; 2004141cc406Sopenharmony_ci} 2005141cc406Sopenharmony_ci 2006141cc406Sopenharmony_cistatic SANE_Status 2007141cc406Sopenharmony_cido_eof (Coolscan_t * scanner) 2008141cc406Sopenharmony_ci{ 2009141cc406Sopenharmony_ci DBG (10, "do_eof\n"); 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci if (scanner->pipe >= 0) 2012141cc406Sopenharmony_ci { 2013141cc406Sopenharmony_ci close (scanner->pipe); 2014141cc406Sopenharmony_ci scanner->pipe = -1; 2015141cc406Sopenharmony_ci } 2016141cc406Sopenharmony_ci return SANE_STATUS_EOF; 2017141cc406Sopenharmony_ci} 2018141cc406Sopenharmony_ci 2019141cc406Sopenharmony_cistatic SANE_Status 2020141cc406Sopenharmony_cido_cancel (Coolscan_t * scanner) 2021141cc406Sopenharmony_ci{ 2022141cc406Sopenharmony_ci DBG (10, "do_cancel\n"); 2023141cc406Sopenharmony_ci swap_res (scanner); 2024141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci do_eof (scanner); /* close pipe and reposition scanner */ 2027141cc406Sopenharmony_ci 2028141cc406Sopenharmony_ci if (sanei_thread_is_valid (scanner->reader_pid)) 2029141cc406Sopenharmony_ci { 2030141cc406Sopenharmony_ci int exit_status; 2031141cc406Sopenharmony_ci 2032141cc406Sopenharmony_ci DBG (10, "do_cancel: kill reader_process\n"); 2033141cc406Sopenharmony_ci 2034141cc406Sopenharmony_ci /* ensure child knows it's time to stop: */ 2035141cc406Sopenharmony_ci sanei_thread_kill (scanner->reader_pid); 2036141cc406Sopenharmony_ci while (sanei_thread_waitpid(scanner->reader_pid, &exit_status) != 2037141cc406Sopenharmony_ci scanner->reader_pid ); 2038141cc406Sopenharmony_ci sanei_thread_invalidate (scanner->reader_pid); 2039141cc406Sopenharmony_ci } 2040141cc406Sopenharmony_ci 2041141cc406Sopenharmony_ci if (scanner->sfd >= 0) 2042141cc406Sopenharmony_ci { 2043141cc406Sopenharmony_ci coolscan_give_scanner (scanner); 2044141cc406Sopenharmony_ci DBG (10, "do_cancel: close filedescriptor\n"); 2045141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 2046141cc406Sopenharmony_ci scanner->sfd = -1; 2047141cc406Sopenharmony_ci } 2048141cc406Sopenharmony_ci 2049141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 2050141cc406Sopenharmony_ci} 2051141cc406Sopenharmony_ci 2052141cc406Sopenharmony_cistatic SANE_Status 2053141cc406Sopenharmony_ciattach_scanner (const char *devicename, Coolscan_t ** devp) 2054141cc406Sopenharmony_ci{ 2055141cc406Sopenharmony_ci Coolscan_t *dev; 2056141cc406Sopenharmony_ci int sfd; 2057141cc406Sopenharmony_ci 2058141cc406Sopenharmony_ci DBG (10, "attach_scanner: %s\n", devicename); 2059141cc406Sopenharmony_ci 2060141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 2061141cc406Sopenharmony_ci { 2062141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 2063141cc406Sopenharmony_ci { 2064141cc406Sopenharmony_ci if (devp) 2065141cc406Sopenharmony_ci { 2066141cc406Sopenharmony_ci *devp = dev; 2067141cc406Sopenharmony_ci } 2068141cc406Sopenharmony_ci DBG (5, "attach_scanner: scanner already attached (is ok)!\n"); 2069141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2070141cc406Sopenharmony_ci } 2071141cc406Sopenharmony_ci } 2072141cc406Sopenharmony_ci 2073141cc406Sopenharmony_ci DBG (10, "attach_scanner: opening %s\n", devicename); 2074141cc406Sopenharmony_ci if (sanei_scsi_open (devicename, &sfd, sense_handler, 0) != 0) 2075141cc406Sopenharmony_ci { 2076141cc406Sopenharmony_ci DBG (1, "attach_scanner: open failed\n"); 2077141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2078141cc406Sopenharmony_ci } 2079141cc406Sopenharmony_ci 2080141cc406Sopenharmony_ci if (NULL == (dev = malloc (sizeof (*dev)))) 2081141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2082141cc406Sopenharmony_ci 2083141cc406Sopenharmony_ci 2084141cc406Sopenharmony_ci dev->row_bufsize = (sanei_scsi_max_request_size < (64 * 1024)) ? 2085141cc406Sopenharmony_ci sanei_scsi_max_request_size : 64 * 1024; 2086141cc406Sopenharmony_ci 2087141cc406Sopenharmony_ci if ((dev->buffer = malloc (dev->row_bufsize)) == NULL) 2088141cc406Sopenharmony_ci/* if ((dev->buffer = malloc (sanei_scsi_max_request_size)) == NULL)*/ 2089141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2090141cc406Sopenharmony_ci 2091141cc406Sopenharmony_ci if ((dev->obuffer = malloc (dev->row_bufsize)) == NULL) 2092141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2093141cc406Sopenharmony_ci 2094141cc406Sopenharmony_ci dev->devicename = strdup (devicename); 2095141cc406Sopenharmony_ci dev->sfd = sfd; 2096141cc406Sopenharmony_ci 2097141cc406Sopenharmony_ci /* Nikon manual: Step 1 */ 2098141cc406Sopenharmony_ci if (coolscan_identify_scanner (dev) != 0) 2099141cc406Sopenharmony_ci { 2100141cc406Sopenharmony_ci DBG (1, "attach_scanner: scanner-identification failed\n"); 2101141cc406Sopenharmony_ci sanei_scsi_close (dev->sfd); 2102141cc406Sopenharmony_ci free (dev->buffer); 2103141cc406Sopenharmony_ci free (dev); 2104141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2105141cc406Sopenharmony_ci } 2106141cc406Sopenharmony_ci 2107141cc406Sopenharmony_ci /* Get MUD (via mode_sense), internal info (via get_internal_info), and 2108141cc406Sopenharmony_ci * initialize values */ 2109141cc406Sopenharmony_ci coolscan_initialize_values (dev); 2110141cc406Sopenharmony_ci 2111141cc406Sopenharmony_ci /* Why? */ 2112141cc406Sopenharmony_ci sanei_scsi_close (dev->sfd); 2113141cc406Sopenharmony_ci dev->sfd = -1; 2114141cc406Sopenharmony_ci 2115141cc406Sopenharmony_ci dev->sane.name = dev->devicename; 2116141cc406Sopenharmony_ci dev->sane.vendor = dev->vendor; 2117141cc406Sopenharmony_ci dev->sane.model = dev->product; 2118141cc406Sopenharmony_ci dev->sane.type = "slide scanner"; 2119141cc406Sopenharmony_ci 2120141cc406Sopenharmony_ci dev->x_range.min = SANE_FIX (0); 2121141cc406Sopenharmony_ci dev->x_range.quant = SANE_FIX (length_quant); 2122141cc406Sopenharmony_ci dev->x_range.max = SANE_FIX ((double) ((dev->xmaxpix) * length_quant)); 2123141cc406Sopenharmony_ci 2124141cc406Sopenharmony_ci dev->y_range.min = SANE_FIX (0.0); 2125141cc406Sopenharmony_ci dev->y_range.quant = SANE_FIX (length_quant); 2126141cc406Sopenharmony_ci dev->y_range.max = SANE_FIX ((double) ((dev->ymaxpix) * length_quant)); 2127141cc406Sopenharmony_ci 2128141cc406Sopenharmony_ci /* ...and this?? */ 2129141cc406Sopenharmony_ci dev->dpi_range.min = SANE_FIX (108); 2130141cc406Sopenharmony_ci dev->dpi_range.quant = SANE_FIX (0); 2131141cc406Sopenharmony_ci dev->dpi_range.max = SANE_FIX (dev->maxres); 2132141cc406Sopenharmony_ci DBG (10, "attach: dev->dpi_range.max = %f\n", 2133141cc406Sopenharmony_ci SANE_UNFIX (dev->dpi_range.max)); 2134141cc406Sopenharmony_ci 2135141cc406Sopenharmony_ci ++num_devices; 2136141cc406Sopenharmony_ci dev->next = first_dev; 2137141cc406Sopenharmony_ci first_dev = dev; 2138141cc406Sopenharmony_ci 2139141cc406Sopenharmony_ci if (devp) 2140141cc406Sopenharmony_ci { 2141141cc406Sopenharmony_ci *devp = dev; 2142141cc406Sopenharmony_ci } 2143141cc406Sopenharmony_ci 2144141cc406Sopenharmony_ci DBG (10, "attach_scanner done\n"); 2145141cc406Sopenharmony_ci 2146141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2147141cc406Sopenharmony_ci} 2148141cc406Sopenharmony_ci 2149141cc406Sopenharmony_cistatic SANE_Status 2150141cc406Sopenharmony_ciattach_one (const char *devName) 2151141cc406Sopenharmony_ci{ 2152141cc406Sopenharmony_ci return attach_scanner(devName, 0); 2153141cc406Sopenharmony_ci} 2154141cc406Sopenharmony_ci 2155141cc406Sopenharmony_cistatic void 2156141cc406Sopenharmony_cisigterm_handler (int signal) 2157141cc406Sopenharmony_ci{ 2158141cc406Sopenharmony_ci (void) signal; 2159141cc406Sopenharmony_ci sanei_scsi_req_flush_all (); /* flush SCSI queue */ 2160141cc406Sopenharmony_ci _exit (SANE_STATUS_GOOD); 2161141cc406Sopenharmony_ci} 2162141cc406Sopenharmony_ci 2163141cc406Sopenharmony_ci 2164141cc406Sopenharmony_citypedef struct Color_correct_s 2165141cc406Sopenharmony_ci{ int sum; /* number of pixels summed so far */ 2166141cc406Sopenharmony_ci double sumr; /* sum of red pixel values*/ 2167141cc406Sopenharmony_ci double sumi; /* sum of infrared pixel values*/ 2168141cc406Sopenharmony_ci double sumri; /* sum of red*ired pixel values*/ 2169141cc406Sopenharmony_ci double sumii; /* sum of ired*ired pixel values*/ 2170141cc406Sopenharmony_ci double sumrr; /* sum of ired*ired pixel values*/ 2171141cc406Sopenharmony_ci int mr; /* factor between red and ired values (*256) */ 2172141cc406Sopenharmony_ci int br; /* offset of ired values */ 2173141cc406Sopenharmony_ci} ColorCorrect; 2174141cc406Sopenharmony_ci 2175141cc406Sopenharmony_ci/* --------------------------------------------------------------- 2176141cc406Sopenharmony_ci 2177141cc406Sopenharmony_ci function: RGBIfix 2178141cc406Sopenharmony_ci 2179141cc406Sopenharmony_ci task: Correct the infrared channel 2180141cc406Sopenharmony_ci 2181141cc406Sopenharmony_ci import: unsigned char * rgbimat - RGBI - matrix from scanner 2182141cc406Sopenharmony_ci int size - number of pixels to correct 2183141cc406Sopenharmony_ci int *lutr - lookup table for red correction 2184141cc406Sopenharmony_ci int *lutg - lookup table for red correction 2185141cc406Sopenharmony_ci int *lutb - lookup table for red correction 2186141cc406Sopenharmony_ci int *lutr - lookup table for red correction 2187141cc406Sopenharmony_ci 2188141cc406Sopenharmony_ci export: unsigned char * orgbimat - RGBI - corrected matrix 2189141cc406Sopenharmony_ci 2190141cc406Sopenharmony_ci written by: Andreas RICK 19.6.1999 2191141cc406Sopenharmony_ci 2192141cc406Sopenharmony_ci ----------------------------------------------------------------*/ 2193141cc406Sopenharmony_ci 2194141cc406Sopenharmony_cistatic int Calc_fix_LUT(Coolscan_t * s) 2195141cc406Sopenharmony_ci{ int uselutr,uselutg,uselutb,useluti; 2196141cc406Sopenharmony_ci/* static int irmulr= -34*25; */ 2197141cc406Sopenharmony_ci int irmulr= -64*25; 2198141cc406Sopenharmony_ci int irmulg= -1*25; 2199141cc406Sopenharmony_ci int irmulb= -0*25; 2200141cc406Sopenharmony_ci int irmuli= 256*25; 2201141cc406Sopenharmony_ci int div; 2202141cc406Sopenharmony_ci int i; 2203141cc406Sopenharmony_ci 2204141cc406Sopenharmony_ci irmulr=s->ired_red*(25); 2205141cc406Sopenharmony_ci irmulg=s->ired_green*(25); 2206141cc406Sopenharmony_ci irmulb=s->ired_blue*(25); 2207141cc406Sopenharmony_ci irmuli=25*256; 2208141cc406Sopenharmony_ci 2209141cc406Sopenharmony_ci if(s->LS==2) /* TODO: right conversion factors for 10 and 12 bit */ 2210141cc406Sopenharmony_ci { div=4; 2211141cc406Sopenharmony_ci } 2212141cc406Sopenharmony_ci else if(s->LS==3) 2213141cc406Sopenharmony_ci { div=16; 2214141cc406Sopenharmony_ci } 2215141cc406Sopenharmony_ci else 2216141cc406Sopenharmony_ci { return 0; 2217141cc406Sopenharmony_ci } 2218141cc406Sopenharmony_ci 2219141cc406Sopenharmony_ci memset(s->lutr, 0,256*4); 2220141cc406Sopenharmony_ci memset(s->lutg, 0,256*4); 2221141cc406Sopenharmony_ci memset(s->lutb, 0,256*4); 2222141cc406Sopenharmony_ci memset(s->luti, 0,256*4); 2223141cc406Sopenharmony_ci 2224141cc406Sopenharmony_ci for(i=0;i<s->lutlength;i++) 2225141cc406Sopenharmony_ci { if(s->gamma_bind) 2226141cc406Sopenharmony_ci { uselutr=uselutg=uselutb=useluti=s->gamma[i]/div; 2227141cc406Sopenharmony_ci } 2228141cc406Sopenharmony_ci else 2229141cc406Sopenharmony_ci { uselutr=s->gamma_r[i]/div; 2230141cc406Sopenharmony_ci uselutg=s->gamma_g[i]/div; 2231141cc406Sopenharmony_ci uselutb=s->gamma_b[i]/div; 2232141cc406Sopenharmony_ci useluti=s->gamma_r[i]/div; 2233141cc406Sopenharmony_ci } 2234141cc406Sopenharmony_ci s->lutr[uselutr]=(int)(irmulr*pow((double)i,(double)0.333333)); 2235141cc406Sopenharmony_ci s->lutg[uselutg]=(int)(irmulg*pow((double)i,(double)0.333333)); 2236141cc406Sopenharmony_ci s->lutb[uselutb]=(int)(irmulb*pow((double)i,(double)0.333333)); 2237141cc406Sopenharmony_ci s->luti[useluti]=(int)(irmuli*pow((double)i,(double)0.333333)); 2238141cc406Sopenharmony_ci if(uselutr<255) 2239141cc406Sopenharmony_ci { if(s->lutr[uselutr+1]==0) s->lutr[uselutr+1]=s->lutr[uselutr]; 2240141cc406Sopenharmony_ci } 2241141cc406Sopenharmony_ci if(uselutg<255) 2242141cc406Sopenharmony_ci { if(s->lutg[uselutg+1]==0) s->lutg[uselutg+1]=s->lutg[uselutg]; 2243141cc406Sopenharmony_ci } 2244141cc406Sopenharmony_ci if(uselutb<255) 2245141cc406Sopenharmony_ci { if(s->lutb[uselutb+1]==0) s->lutb[uselutb+1]=s->lutb[uselutb]; 2246141cc406Sopenharmony_ci } 2247141cc406Sopenharmony_ci if(useluti<255) 2248141cc406Sopenharmony_ci { if(s->luti[useluti+1]==0) s->luti[useluti+1]=s->luti[useluti]; 2249141cc406Sopenharmony_ci } 2250141cc406Sopenharmony_ci } 2251141cc406Sopenharmony_ci /* DEBUG 2252141cc406Sopenharmony_ci for(i=0;i<255;i++) 2253141cc406Sopenharmony_ci { fprintf(stderr,"%d %d %d %d\n" 2254141cc406Sopenharmony_ci ,s->lutr[i],s->lutg[i],s->lutb[i],s->luti[i]); 2255141cc406Sopenharmony_ci } 2256141cc406Sopenharmony_ci */ 2257141cc406Sopenharmony_ci return 1; 2258141cc406Sopenharmony_ci} 2259141cc406Sopenharmony_ci 2260141cc406Sopenharmony_ci 2261141cc406Sopenharmony_ci 2262141cc406Sopenharmony_ci/* --------------------------------------------------------------- 2263141cc406Sopenharmony_ci 2264141cc406Sopenharmony_ci function: RGBIfix 2265141cc406Sopenharmony_ci 2266141cc406Sopenharmony_ci task: Correct the infrared channel 2267141cc406Sopenharmony_ci 2268141cc406Sopenharmony_ci import: unsigned char * rgbimat - RGBI - matrix from scanner 2269141cc406Sopenharmony_ci int size - number of pixels to correct 2270141cc406Sopenharmony_ci int *lutr - lookup table for red correction 2271141cc406Sopenharmony_ci int *lutg - lookup table for red correction 2272141cc406Sopenharmony_ci int *lutb - lookup table for red correction 2273141cc406Sopenharmony_ci int *lutr - lookup table for red correction 2274141cc406Sopenharmony_ci 2275141cc406Sopenharmony_ci export: unsigned char * orgbimat - RGBI - corrected matrix 2276141cc406Sopenharmony_ci 2277141cc406Sopenharmony_ci written by: Andreas RICK 19.6.1999 2278141cc406Sopenharmony_ci 2279141cc406Sopenharmony_ci ----------------------------------------------------------------*/ 2280141cc406Sopenharmony_ci 2281141cc406Sopenharmony_cistatic int RGBIfix(Coolscan_t * scanner, 2282141cc406Sopenharmony_ci unsigned char* rgbimat, 2283141cc406Sopenharmony_ci unsigned char* orgbimat, 2284141cc406Sopenharmony_ci int size, 2285141cc406Sopenharmony_ci int *lutr, 2286141cc406Sopenharmony_ci int *lutg, 2287141cc406Sopenharmony_ci int *lutb, 2288141cc406Sopenharmony_ci int *luti) 2289141cc406Sopenharmony_ci 2290141cc406Sopenharmony_ci{ 2291141cc406Sopenharmony_ci unsigned char *pr,*pg,*pb,*pi; 2292141cc406Sopenharmony_ci unsigned char *opr,*opg,*opb,*opi; 2293141cc406Sopenharmony_ci 2294141cc406Sopenharmony_ci int r,g,b,i; 2295141cc406Sopenharmony_ci int ii; 2296141cc406Sopenharmony_ci int x; 2297141cc406Sopenharmony_ci for(x=0;x<size;x++) 2298141cc406Sopenharmony_ci { 2299141cc406Sopenharmony_ci pr=rgbimat+x*4; 2300141cc406Sopenharmony_ci pg=pr+1; 2301141cc406Sopenharmony_ci pb=pg+1; 2302141cc406Sopenharmony_ci pi=pb+1; 2303141cc406Sopenharmony_ci opr=orgbimat+x*4; 2304141cc406Sopenharmony_ci opg=opr+1; 2305141cc406Sopenharmony_ci opb=opg+1; 2306141cc406Sopenharmony_ci opi=opb+1; 2307141cc406Sopenharmony_ci r=lutr[(*pr)]; 2308141cc406Sopenharmony_ci g=lutg[(*pg)]; 2309141cc406Sopenharmony_ci b=lutb[(*pb)]; 2310141cc406Sopenharmony_ci i=luti[(*pi)]; 2311141cc406Sopenharmony_ci ii= i-r-g-b; 2312141cc406Sopenharmony_ci (*opr)=(*pr); 2313141cc406Sopenharmony_ci (*opg)=(*pg); 2314141cc406Sopenharmony_ci (*opb)=(*pb); 2315141cc406Sopenharmony_ci if(ii<0)ii=0; 2316141cc406Sopenharmony_ci if(ii>255*256)ii=255*256; 2317141cc406Sopenharmony_ci if(scanner->negative) 2318141cc406Sopenharmony_ci { 2319141cc406Sopenharmony_ci (*opi)=(unsigned char)(255-(ii>>8)); 2320141cc406Sopenharmony_ci } 2321141cc406Sopenharmony_ci else 2322141cc406Sopenharmony_ci { 2323141cc406Sopenharmony_ci (*opi)=(unsigned char)(ii>>8); 2324141cc406Sopenharmony_ci } 2325141cc406Sopenharmony_ci } 2326141cc406Sopenharmony_ci return 1; 2327141cc406Sopenharmony_ci} 2328141cc406Sopenharmony_ci 2329141cc406Sopenharmony_ci/* --------------------------------------------------------------- 2330141cc406Sopenharmony_ci 2331141cc406Sopenharmony_ci function: RGBIfix16 2332141cc406Sopenharmony_ci 2333141cc406Sopenharmony_ci task: Correct the infrared channel for 16 bit images 2334141cc406Sopenharmony_ci (doesn't do anything for now) 2335141cc406Sopenharmony_ci 2336141cc406Sopenharmony_ci import: unsigned char * rgbimat - RGBI - matrix from scanner 2337141cc406Sopenharmony_ci int size - number of pixels to correct 2338141cc406Sopenharmony_ci int *lutr - lookup table for red correction 2339141cc406Sopenharmony_ci int *lutg - lookup table for red correction 2340141cc406Sopenharmony_ci int *lutb - lookup table for red correction 2341141cc406Sopenharmony_ci int *lutr - lookup table for red correction 2342141cc406Sopenharmony_ci 2343141cc406Sopenharmony_ci export: unsigned char * orgbimat - RGBI - corrected matrix 2344141cc406Sopenharmony_ci 2345141cc406Sopenharmony_ci written by: Andreas RICK 19.6.1999 2346141cc406Sopenharmony_ci 2347141cc406Sopenharmony_ci ----------------------------------------------------------------*/ 2348141cc406Sopenharmony_ci 2349141cc406Sopenharmony_cistatic int RGBIfix16(Coolscan_t * scanner, 2350141cc406Sopenharmony_ci unsigned short* rgbimat, 2351141cc406Sopenharmony_ci unsigned short* orgbimat, 2352141cc406Sopenharmony_ci int size, 2353141cc406Sopenharmony_ci int *lutr, 2354141cc406Sopenharmony_ci int *lutg, 2355141cc406Sopenharmony_ci int *lutb, 2356141cc406Sopenharmony_ci int *luti) 2357141cc406Sopenharmony_ci 2358141cc406Sopenharmony_ci{ 2359141cc406Sopenharmony_ci unsigned short *pr,*pg,*pb,*pi; 2360141cc406Sopenharmony_ci unsigned short *opr,*opg,*opb,*opi; 2361141cc406Sopenharmony_ci int x; 2362141cc406Sopenharmony_ci 2363141cc406Sopenharmony_ci (void) scanner; (void) lutr; (void) lutg; (void) lutb; (void) luti; 2364141cc406Sopenharmony_ci 2365141cc406Sopenharmony_ci for(x=0;x<size;x++) 2366141cc406Sopenharmony_ci { 2367141cc406Sopenharmony_ci pr=rgbimat+x*4; 2368141cc406Sopenharmony_ci pg=pr+1; 2369141cc406Sopenharmony_ci pb=pg+1; 2370141cc406Sopenharmony_ci pi=pb+1; 2371141cc406Sopenharmony_ci opr=orgbimat+x*4; 2372141cc406Sopenharmony_ci opg=opr+1; 2373141cc406Sopenharmony_ci opb=opg+1; 2374141cc406Sopenharmony_ci opi=opb+1; 2375141cc406Sopenharmony_ci (*opr)=(((*pr)&0x00ff)<<8)+(((*pr)&0xff00)>>8); 2376141cc406Sopenharmony_ci (*opg)=(((*pg)&0x00ff)<<8)+(((*pg)&0xff00)>>8); 2377141cc406Sopenharmony_ci (*opb)=(((*pb)&0x00ff)<<8)+(((*pb)&0xff00)>>8); 2378141cc406Sopenharmony_ci (*opi)=(((*pi)&0x00ff)<<8)+(((*pi)&0xff00)>>8); 2379141cc406Sopenharmony_ci } 2380141cc406Sopenharmony_ci return 1; 2381141cc406Sopenharmony_ci} 2382141cc406Sopenharmony_ci 2383141cc406Sopenharmony_ci 2384141cc406Sopenharmony_ci/* --------------------------------------------------------------- 2385141cc406Sopenharmony_ci 2386141cc406Sopenharmony_ci function: rgb2g 2387141cc406Sopenharmony_ci 2388141cc406Sopenharmony_ci task: Convert RGB data to grey 2389141cc406Sopenharmony_ci 2390141cc406Sopenharmony_ci import: unsigned char * rgbimat - RGB - matrix from scanner 2391141cc406Sopenharmony_ci int size - size of input data (num pixel) 2392141cc406Sopenharmony_ci 2393141cc406Sopenharmony_ci export: unsigned char * gomat - Grey matrix 2394141cc406Sopenharmony_ci 2395141cc406Sopenharmony_ci written by: Andreas RICK 13.7.1999 2396141cc406Sopenharmony_ci 2397141cc406Sopenharmony_ci ----------------------------------------------------------------*/ 2398141cc406Sopenharmony_ci#define RtoG ((int)(0.27*256)) 2399141cc406Sopenharmony_ci#define GtoG ((int)(0.54*256)) 2400141cc406Sopenharmony_ci#define BtoG ((int)(0.19*256)) 2401141cc406Sopenharmony_ci 2402141cc406Sopenharmony_cistatic int rgb2g(unsigned char* rgbimat,unsigned char* gomat, 2403141cc406Sopenharmony_ci int size) 2404141cc406Sopenharmony_ci 2405141cc406Sopenharmony_ci{ unsigned char *pr,*pg,*pb; 2406141cc406Sopenharmony_ci unsigned char *opg; 2407141cc406Sopenharmony_ci 2408141cc406Sopenharmony_ci int g; 2409141cc406Sopenharmony_ci int x; 2410141cc406Sopenharmony_ci for(x=0;x<size;x++) 2411141cc406Sopenharmony_ci { 2412141cc406Sopenharmony_ci pr=rgbimat+x*3; 2413141cc406Sopenharmony_ci pg=pr+1; 2414141cc406Sopenharmony_ci pb=pg+1; 2415141cc406Sopenharmony_ci opg=gomat+x; 2416141cc406Sopenharmony_ci g= RtoG*(*pr) + GtoG*(*pg) + BtoG*(*pb); 2417141cc406Sopenharmony_ci (*opg)=(unsigned char)(g>>8); 2418141cc406Sopenharmony_ci } 2419141cc406Sopenharmony_ci return 1; 2420141cc406Sopenharmony_ci} 2421141cc406Sopenharmony_ci 2422141cc406Sopenharmony_ci 2423141cc406Sopenharmony_ci/* --------------------------------------------------------------- 2424141cc406Sopenharmony_ci 2425141cc406Sopenharmony_ci function: RGBIfix1 2426141cc406Sopenharmony_ci 2427141cc406Sopenharmony_ci task: Correct the infrared channel. 2428141cc406Sopenharmony_ci The input image data is the output of scanning 2429141cc406Sopenharmony_ci with LUT. To calculate the original values 2430141cc406Sopenharmony_ci the lutr and luti is applied. 2431141cc406Sopenharmony_ci The infrared values is corrected by: 2432141cc406Sopenharmony_ci 2433141cc406Sopenharmony_ci Ir=mr*lutr(r)+luti(i) 2434141cc406Sopenharmony_ci 2435141cc406Sopenharmony_ci import: unsigned char * rgbimat - RGBI - matrix from scanner 2436141cc406Sopenharmony_ci int size - number of pixels to correct 2437141cc406Sopenharmony_ci ColorCorrect *cc, 2438141cc406Sopenharmony_ci int *lutr - lookup table for red correction 2439141cc406Sopenharmony_ci int *luti - lookup table for ired correction 2440141cc406Sopenharmony_ci 2441141cc406Sopenharmony_ci export: unsigned char * orgbimat - RGBI - corrected matrix 2442141cc406Sopenharmony_ci 2443141cc406Sopenharmony_ci written by: Andreas RICK 3.7.1999 2444141cc406Sopenharmony_ci 2445141cc406Sopenharmony_ci ----------------------------------------------------------------*/ 2446141cc406Sopenharmony_ci#if 0 2447141cc406Sopenharmony_cistatic int RGBIfix1(unsigned char* rgbimat,unsigned char* orgbimat, 2448141cc406Sopenharmony_ci int size, 2449141cc406Sopenharmony_ci int *lutr, 2450141cc406Sopenharmony_ci int *lutg, 2451141cc406Sopenharmony_ci int *lutb, 2452141cc406Sopenharmony_ci int *luti) 2453141cc406Sopenharmony_ci 2454141cc406Sopenharmony_ci{ unsigned char *pr,*pg,*pb,*pi; 2455141cc406Sopenharmony_ci unsigned char *opr,*opg,*opb,*opi; 2456141cc406Sopenharmony_ci ColorCorrect cc; 2457141cc406Sopenharmony_ci int r,i; 2458141cc406Sopenharmony_ci static int thresi=100; 2459141cc406Sopenharmony_ci int ii; 2460141cc406Sopenharmony_ci int x; 2461141cc406Sopenharmony_ci 2462141cc406Sopenharmony_ci (void) lutg; (void) lutb; 2463141cc406Sopenharmony_ci 2464141cc406Sopenharmony_ci /* calculate regression between r and ir */ 2465141cc406Sopenharmony_ci cc.sum=0; 2466141cc406Sopenharmony_ci cc.sumr=cc.sumii=cc.sumrr=cc.sumi=cc.sumri=0.0; 2467141cc406Sopenharmony_ci for(x=0;x<size;x++) 2468141cc406Sopenharmony_ci { pr=rgbimat+x*4; 2469141cc406Sopenharmony_ci pi=pr+3; 2470141cc406Sopenharmony_ci r=lutr[(*pr)]; 2471141cc406Sopenharmony_ci i=luti[(*pi)]; 2472141cc406Sopenharmony_ci /* r=(*pr); 2473141cc406Sopenharmony_ci i=(*pi); */ 2474141cc406Sopenharmony_ci if((*pi)>thresi) 2475141cc406Sopenharmony_ci { cc.sum++; 2476141cc406Sopenharmony_ci cc.sumr+=r; 2477141cc406Sopenharmony_ci cc.sumii+=(i*i); 2478141cc406Sopenharmony_ci cc.sumrr+=(r*r); 2479141cc406Sopenharmony_ci cc.sumi+=i; 2480141cc406Sopenharmony_ci cc.sumri+=(i*r); 2481141cc406Sopenharmony_ci } 2482141cc406Sopenharmony_ci } 2483141cc406Sopenharmony_ci if((cc.sumii!=0)&&(cc.sum!=0)) 2484141cc406Sopenharmony_ci { double dn,dz,dm; 2485141cc406Sopenharmony_ci dz=(cc.sumri-cc.sumr*cc.sumi/cc.sum); 2486141cc406Sopenharmony_ci dn=(cc.sumrr-cc.sumr*cc.sumr/cc.sum); 2487141cc406Sopenharmony_ci DBG (2, "Reg:dz:%e dn:%e\n",dz,dn); 2488141cc406Sopenharmony_ci if(dn!=0) 2489141cc406Sopenharmony_ci { dm=(dz/dn); 2490141cc406Sopenharmony_ci cc.mr=(int)(dm*1024); 2491141cc406Sopenharmony_ci } 2492141cc406Sopenharmony_ci else 2493141cc406Sopenharmony_ci { cc.mr=0; 2494141cc406Sopenharmony_ci dm=0; 2495141cc406Sopenharmony_ci } 2496141cc406Sopenharmony_ci cc.br=(int)((cc.sumi-dm*cc.sumr)/cc.sum); 2497141cc406Sopenharmony_ci } 2498141cc406Sopenharmony_ci else 2499141cc406Sopenharmony_ci { cc.mr=0; 2500141cc406Sopenharmony_ci } 2501141cc406Sopenharmony_ci DBG (2, "Regression: size:%d I=%d/1024*R b:%d s:%d sr:%e si:%e sii:%e sri:%e srr:%e\n", 2502141cc406Sopenharmony_ci size,cc.mr,cc.br,cc.sum,cc.sumr,cc.sumi,cc.sumii,cc.sumri,cc.sumrr); 2503141cc406Sopenharmony_ci for(x=0;x<size;x++) 2504141cc406Sopenharmony_ci { 2505141cc406Sopenharmony_ci 2506141cc406Sopenharmony_ci pr=rgbimat+x*4; 2507141cc406Sopenharmony_ci pg=pr+1; 2508141cc406Sopenharmony_ci pb=pg+1; 2509141cc406Sopenharmony_ci pi=pb+1; 2510141cc406Sopenharmony_ci opr=orgbimat+x*4; 2511141cc406Sopenharmony_ci opg=opr+1; 2512141cc406Sopenharmony_ci opb=opg+1; 2513141cc406Sopenharmony_ci opi=opb+1; 2514141cc406Sopenharmony_ci r=lutr[(*pr)]; 2515141cc406Sopenharmony_ci i=luti[(*pi)]; 2516141cc406Sopenharmony_ci /* r=(*pr); 2517141cc406Sopenharmony_ci i=(*pi); */ 2518141cc406Sopenharmony_ci ii= ((i-((r*cc.mr)>>10)-cc.br)>>2) +128; 2519141cc406Sopenharmony_ci (*opr)=(*pr); 2520141cc406Sopenharmony_ci (*opg)=(*pg); 2521141cc406Sopenharmony_ci (*opb)=(*pb); 2522141cc406Sopenharmony_ci if(ii<0) ii=0; 2523141cc406Sopenharmony_ci if(ii>255) ii=255; 2524141cc406Sopenharmony_ci (*opi)=(unsigned char)(ii); 2525141cc406Sopenharmony_ci } 2526141cc406Sopenharmony_ci return 1; 2527141cc406Sopenharmony_ci} 2528141cc406Sopenharmony_ci 2529141cc406Sopenharmony_ci#endif 2530141cc406Sopenharmony_ci/* This function is executed as a child process. */ 2531141cc406Sopenharmony_cistatic int 2532141cc406Sopenharmony_cireader_process (void *data ) 2533141cc406Sopenharmony_ci{ 2534141cc406Sopenharmony_ci int status; 2535141cc406Sopenharmony_ci unsigned int i; 2536141cc406Sopenharmony_ci unsigned char h; 2537141cc406Sopenharmony_ci unsigned int data_left; 2538141cc406Sopenharmony_ci unsigned int data_to_read; 2539141cc406Sopenharmony_ci unsigned int data_to_write; 2540141cc406Sopenharmony_ci FILE *fp; 2541141cc406Sopenharmony_ci sigset_t sigterm_set, ignore_set; 2542141cc406Sopenharmony_ci struct SIGACTION act; 2543141cc406Sopenharmony_ci unsigned int bpl, linesPerBuf, lineOffset; 2544141cc406Sopenharmony_ci unsigned char r_data, g_data, b_data; 2545141cc406Sopenharmony_ci unsigned int j, line; 2546141cc406Sopenharmony_ci Coolscan_t * scanner = (Coolscan_t*)data; 2547141cc406Sopenharmony_ci 2548141cc406Sopenharmony_ci if (sanei_thread_is_forked ()) 2549141cc406Sopenharmony_ci { 2550141cc406Sopenharmony_ci DBG (10, "reader_process started (forked)\n"); 2551141cc406Sopenharmony_ci close (scanner->pipe); 2552141cc406Sopenharmony_ci scanner->pipe = -1; 2553141cc406Sopenharmony_ci 2554141cc406Sopenharmony_ci sigfillset ( &ignore_set ); 2555141cc406Sopenharmony_ci sigdelset ( &ignore_set, SIGTERM ); 2556141cc406Sopenharmony_ci#if defined (__APPLE__) && defined (__MACH__) 2557141cc406Sopenharmony_ci sigdelset ( &ignore_set, SIGUSR2 ); 2558141cc406Sopenharmony_ci#endif 2559141cc406Sopenharmony_ci sigprocmask( SIG_SETMASK, &ignore_set, 0 ); 2560141cc406Sopenharmony_ci 2561141cc406Sopenharmony_ci memset (&act, 0, sizeof (act)); 2562141cc406Sopenharmony_ci sigaction (SIGTERM, &act, 0); 2563141cc406Sopenharmony_ci } 2564141cc406Sopenharmony_ci else 2565141cc406Sopenharmony_ci { 2566141cc406Sopenharmony_ci DBG (10, "reader_process started (as thread)\n"); 2567141cc406Sopenharmony_ci } 2568141cc406Sopenharmony_ci 2569141cc406Sopenharmony_ci sigemptyset (&sigterm_set); 2570141cc406Sopenharmony_ci sigaddset (&sigterm_set, SIGTERM); 2571141cc406Sopenharmony_ci 2572141cc406Sopenharmony_ci fp = fdopen ( scanner->reader_fds, "w"); 2573141cc406Sopenharmony_ci if (!fp) 2574141cc406Sopenharmony_ci { 2575141cc406Sopenharmony_ci DBG (1, "reader_process: couldn't open pipe!\n"); 2576141cc406Sopenharmony_ci return 1; 2577141cc406Sopenharmony_ci } 2578141cc406Sopenharmony_ci 2579141cc406Sopenharmony_ci DBG (10, "reader_process: starting to READ data\n"); 2580141cc406Sopenharmony_ci 2581141cc406Sopenharmony_ci data_left = scan_bytes_per_line (scanner) * 2582141cc406Sopenharmony_ci lines_per_scan (scanner); 2583141cc406Sopenharmony_ci 2584141cc406Sopenharmony_ci /*scanner->row_bufsize = sanei_scsi_max_request_size;*/ 2585141cc406Sopenharmony_ci coolscan_trim_rowbufsize (scanner); /* trim bufsize */ 2586141cc406Sopenharmony_ci 2587141cc406Sopenharmony_ci DBG (10, "reader_process: reading %u bytes in blocks of %u bytes\n", 2588141cc406Sopenharmony_ci data_left, scanner->row_bufsize); 2589141cc406Sopenharmony_ci 2590141cc406Sopenharmony_ci memset (&act, 0, sizeof (act)); 2591141cc406Sopenharmony_ci act.sa_handler = sigterm_handler; 2592141cc406Sopenharmony_ci sigaction (SIGTERM, &act, 0); 2593141cc406Sopenharmony_ci /* wait_scanner(scanner); */ 2594141cc406Sopenharmony_ci do 2595141cc406Sopenharmony_ci { 2596141cc406Sopenharmony_ci data_to_read = (data_left < scanner->row_bufsize) ? 2597141cc406Sopenharmony_ci data_left : scanner->row_bufsize; 2598141cc406Sopenharmony_ci 2599141cc406Sopenharmony_ci data_to_write=data_to_read; 2600141cc406Sopenharmony_ci 2601141cc406Sopenharmony_ci status = coolscan_read_data_block (scanner 2602141cc406Sopenharmony_ci ,R_datatype_imagedata,data_to_read); 2603141cc406Sopenharmony_ci if (status == 0) 2604141cc406Sopenharmony_ci { 2605141cc406Sopenharmony_ci continue; 2606141cc406Sopenharmony_ci } 2607141cc406Sopenharmony_ci if (status == -1) 2608141cc406Sopenharmony_ci { 2609141cc406Sopenharmony_ci DBG (1, "reader_process: unable to get image data from scanner!\n"); 2610141cc406Sopenharmony_ci fclose (fp); 2611141cc406Sopenharmony_ci return (-1); 2612141cc406Sopenharmony_ci } 2613141cc406Sopenharmony_ci 2614141cc406Sopenharmony_ci if (scanner->LS == 1) { /* mirror image for LS-1000 */ 2615141cc406Sopenharmony_ci bpl = scan_bytes_per_line(scanner); 2616141cc406Sopenharmony_ci linesPerBuf = data_to_read / bpl; 2617141cc406Sopenharmony_ci 2618141cc406Sopenharmony_ci for (line = 0, lineOffset = 0; line < linesPerBuf; 2619141cc406Sopenharmony_ci line++, lineOffset += bpl ) { 2620141cc406Sopenharmony_ci 2621141cc406Sopenharmony_ci if (scanner->colormode == RGB) { 2622141cc406Sopenharmony_ci for (j = 0; j < bpl/2 ; j += 3) { 2623141cc406Sopenharmony_ci r_data=scanner->buffer[lineOffset + j]; 2624141cc406Sopenharmony_ci g_data=scanner->buffer[lineOffset + j + 1]; 2625141cc406Sopenharmony_ci b_data=scanner->buffer[lineOffset + j + 2]; 2626141cc406Sopenharmony_ci 2627141cc406Sopenharmony_ci scanner->buffer[lineOffset + j] = 2628141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl -1 - j - 2 ]; 2629141cc406Sopenharmony_ci scanner->buffer[lineOffset + j + 1] = 2630141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl -1 - j - 1 ]; 2631141cc406Sopenharmony_ci scanner->buffer[lineOffset + j + 2] = 2632141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl -1 - j ]; 2633141cc406Sopenharmony_ci 2634141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl -1 - j - 2 ] = r_data; 2635141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl -1 - j - 1] = g_data; 2636141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl -1 - j] = b_data; 2637141cc406Sopenharmony_ci } 2638141cc406Sopenharmony_ci } 2639141cc406Sopenharmony_ci else { 2640141cc406Sopenharmony_ci for (j = 0; j < bpl/2; j++) { 2641141cc406Sopenharmony_ci r_data=scanner->buffer[lineOffset + j]; 2642141cc406Sopenharmony_ci scanner->buffer[lineOffset + j] = 2643141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl - 1 - j]; 2644141cc406Sopenharmony_ci scanner->buffer[lineOffset + bpl - 1 - j] = r_data; 2645141cc406Sopenharmony_ci } 2646141cc406Sopenharmony_ci } 2647141cc406Sopenharmony_ci } 2648141cc406Sopenharmony_ci } 2649141cc406Sopenharmony_ci if(scanner->colormode==RGBI) 2650141cc406Sopenharmony_ci { /* Correct Infrared Channel */ 2651141cc406Sopenharmony_ci if(scanner->bits_per_color>8) 2652141cc406Sopenharmony_ci { 2653141cc406Sopenharmony_ci RGBIfix16(scanner, (unsigned short * ) scanner->buffer, 2654141cc406Sopenharmony_ci (unsigned short * )scanner->obuffer, 2655141cc406Sopenharmony_ci data_to_read/8,scanner->lutr, 2656141cc406Sopenharmony_ci scanner->lutg,scanner->lutb,scanner->luti); 2657141cc406Sopenharmony_ci } 2658141cc406Sopenharmony_ci else 2659141cc406Sopenharmony_ci { 2660141cc406Sopenharmony_ci RGBIfix(scanner,scanner->buffer,scanner->obuffer, 2661141cc406Sopenharmony_ci data_to_read/4,scanner->lutr, 2662141cc406Sopenharmony_ci scanner->lutg,scanner->lutb,scanner->luti); 2663141cc406Sopenharmony_ci } 2664141cc406Sopenharmony_ci } 2665141cc406Sopenharmony_ci else if((scanner->colormode==GREYSCALE)&&(scanner->LS>=2)) 2666141cc406Sopenharmony_ci { /* Convert to Grey */ 2667141cc406Sopenharmony_ci data_to_write/=3; 2668141cc406Sopenharmony_ci rgb2g(scanner->buffer,scanner->obuffer,data_to_write); 2669141cc406Sopenharmony_ci } 2670141cc406Sopenharmony_ci else 2671141cc406Sopenharmony_ci { /* or just copy */ 2672141cc406Sopenharmony_ci memcpy (scanner->obuffer, scanner->buffer,data_to_read); 2673141cc406Sopenharmony_ci } 2674141cc406Sopenharmony_ci if((!scanner->low_byte_first)&&(scanner->bits_per_color>8)) 2675141cc406Sopenharmony_ci { for(i=0;i<data_to_write;i++) /* inverse byteorder */ 2676141cc406Sopenharmony_ci { h=scanner->obuffer[i]; 2677141cc406Sopenharmony_ci scanner->obuffer[i]=scanner->obuffer[i+1]; 2678141cc406Sopenharmony_ci i++; 2679141cc406Sopenharmony_ci scanner->obuffer[i]=h; 2680141cc406Sopenharmony_ci } 2681141cc406Sopenharmony_ci } 2682141cc406Sopenharmony_ci fwrite (scanner->obuffer, 1, data_to_write, fp); 2683141cc406Sopenharmony_ci fflush (fp); 2684141cc406Sopenharmony_ci data_left -= data_to_read; 2685141cc406Sopenharmony_ci DBG (10, "reader_process: buffer of %d bytes read; %d bytes to go\n", 2686141cc406Sopenharmony_ci data_to_read, data_left); 2687141cc406Sopenharmony_ci } 2688141cc406Sopenharmony_ci while (data_left); 2689141cc406Sopenharmony_ci 2690141cc406Sopenharmony_ci fclose (fp); 2691141cc406Sopenharmony_ci 2692141cc406Sopenharmony_ci DBG (10, "reader_process: finished reading data\n"); 2693141cc406Sopenharmony_ci 2694141cc406Sopenharmony_ci return 0; 2695141cc406Sopenharmony_ci} 2696141cc406Sopenharmony_ci 2697141cc406Sopenharmony_cistatic SANE_Status 2698141cc406Sopenharmony_ciinit_options (Coolscan_t * scanner) 2699141cc406Sopenharmony_ci{ 2700141cc406Sopenharmony_ci int i; 2701141cc406Sopenharmony_ci int bit_depths; 2702141cc406Sopenharmony_ci 2703141cc406Sopenharmony_ci DBG (10, "init_options\n"); 2704141cc406Sopenharmony_ci 2705141cc406Sopenharmony_ci memset (scanner->opt, 0, sizeof (scanner->opt)); 2706141cc406Sopenharmony_ci 2707141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 2708141cc406Sopenharmony_ci { 2709141cc406Sopenharmony_ci scanner->opt[i].size = sizeof (SANE_Word); 2710141cc406Sopenharmony_ci scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2711141cc406Sopenharmony_ci } 2712141cc406Sopenharmony_ci 2713141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2714141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2715141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2716141cc406Sopenharmony_ci scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2717141cc406Sopenharmony_ci 2718141cc406Sopenharmony_ci /* "Mode" group: */ 2719141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].title = "Scan Mode"; 2720141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].desc = ""; 2721141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 2722141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].cap = 0; 2723141cc406Sopenharmony_ci scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2724141cc406Sopenharmony_ci 2725141cc406Sopenharmony_ci /* scan mode */ 2726141cc406Sopenharmony_ci scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 2727141cc406Sopenharmony_ci scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 2728141cc406Sopenharmony_ci scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 2729141cc406Sopenharmony_ci scanner->opt[OPT_MODE].type = SANE_TYPE_STRING; 2730141cc406Sopenharmony_ci if(scanner->LS<2) 2731141cc406Sopenharmony_ci { scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list_LS20); 2732141cc406Sopenharmony_ci scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2733141cc406Sopenharmony_ci scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list_LS20; 2734141cc406Sopenharmony_ci } 2735141cc406Sopenharmony_ci else 2736141cc406Sopenharmony_ci { scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list_LS30); 2737141cc406Sopenharmony_ci scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2738141cc406Sopenharmony_ci scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list_LS30; 2739141cc406Sopenharmony_ci } 2740141cc406Sopenharmony_ci 2741141cc406Sopenharmony_ci /* source */ 2742141cc406Sopenharmony_ci source_list[0] = "Slide"; 2743141cc406Sopenharmony_ci source_list[1] = "Automatic Slide Feeder"; 2744141cc406Sopenharmony_ci source_list[2] = NULL; 2745141cc406Sopenharmony_ci if (!scanner->autofeeder) 2746141cc406Sopenharmony_ci { 2747141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].cap = SANE_CAP_INACTIVE; 2748141cc406Sopenharmony_ci } 2749141cc406Sopenharmony_ci 2750141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 2751141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 2752141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 2753141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].type = SANE_TYPE_STRING; 2754141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].size = max_string_size (source_list); 2755141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2756141cc406Sopenharmony_ci scanner->opt[OPT_SOURCE].constraint.string_list = source_list; 2757141cc406Sopenharmony_ci 2758141cc406Sopenharmony_ci /* negative */ 2759141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].name = "type"; 2760141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].title = "Film type"; 2761141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].desc = 2762141cc406Sopenharmony_ci "Select the film type (positive (slide) or negative)"; 2763141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].type = SANE_TYPE_STRING; 2764141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].size = max_string_size (type_list); 2765141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2766141cc406Sopenharmony_ci scanner->opt[OPT_TYPE].constraint.string_list = type_list; 2767141cc406Sopenharmony_ci 2768141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].name = "prescan"; 2769141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].title = "Prescan"; 2770141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].desc = 2771141cc406Sopenharmony_ci "Perform a prescan during preview"; 2772141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].type = SANE_TYPE_BOOL; 2773141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN].unit = SANE_UNIT_NONE; 2774141cc406Sopenharmony_ci 2775141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].name = "prescan now"; 2776141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].title = "Prescan now"; 2777141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].desc = 2778141cc406Sopenharmony_ci "Perform a prescan now"; 2779141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].type = SANE_TYPE_BUTTON; 2780141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].unit = SANE_UNIT_NONE; 2781141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].size = 0; 2782141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2783141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].constraint_type = SANE_CONSTRAINT_NONE; 2784141cc406Sopenharmony_ci scanner->opt[OPT_PRESCAN_NOW].constraint.string_list = 0; 2785141cc406Sopenharmony_ci 2786141cc406Sopenharmony_ci /* bit depth */ 2787141cc406Sopenharmony_ci 2788141cc406Sopenharmony_ci bit_depths=0; 2789141cc406Sopenharmony_ci bit_depth_list[++bit_depths] = 8; 2790141cc406Sopenharmony_ci if (scanner->LS==2) 2791141cc406Sopenharmony_ci { 2792141cc406Sopenharmony_ci bit_depth_list[++bit_depths] = 10; 2793141cc406Sopenharmony_ci } 2794141cc406Sopenharmony_ci if (scanner->LS==3) 2795141cc406Sopenharmony_ci { 2796141cc406Sopenharmony_ci bit_depth_list[++bit_depths] = 12; 2797141cc406Sopenharmony_ci } 2798141cc406Sopenharmony_ci 2799141cc406Sopenharmony_ci bit_depth_list[0] = bit_depths; 2800141cc406Sopenharmony_ci 2801141cc406Sopenharmony_ci scanner->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; 2802141cc406Sopenharmony_ci scanner->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; 2803141cc406Sopenharmony_ci scanner->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; 2804141cc406Sopenharmony_ci scanner->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; 2805141cc406Sopenharmony_ci scanner->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; 2806141cc406Sopenharmony_ci scanner->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2807141cc406Sopenharmony_ci scanner->opt[OPT_BIT_DEPTH].constraint.word_list = bit_depth_list; 2808141cc406Sopenharmony_ci 2809141cc406Sopenharmony_ci /* resolution */ 2810141cc406Sopenharmony_ci scanner->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 2811141cc406Sopenharmony_ci scanner->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 2812141cc406Sopenharmony_ci scanner->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 2813141cc406Sopenharmony_ci scanner->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 2814141cc406Sopenharmony_ci scanner->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 2815141cc406Sopenharmony_ci scanner->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2816141cc406Sopenharmony_ci scanner->opt[OPT_RESOLUTION].constraint.word_list = resolution_list; 2817141cc406Sopenharmony_ci 2818141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RESOLUTION].name = "preview-resolution"; 2819141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RESOLUTION].title = "Preview resolution"; 2820141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 2821141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RESOLUTION].type = SANE_TYPE_INT; 2822141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RESOLUTION].unit = SANE_UNIT_DPI; 2823141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2824141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW_RESOLUTION].constraint.word_list = resolution_list; 2825141cc406Sopenharmony_ci 2826141cc406Sopenharmony_ci /* "Geometry" group: */ 2827141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; 2828141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].desc = ""; 2829141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 2830141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 2831141cc406Sopenharmony_ci scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2832141cc406Sopenharmony_ci 2833141cc406Sopenharmony_ci /* top-left x */ 2834141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 2835141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 2836141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 2837141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 2838141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM; 2839141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 2840141cc406Sopenharmony_ci scanner->opt[OPT_TL_X].constraint.range = &(scanner->x_range); 2841141cc406Sopenharmony_ci 2842141cc406Sopenharmony_ci /* top-left y */ 2843141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 2844141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 2845141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 2846141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 2847141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 2848141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2849141cc406Sopenharmony_ci scanner->opt[OPT_TL_Y].constraint.range = &(scanner->y_range); 2850141cc406Sopenharmony_ci 2851141cc406Sopenharmony_ci /* bottom-right x */ 2852141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 2853141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 2854141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 2855141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 2856141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM; 2857141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 2858141cc406Sopenharmony_ci scanner->opt[OPT_BR_X].constraint.range = &(scanner->x_range); 2859141cc406Sopenharmony_ci 2860141cc406Sopenharmony_ci /* bottom-right y */ 2861141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 2862141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 2863141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 2864141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 2865141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 2866141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2867141cc406Sopenharmony_ci scanner->opt[OPT_BR_Y].constraint.range = &(scanner->y_range); 2868141cc406Sopenharmony_ci 2869141cc406Sopenharmony_ci 2870141cc406Sopenharmony_ci /* ------------------------------ */ 2871141cc406Sopenharmony_ci 2872141cc406Sopenharmony_ci /* "Enhancement" group: */ 2873141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; 2874141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 2875141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 2876141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0; 2877141cc406Sopenharmony_ci scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2878141cc406Sopenharmony_ci 2879141cc406Sopenharmony_ci 2880141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_BIND].name = "gamma-bind"; 2881141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_BIND].title = "Gamma bind"; 2882141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_BIND].desc = 2883141cc406Sopenharmony_ci "Use same gamma correction for all colours"; 2884141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL; 2885141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_BIND].unit = SANE_UNIT_NONE; 2886141cc406Sopenharmony_ci 2887141cc406Sopenharmony_ci 2888141cc406Sopenharmony_ci scanner->opt[OPT_ANALOG_GAMMA].name = "analog_gamma"; 2889141cc406Sopenharmony_ci scanner->opt[OPT_ANALOG_GAMMA].title = "Analog Gamma"; 2890141cc406Sopenharmony_ci scanner->opt[OPT_ANALOG_GAMMA].desc = "Analog Gamma"; 2891141cc406Sopenharmony_ci scanner->opt[OPT_ANALOG_GAMMA].type = SANE_TYPE_BOOL; 2892141cc406Sopenharmony_ci scanner->opt[OPT_ANALOG_GAMMA].unit = SANE_UNIT_NONE; 2893141cc406Sopenharmony_ci if (!scanner->analoggamma) 2894141cc406Sopenharmony_ci { 2895141cc406Sopenharmony_ci scanner->opt[OPT_ANALOG_GAMMA].cap = SANE_CAP_INACTIVE; 2896141cc406Sopenharmony_ci } 2897141cc406Sopenharmony_ci 2898141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].name = "averaging"; 2899141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].title = "Averaging"; 2900141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].desc = "Averaging"; 2901141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].type = SANE_TYPE_BOOL; 2902141cc406Sopenharmony_ci scanner->opt[OPT_AVERAGING].unit = SANE_UNIT_NONE; 2903141cc406Sopenharmony_ci 2904141cc406Sopenharmony_ci 2905141cc406Sopenharmony_ci scanner->opt[OPT_RGB_CONTROL].name = "rgb-control"; 2906141cc406Sopenharmony_ci scanner->opt[OPT_RGB_CONTROL].title = "RGB control"; 2907141cc406Sopenharmony_ci scanner->opt[OPT_RGB_CONTROL].desc = 2908141cc406Sopenharmony_ci "toggles brightness/contrast control over individual colours"; 2909141cc406Sopenharmony_ci scanner->opt[OPT_RGB_CONTROL].type = SANE_TYPE_BOOL; 2910141cc406Sopenharmony_ci scanner->opt[OPT_RGB_CONTROL].unit = SANE_UNIT_NONE; 2911141cc406Sopenharmony_ci if(scanner->LS>=2) 2912141cc406Sopenharmony_ci { scanner->opt[OPT_RGB_CONTROL].cap |= SANE_CAP_INACTIVE; 2913141cc406Sopenharmony_ci } 2914141cc406Sopenharmony_ci 2915141cc406Sopenharmony_ci 2916141cc406Sopenharmony_ci 2917141cc406Sopenharmony_ci /* brightness */ 2918141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 2919141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 2920141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2921141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 2922141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 2923141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2924141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range; 2925141cc406Sopenharmony_ci if(scanner->LS>=2) 2926141cc406Sopenharmony_ci { scanner->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2927141cc406Sopenharmony_ci } 2928141cc406Sopenharmony_ci 2929141cc406Sopenharmony_ci 2930141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].name = "red-brightness"; 2931141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].title = "Red brightness"; 2932141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2933141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].type = SANE_TYPE_INT; 2934141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].unit = SANE_UNIT_NONE; 2935141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2936141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].constraint.range = &brightness_range; 2937141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2938141cc406Sopenharmony_ci 2939141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].name = "green-brightness"; 2940141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].title = "Green brightness"; 2941141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2942141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].type = SANE_TYPE_INT; 2943141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].unit = SANE_UNIT_NONE; 2944141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2945141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].constraint.range = &brightness_range; 2946141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2947141cc406Sopenharmony_ci 2948141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].name = "blue-brightness"; 2949141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].title = "Blue brightness"; 2950141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2951141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].type = SANE_TYPE_INT; 2952141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].unit = SANE_UNIT_NONE; 2953141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 2954141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].constraint.range = &brightness_range; 2955141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2956141cc406Sopenharmony_ci 2957141cc406Sopenharmony_ci /* contrast */ 2958141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 2959141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 2960141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 2961141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].type = SANE_TYPE_INT; 2962141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; 2963141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2964141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].constraint.range = &contrast_range; 2965141cc406Sopenharmony_ci if(scanner->LS>=2) 2966141cc406Sopenharmony_ci { scanner->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 2967141cc406Sopenharmony_ci } 2968141cc406Sopenharmony_ci 2969141cc406Sopenharmony_ci 2970141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].name = "red-contrast"; 2971141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].title = "Red contrast"; 2972141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].desc = SANE_DESC_CONTRAST; 2973141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].type = SANE_TYPE_INT; 2974141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].unit = SANE_UNIT_NONE; 2975141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2976141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].constraint.range = &contrast_range; 2977141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].cap |= SANE_CAP_INACTIVE; 2978141cc406Sopenharmony_ci 2979141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].name = "green-contrast"; 2980141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].title = "Green contrast"; 2981141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].desc = SANE_DESC_CONTRAST; 2982141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].type = SANE_TYPE_INT; 2983141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].unit = SANE_UNIT_NONE; 2984141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2985141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].constraint.range = &contrast_range; 2986141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].cap |= SANE_CAP_INACTIVE; 2987141cc406Sopenharmony_ci 2988141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].name = "blue-contrast"; 2989141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].title = "Blue contrast"; 2990141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].desc = SANE_DESC_CONTRAST; 2991141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].type = SANE_TYPE_INT; 2992141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].unit = SANE_UNIT_NONE; 2993141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 2994141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].constraint.range = &contrast_range; 2995141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].cap |= SANE_CAP_INACTIVE; 2996141cc406Sopenharmony_ci 2997141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].name = "exposure"; 2998141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].title = "Exposure"; 2999141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].desc = ""; 3000141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].type = SANE_TYPE_INT; 3001141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3002141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; 3003141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; 3004141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].constraint.range = &exposure_range; 3005141cc406Sopenharmony_ci 3006141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].name = "red-exposure"; 3007141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].title = "Red exposure"; 3008141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].desc = ""; 3009141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].type = SANE_TYPE_INT; 3010141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3011141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].unit = SANE_UNIT_PERCENT; 3012141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; 3013141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].constraint.range = &exposure_range; 3014141cc406Sopenharmony_ci 3015141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].name = "green-exposure"; 3016141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].title = "Green exposure"; 3017141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].desc = ""; 3018141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].type = SANE_TYPE_INT; 3019141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].unit = SANE_UNIT_PERCENT; 3020141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; 3021141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].constraint.range = &exposure_range; 3022141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3023141cc406Sopenharmony_ci 3024141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].name = "blue-exposure"; 3025141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].title = "Blue exposre"; 3026141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].desc = ""; 3027141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].type = SANE_TYPE_INT; 3028141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].unit = SANE_UNIT_PERCENT; 3029141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; 3030141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].constraint.range = &exposure_range; 3031141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3032141cc406Sopenharmony_ci if(scanner->LS>=2) 3033141cc406Sopenharmony_ci { scanner->opt[OPT_R_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3034141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3035141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3036141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3037141cc406Sopenharmony_ci } 3038141cc406Sopenharmony_ci 3039141cc406Sopenharmony_ci scanner->opt[OPT_R_SHIFT].name = "red-shift"; 3040141cc406Sopenharmony_ci scanner->opt[OPT_R_SHIFT].title = "Red shift"; 3041141cc406Sopenharmony_ci scanner->opt[OPT_R_SHIFT].desc = ""; 3042141cc406Sopenharmony_ci scanner->opt[OPT_R_SHIFT].type = SANE_TYPE_INT; 3043141cc406Sopenharmony_ci scanner->opt[OPT_R_SHIFT].unit = SANE_UNIT_NONE; 3044141cc406Sopenharmony_ci scanner->opt[OPT_R_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE; 3045141cc406Sopenharmony_ci scanner->opt[OPT_R_SHIFT].constraint.range = &shift_range; 3046141cc406Sopenharmony_ci if(scanner->LS>=2) 3047141cc406Sopenharmony_ci { scanner->opt[OPT_R_SHIFT].cap |= SANE_CAP_INACTIVE; 3048141cc406Sopenharmony_ci } 3049141cc406Sopenharmony_ci 3050141cc406Sopenharmony_ci 3051141cc406Sopenharmony_ci scanner->opt[OPT_G_SHIFT].name = "green-shift"; 3052141cc406Sopenharmony_ci scanner->opt[OPT_G_SHIFT].title = "Green shift"; 3053141cc406Sopenharmony_ci scanner->opt[OPT_G_SHIFT].desc = ""; 3054141cc406Sopenharmony_ci scanner->opt[OPT_G_SHIFT].type = SANE_TYPE_INT; 3055141cc406Sopenharmony_ci scanner->opt[OPT_G_SHIFT].unit = SANE_UNIT_NONE; 3056141cc406Sopenharmony_ci scanner->opt[OPT_G_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE; 3057141cc406Sopenharmony_ci scanner->opt[OPT_G_SHIFT].constraint.range = &shift_range; 3058141cc406Sopenharmony_ci if(scanner->LS>=2) 3059141cc406Sopenharmony_ci { scanner->opt[OPT_G_SHIFT].cap |= SANE_CAP_INACTIVE; 3060141cc406Sopenharmony_ci } 3061141cc406Sopenharmony_ci 3062141cc406Sopenharmony_ci 3063141cc406Sopenharmony_ci scanner->opt[OPT_B_SHIFT].name = "blue-shift"; 3064141cc406Sopenharmony_ci scanner->opt[OPT_B_SHIFT].title = "Blue shift"; 3065141cc406Sopenharmony_ci scanner->opt[OPT_B_SHIFT].desc = ""; 3066141cc406Sopenharmony_ci scanner->opt[OPT_B_SHIFT].type = SANE_TYPE_INT; 3067141cc406Sopenharmony_ci scanner->opt[OPT_B_SHIFT].unit = SANE_UNIT_NONE; 3068141cc406Sopenharmony_ci scanner->opt[OPT_B_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE; 3069141cc406Sopenharmony_ci scanner->opt[OPT_B_SHIFT].constraint.range = &shift_range; 3070141cc406Sopenharmony_ci if(scanner->LS>=2) 3071141cc406Sopenharmony_ci { scanner->opt[OPT_B_SHIFT].cap |= SANE_CAP_INACTIVE; 3072141cc406Sopenharmony_ci } 3073141cc406Sopenharmony_ci 3074141cc406Sopenharmony_ci /* R+G+B gamma vector */ 3075141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 3076141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 3077141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 3078141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 3079141cc406Sopenharmony_ci if (scanner->LS == 1) 3080141cc406Sopenharmony_ci { 3081141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].cap = SANE_CAP_INACTIVE; 3082141cc406Sopenharmony_ci } 3083141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 3084141cc406Sopenharmony_ci switch(scanner->LS) 3085141cc406Sopenharmony_ci { case 0: 3086141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_8; 3087141cc406Sopenharmony_ci scanner->lutlength=2048; 3088141cc406Sopenharmony_ci break; 3089141cc406Sopenharmony_ci case 1: 3090141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_9; 3091141cc406Sopenharmony_ci scanner->lutlength=512; 3092141cc406Sopenharmony_ci break; 3093141cc406Sopenharmony_ci case 2: 3094141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_10; 3095141cc406Sopenharmony_ci scanner->lutlength=1024; 3096141cc406Sopenharmony_ci break; 3097141cc406Sopenharmony_ci case 3: 3098141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_12; 3099141cc406Sopenharmony_ci scanner->lutlength=4096; 3100141cc406Sopenharmony_ci break; 3101141cc406Sopenharmony_ci } 3102141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].size = scanner->lutlength * sizeof (SANE_Word); 3103141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 3104141cc406Sopenharmony_ci 3105141cc406Sopenharmony_ci /* red gamma vector */ 3106141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 3107141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 3108141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 3109141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 3110141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 3111141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 3112141cc406Sopenharmony_ci switch(scanner->LS) 3113141cc406Sopenharmony_ci { case 0: 3114141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_8; 3115141cc406Sopenharmony_ci scanner->lutlength=2048; 3116141cc406Sopenharmony_ci break; 3117141cc406Sopenharmony_ci case 1: 3118141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_9; 3119141cc406Sopenharmony_ci scanner->lutlength=512; 3120141cc406Sopenharmony_ci break; 3121141cc406Sopenharmony_ci case 2: 3122141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_10; 3123141cc406Sopenharmony_ci scanner->lutlength=1024; 3124141cc406Sopenharmony_ci break; 3125141cc406Sopenharmony_ci case 3: 3126141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_12; 3127141cc406Sopenharmony_ci scanner->lutlength=4096; 3128141cc406Sopenharmony_ci break; 3129141cc406Sopenharmony_ci } 3130141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].size = scanner->lutlength * sizeof (SANE_Word); 3131141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 3132141cc406Sopenharmony_ci 3133141cc406Sopenharmony_ci /* green gamma vector */ 3134141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 3135141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 3136141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 3137141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 3138141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 3139141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 3140141cc406Sopenharmony_ci switch(scanner->LS) 3141141cc406Sopenharmony_ci { case 0: 3142141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_8; 3143141cc406Sopenharmony_ci scanner->lutlength=2048; 3144141cc406Sopenharmony_ci break; 3145141cc406Sopenharmony_ci case 1: 3146141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_9; 3147141cc406Sopenharmony_ci scanner->lutlength=512; 3148141cc406Sopenharmony_ci break; 3149141cc406Sopenharmony_ci case 2: 3150141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_10; 3151141cc406Sopenharmony_ci scanner->lutlength=1024; 3152141cc406Sopenharmony_ci break; 3153141cc406Sopenharmony_ci case 3: 3154141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_12; 3155141cc406Sopenharmony_ci scanner->lutlength=4096; 3156141cc406Sopenharmony_ci break; 3157141cc406Sopenharmony_ci } 3158141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].size = scanner->lutlength * sizeof (SANE_Word); 3159141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 3160141cc406Sopenharmony_ci 3161141cc406Sopenharmony_ci /* blue gamma vector */ 3162141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 3163141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 3164141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 3165141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 3166141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 3167141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 3168141cc406Sopenharmony_ci switch(scanner->LS) 3169141cc406Sopenharmony_ci { case 0: 3170141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_8; 3171141cc406Sopenharmony_ci scanner->lutlength=2048; 3172141cc406Sopenharmony_ci break; 3173141cc406Sopenharmony_ci case 1: 3174141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_9; 3175141cc406Sopenharmony_ci scanner->lutlength=512; 3176141cc406Sopenharmony_ci break; 3177141cc406Sopenharmony_ci case 2: 3178141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_10; 3179141cc406Sopenharmony_ci scanner->lutlength=1024; 3180141cc406Sopenharmony_ci break; 3181141cc406Sopenharmony_ci case 3: 3182141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_12; 3183141cc406Sopenharmony_ci scanner->lutlength=4096; 3184141cc406Sopenharmony_ci break; 3185141cc406Sopenharmony_ci } 3186141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].size = scanner->lutlength * sizeof (SANE_Word); 3187141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 3188141cc406Sopenharmony_ci 3189141cc406Sopenharmony_ci 3190141cc406Sopenharmony_ci /* ------------------------------ */ 3191141cc406Sopenharmony_ci 3192141cc406Sopenharmony_ci /* "Advanced" group: */ 3193141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced"; 3194141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].desc = ""; 3195141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; 3196141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; 3197141cc406Sopenharmony_ci scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 3198141cc406Sopenharmony_ci 3199141cc406Sopenharmony_ci /* preview */ 3200141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 3201141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 3202141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 3203141cc406Sopenharmony_ci scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 3204141cc406Sopenharmony_ci 3205141cc406Sopenharmony_ci /* Autofocus */ 3206141cc406Sopenharmony_ci scanner->opt[OPT_AUTOFOCUS].name = "Autofocus"; 3207141cc406Sopenharmony_ci scanner->opt[OPT_AUTOFOCUS].title ="Autofocus"; 3208141cc406Sopenharmony_ci scanner->opt[OPT_AUTOFOCUS].desc = "When to do autofocussing"; 3209141cc406Sopenharmony_ci scanner->opt[OPT_AUTOFOCUS].type = SANE_TYPE_STRING; 3210141cc406Sopenharmony_ci scanner->opt[OPT_AUTOFOCUS].size = max_string_size (autofocus_mode_list); 3211141cc406Sopenharmony_ci scanner->opt[OPT_AUTOFOCUS].constraint_type = SANE_CONSTRAINT_STRING_LIST; 3212141cc406Sopenharmony_ci scanner->opt[OPT_AUTOFOCUS].constraint.string_list = autofocus_mode_list; 3213141cc406Sopenharmony_ci 3214141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].name = "IRED cor. red"; 3215141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].title ="IRED cor. red"; 3216141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].desc = "Correction of infrared from red"; 3217141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].type = SANE_TYPE_INT; 3218141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].unit = SANE_UNIT_NONE; 3219141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].constraint_type = SANE_CONSTRAINT_RANGE; 3220141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].constraint.range = &gamma_range_8; 3221141cc406Sopenharmony_ci scanner->opt[OPT_IRED_RED].cap |= SANE_CAP_ADVANCED; 3222141cc406Sopenharmony_ci if(scanner->LS<2) 3223141cc406Sopenharmony_ci { scanner->opt[OPT_IRED_RED].cap |= SANE_CAP_INACTIVE; 3224141cc406Sopenharmony_ci } 3225141cc406Sopenharmony_ci 3226141cc406Sopenharmony_ci 3227141cc406Sopenharmony_ci 3228141cc406Sopenharmony_ci /* scanner->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; */ 3229141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3230141cc406Sopenharmony_ci} 3231141cc406Sopenharmony_ci 3232141cc406Sopenharmony_ci 3233141cc406Sopenharmony_ciSANE_Status 3234141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 3235141cc406Sopenharmony_ci{ 3236141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 3237141cc406Sopenharmony_ci size_t len; 3238141cc406Sopenharmony_ci FILE *fp; 3239141cc406Sopenharmony_ci 3240141cc406Sopenharmony_ci (void) authorize; 3241141cc406Sopenharmony_ci 3242141cc406Sopenharmony_ci DBG_INIT (); 3243141cc406Sopenharmony_ci sanei_thread_init (); 3244141cc406Sopenharmony_ci 3245141cc406Sopenharmony_ci DBG (10, "sane_init\n"); 3246141cc406Sopenharmony_ci if (version_code) 3247141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 3248141cc406Sopenharmony_ci 3249141cc406Sopenharmony_ci fp = sanei_config_open (COOLSCAN_CONFIG_FILE); 3250141cc406Sopenharmony_ci if (!fp) 3251141cc406Sopenharmony_ci { 3252141cc406Sopenharmony_ci attach_scanner ("/dev/scanner", 0); /* no config-file: /dev/scanner */ 3253141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3254141cc406Sopenharmony_ci } 3255141cc406Sopenharmony_ci 3256141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 3257141cc406Sopenharmony_ci { 3258141cc406Sopenharmony_ci if (dev_name[0] == '#') 3259141cc406Sopenharmony_ci continue; /* ignore line comments */ 3260141cc406Sopenharmony_ci len = strlen (dev_name); 3261141cc406Sopenharmony_ci 3262141cc406Sopenharmony_ci if (!len) 3263141cc406Sopenharmony_ci continue; /* ignore empty lines */ 3264141cc406Sopenharmony_ci 3265141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 3266141cc406Sopenharmony_ci /*attach_scanner (dev_name, 0);*/ 3267141cc406Sopenharmony_ci } 3268141cc406Sopenharmony_ci fclose (fp); 3269141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3270141cc406Sopenharmony_ci} 3271141cc406Sopenharmony_ci 3272141cc406Sopenharmony_civoid 3273141cc406Sopenharmony_cisane_exit (void) 3274141cc406Sopenharmony_ci{ 3275141cc406Sopenharmony_ci Coolscan_t *dev, *next; 3276141cc406Sopenharmony_ci 3277141cc406Sopenharmony_ci DBG (10, "sane_exit\n"); 3278141cc406Sopenharmony_ci 3279141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 3280141cc406Sopenharmony_ci { 3281141cc406Sopenharmony_ci next = dev->next; 3282141cc406Sopenharmony_ci free (dev->devicename); 3283141cc406Sopenharmony_ci free (dev->buffer); 3284141cc406Sopenharmony_ci free (dev->obuffer); 3285141cc406Sopenharmony_ci free (dev); 3286141cc406Sopenharmony_ci } 3287141cc406Sopenharmony_ci 3288141cc406Sopenharmony_ci if (devlist) 3289141cc406Sopenharmony_ci free (devlist); 3290141cc406Sopenharmony_ci} 3291141cc406Sopenharmony_ci 3292141cc406Sopenharmony_ci/* ----------------------------- SANE GET DEVICES -------------------------- */ 3293141cc406Sopenharmony_ciSANE_Status 3294141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, 3295141cc406Sopenharmony_ci SANE_Bool local_only) 3296141cc406Sopenharmony_ci{ 3297141cc406Sopenharmony_ci Coolscan_t *dev; 3298141cc406Sopenharmony_ci int i; 3299141cc406Sopenharmony_ci 3300141cc406Sopenharmony_ci (void) local_only; 3301141cc406Sopenharmony_ci 3302141cc406Sopenharmony_ci DBG (10, "sane_get_devices\n"); 3303141cc406Sopenharmony_ci 3304141cc406Sopenharmony_ci if (devlist) 3305141cc406Sopenharmony_ci free (devlist); 3306141cc406Sopenharmony_ci 3307141cc406Sopenharmony_ci devlist = calloc (num_devices + 1, sizeof (devlist[0])); 3308141cc406Sopenharmony_ci if (!devlist) 3309141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3310141cc406Sopenharmony_ci 3311141cc406Sopenharmony_ci i = 0; 3312141cc406Sopenharmony_ci 3313141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 3314141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 3315141cc406Sopenharmony_ci 3316141cc406Sopenharmony_ci devlist[i++] = 0; 3317141cc406Sopenharmony_ci 3318141cc406Sopenharmony_ci *device_list = devlist; 3319141cc406Sopenharmony_ci 3320141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3321141cc406Sopenharmony_ci} 3322141cc406Sopenharmony_ci 3323141cc406Sopenharmony_ciSANE_Status 3324141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 3325141cc406Sopenharmony_ci{ 3326141cc406Sopenharmony_ci Coolscan_t *dev; 3327141cc406Sopenharmony_ci SANE_Status status; 3328141cc406Sopenharmony_ci 3329141cc406Sopenharmony_ci DBG (10, "sane_open\n"); 3330141cc406Sopenharmony_ci 3331141cc406Sopenharmony_ci if (devicename[0]) 3332141cc406Sopenharmony_ci { /* search for devicename */ 3333141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 3334141cc406Sopenharmony_ci { 3335141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 3336141cc406Sopenharmony_ci { 3337141cc406Sopenharmony_ci break; 3338141cc406Sopenharmony_ci } 3339141cc406Sopenharmony_ci } 3340141cc406Sopenharmony_ci 3341141cc406Sopenharmony_ci if (!dev) 3342141cc406Sopenharmony_ci { 3343141cc406Sopenharmony_ci status = attach_scanner (devicename, &dev); 3344141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3345141cc406Sopenharmony_ci { 3346141cc406Sopenharmony_ci return status; 3347141cc406Sopenharmony_ci } 3348141cc406Sopenharmony_ci } 3349141cc406Sopenharmony_ci } 3350141cc406Sopenharmony_ci else 3351141cc406Sopenharmony_ci { 3352141cc406Sopenharmony_ci dev = first_dev; /* empty devicname -> use first device */ 3353141cc406Sopenharmony_ci } 3354141cc406Sopenharmony_ci 3355141cc406Sopenharmony_ci if (!dev) 3356141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3357141cc406Sopenharmony_ci 3358141cc406Sopenharmony_ci dev->sfd = -1; 3359141cc406Sopenharmony_ci dev->pipe = -1; 3360141cc406Sopenharmony_ci dev->scanning = SANE_FALSE; 3361141cc406Sopenharmony_ci 3362141cc406Sopenharmony_ci init_options (dev); 3363141cc406Sopenharmony_ci *handle = dev; 3364141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3365141cc406Sopenharmony_ci} 3366141cc406Sopenharmony_ci 3367141cc406Sopenharmony_civoid 3368141cc406Sopenharmony_cisane_close (SANE_Handle handle) 3369141cc406Sopenharmony_ci{ 3370141cc406Sopenharmony_ci DBG (10, "sane_close\n"); 3371141cc406Sopenharmony_ci if (((Coolscan_t *) handle)->scanning) 3372141cc406Sopenharmony_ci do_cancel (handle); 3373141cc406Sopenharmony_ci} 3374141cc406Sopenharmony_ci 3375141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 3376141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 3377141cc406Sopenharmony_ci{ 3378141cc406Sopenharmony_ci Coolscan_t *scanner = handle; 3379141cc406Sopenharmony_ci 3380141cc406Sopenharmony_ci DBG (10, "sane_get_option_descriptor %d\n", option); 3381141cc406Sopenharmony_ci 3382141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 3383141cc406Sopenharmony_ci return 0; 3384141cc406Sopenharmony_ci return &scanner->opt[option]; 3385141cc406Sopenharmony_ci} 3386141cc406Sopenharmony_ci 3387141cc406Sopenharmony_ci/* 3388141cc406Sopenharmony_ci static void 3389141cc406Sopenharmony_ci worddump(char *comment, SANE_Word * p, int l) 3390141cc406Sopenharmony_ci { 3391141cc406Sopenharmony_ci int i; 3392141cc406Sopenharmony_ci char line[128]; 3393141cc406Sopenharmony_ci char *ptr; 3394141cc406Sopenharmony_ci 3395141cc406Sopenharmony_ci DBG (5, "%s\n", comment); 3396141cc406Sopenharmony_ci ptr = line; 3397141cc406Sopenharmony_ci for (i = 0; i < l; i++, p++) 3398141cc406Sopenharmony_ci { 3399141cc406Sopenharmony_ci if ((i % 8) == 0) 3400141cc406Sopenharmony_ci { 3401141cc406Sopenharmony_ci if (ptr != line) 3402141cc406Sopenharmony_ci { 3403141cc406Sopenharmony_ci *ptr = '\0'; 3404141cc406Sopenharmony_ci DBG (5, "%s\n", line); 3405141cc406Sopenharmony_ci ptr = line; 3406141cc406Sopenharmony_ci } 3407141cc406Sopenharmony_ci sprintf (ptr, "%3.3d:", i); 3408141cc406Sopenharmony_ci ptr += 4; 3409141cc406Sopenharmony_ci } 3410141cc406Sopenharmony_ci sprintf (ptr, " %4.4d", *p); 3411141cc406Sopenharmony_ci ptr += 5; 3412141cc406Sopenharmony_ci } 3413141cc406Sopenharmony_ci *ptr = '\0'; 3414141cc406Sopenharmony_ci DBG (5, "%s\n", line); 3415141cc406Sopenharmony_ci } 3416141cc406Sopenharmony_ci */ 3417141cc406Sopenharmony_ciSANE_Status 3418141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 3419141cc406Sopenharmony_ci SANE_Action action, void *val, 3420141cc406Sopenharmony_ci SANE_Int * info) 3421141cc406Sopenharmony_ci{ 3422141cc406Sopenharmony_ci Coolscan_t *scanner = handle; 3423141cc406Sopenharmony_ci SANE_Status status; 3424141cc406Sopenharmony_ci SANE_Word cap; 3425141cc406Sopenharmony_ci 3426141cc406Sopenharmony_ci if (info) 3427141cc406Sopenharmony_ci *info = 0; 3428141cc406Sopenharmony_ci 3429141cc406Sopenharmony_ci if (scanner->scanning) 3430141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 3431141cc406Sopenharmony_ci 3432141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) 3433141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3434141cc406Sopenharmony_ci 3435141cc406Sopenharmony_ci cap = scanner->opt[option].cap; 3436141cc406Sopenharmony_ci 3437141cc406Sopenharmony_ci 3438141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 3439141cc406Sopenharmony_ci { 3440141cc406Sopenharmony_ci DBG (10, "sane_control_option %d, get value\n", option); 3441141cc406Sopenharmony_ci switch (option) 3442141cc406Sopenharmony_ci { 3443141cc406Sopenharmony_ci /* word options: */ 3444141cc406Sopenharmony_ci case OPT_TL_X: 3445141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tlx)); 3446141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3447141cc406Sopenharmony_ci 3448141cc406Sopenharmony_ci case OPT_TL_Y: 3449141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tly)); 3450141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3451141cc406Sopenharmony_ci 3452141cc406Sopenharmony_ci case OPT_BR_X: 3453141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->brx)); 3454141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3455141cc406Sopenharmony_ci 3456141cc406Sopenharmony_ci case OPT_BR_Y: 3457141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->bry)); 3458141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3459141cc406Sopenharmony_ci 3460141cc406Sopenharmony_ci case OPT_PREVIEW: 3461141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->preview; 3462141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3463141cc406Sopenharmony_ci 3464141cc406Sopenharmony_ci case OPT_AUTOFOCUS: 3465141cc406Sopenharmony_ci switch(scanner->autofocus) 3466141cc406Sopenharmony_ci { case AF_NEVER: strcpy (val,neverStr); 3467141cc406Sopenharmony_ci break; 3468141cc406Sopenharmony_ci case AF_PREVIEW:strcpy (val,previewStr); 3469141cc406Sopenharmony_ci break; 3470141cc406Sopenharmony_ci case AF_SCAN:if(scanner->LS>=2) strcpy (val,scanStr); 3471141cc406Sopenharmony_ci break; 3472141cc406Sopenharmony_ci case AF_PREANDSCAN:if(scanner->LS>=2) strcpy (val,preandscanStr); 3473141cc406Sopenharmony_ci break; 3474141cc406Sopenharmony_ci } 3475141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3476141cc406Sopenharmony_ci 3477141cc406Sopenharmony_ci case OPT_NUM_OPTS: 3478141cc406Sopenharmony_ci *(SANE_Word *) val = NUM_OPTIONS; 3479141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3480141cc406Sopenharmony_ci 3481141cc406Sopenharmony_ci case OPT_RESOLUTION: 3482141cc406Sopenharmony_ci *(SANE_Word *) val = resDivToVal (scanner->x_nres); 3483141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3484141cc406Sopenharmony_ci 3485141cc406Sopenharmony_ci case OPT_PREVIEW_RESOLUTION: 3486141cc406Sopenharmony_ci *(SANE_Word *) val = resDivToVal (scanner->x_p_nres); 3487141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3488141cc406Sopenharmony_ci 3489141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 3490141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->bits_per_color; 3491141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3492141cc406Sopenharmony_ci 3493141cc406Sopenharmony_ci case OPT_CONTRAST: 3494141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->contrast - 128; 3495141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3496141cc406Sopenharmony_ci 3497141cc406Sopenharmony_ci case OPT_R_CONTRAST: 3498141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->contrast_R - 128; 3499141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3500141cc406Sopenharmony_ci 3501141cc406Sopenharmony_ci case OPT_G_CONTRAST: 3502141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->contrast_G - 128; 3503141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3504141cc406Sopenharmony_ci 3505141cc406Sopenharmony_ci case OPT_B_CONTRAST: 3506141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->contrast_B - 128; 3507141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3508141cc406Sopenharmony_ci 3509141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3510141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->brightness - 128; 3511141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3512141cc406Sopenharmony_ci 3513141cc406Sopenharmony_ci case OPT_R_BRIGHTNESS: 3514141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->brightness_R - 128; 3515141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3516141cc406Sopenharmony_ci 3517141cc406Sopenharmony_ci case OPT_G_BRIGHTNESS: 3518141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->brightness_G - 128; 3519141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3520141cc406Sopenharmony_ci 3521141cc406Sopenharmony_ci case OPT_B_BRIGHTNESS: 3522141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->brightness_B - 128; 3523141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3524141cc406Sopenharmony_ci 3525141cc406Sopenharmony_ci case OPT_EXPOSURE: 3526141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->exposure_R * 2; 3527141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3528141cc406Sopenharmony_ci 3529141cc406Sopenharmony_ci case OPT_R_EXPOSURE: 3530141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->exposure_R * 2; 3531141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3532141cc406Sopenharmony_ci 3533141cc406Sopenharmony_ci case OPT_G_EXPOSURE: 3534141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->exposure_G * 2; 3535141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3536141cc406Sopenharmony_ci 3537141cc406Sopenharmony_ci case OPT_B_EXPOSURE: 3538141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->exposure_B * 2; 3539141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3540141cc406Sopenharmony_ci 3541141cc406Sopenharmony_ci case OPT_R_SHIFT: 3542141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->shift_R - 128; 3543141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3544141cc406Sopenharmony_ci 3545141cc406Sopenharmony_ci case OPT_G_SHIFT: 3546141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->shift_G - 128; 3547141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3548141cc406Sopenharmony_ci 3549141cc406Sopenharmony_ci case OPT_B_SHIFT: 3550141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->shift_B - 128; 3551141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3552141cc406Sopenharmony_ci 3553141cc406Sopenharmony_ci 3554141cc406Sopenharmony_ci case OPT_IRED_RED: 3555141cc406Sopenharmony_ci *(SANE_Word *) val = scanner->ired_red; 3556141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3557141cc406Sopenharmony_ci 3558141cc406Sopenharmony_ci /* string options: */ 3559141cc406Sopenharmony_ci case OPT_TYPE: 3560141cc406Sopenharmony_ci strcpy (val, ((scanner->negative) ? negativeStr : positiveStr)); 3561141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3562141cc406Sopenharmony_ci 3563141cc406Sopenharmony_ci case OPT_MODE: 3564141cc406Sopenharmony_ci switch(scanner->colormode) 3565141cc406Sopenharmony_ci { case RGB: strcpy (val,colorStr); 3566141cc406Sopenharmony_ci break; 3567141cc406Sopenharmony_ci case GREYSCALE:strcpy (val,grayStr); 3568141cc406Sopenharmony_ci break; 3569141cc406Sopenharmony_ci case RGBI:if(scanner->LS>=2) strcpy (val,rgbiStr); 3570141cc406Sopenharmony_ci else strcpy (val,colorStr); 3571141cc406Sopenharmony_ci break; 3572141cc406Sopenharmony_ci case IRED:if(scanner->LS>=2) strcpy (val,iredStr); 3573141cc406Sopenharmony_ci else strcpy (val,grayStr); 3574141cc406Sopenharmony_ci break; 3575141cc406Sopenharmony_ci } 3576141cc406Sopenharmony_ci if (info) 3577141cc406Sopenharmony_ci { 3578141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3579141cc406Sopenharmony_ci } 3580141cc406Sopenharmony_ci 3581141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3582141cc406Sopenharmony_ci 3583141cc406Sopenharmony_ci case OPT_PRESCAN: 3584141cc406Sopenharmony_ci *(SANE_Word *) val = (scanner->prescan) ? SANE_TRUE : SANE_FALSE; 3585141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3586141cc406Sopenharmony_ci 3587141cc406Sopenharmony_ci case OPT_PRESCAN_NOW: 3588141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3589141cc406Sopenharmony_ci 3590141cc406Sopenharmony_ci case OPT_RGB_CONTROL: 3591141cc406Sopenharmony_ci *(SANE_Word *) val = (scanner->rgb_control) ? SANE_TRUE : SANE_FALSE; 3592141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3593141cc406Sopenharmony_ci 3594141cc406Sopenharmony_ci case OPT_GAMMA_BIND: 3595141cc406Sopenharmony_ci *(SANE_Word *) val = (scanner->gamma_bind) ? SANE_TRUE : SANE_FALSE; 3596141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3597141cc406Sopenharmony_ci 3598141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA: 3599141cc406Sopenharmony_ci *(SANE_Word *) val = 3600141cc406Sopenharmony_ci (scanner->analog_gamma_r) ? SANE_TRUE : SANE_FALSE; 3601141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3602141cc406Sopenharmony_ci 3603141cc406Sopenharmony_ci case OPT_AVERAGING: 3604141cc406Sopenharmony_ci *(SANE_Word *) val = (scanner->averaging) ? SANE_TRUE : SANE_FALSE; 3605141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3606141cc406Sopenharmony_ci 3607141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 3608141cc406Sopenharmony_ci memcpy (val, scanner->gamma, scanner->opt[option].size); 3609141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3610141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3611141cc406Sopenharmony_ci memcpy (val, scanner->gamma_r, scanner->opt[option].size); 3612141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3613141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3614141cc406Sopenharmony_ci memcpy (val, scanner->gamma_g, scanner->opt[option].size); 3615141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3616141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3617141cc406Sopenharmony_ci memcpy (val, scanner->gamma_b, scanner->opt[option].size); 3618141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3619141cc406Sopenharmony_ci 3620141cc406Sopenharmony_ci case OPT_SOURCE: 3621141cc406Sopenharmony_ci if (strcmp (val, "Automatic Slide Feeder") == 0) 3622141cc406Sopenharmony_ci { 3623141cc406Sopenharmony_ci /* Feed/Discharge/update filename/etc */ 3624141cc406Sopenharmony_ci } 3625141cc406Sopenharmony_ci else 3626141cc406Sopenharmony_ci { 3627141cc406Sopenharmony_ci /* Reset above */ 3628141cc406Sopenharmony_ci } 3629141cc406Sopenharmony_ci if (info) 3630141cc406Sopenharmony_ci { 3631141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3632141cc406Sopenharmony_ci } 3633141cc406Sopenharmony_ci } 3634141cc406Sopenharmony_ci 3635141cc406Sopenharmony_ci } 3636141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 3637141cc406Sopenharmony_ci { 3638141cc406Sopenharmony_ci DBG (10, "sane_control_option %d, set value\n", option); 3639141cc406Sopenharmony_ci 3640141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 3641141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3642141cc406Sopenharmony_ci 3643141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 3644141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3645141cc406Sopenharmony_ci 3646141cc406Sopenharmony_ci status = sanei_constrain_value (scanner->opt + option, val, info); 3647141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3648141cc406Sopenharmony_ci return status; 3649141cc406Sopenharmony_ci 3650141cc406Sopenharmony_ci switch (option) 3651141cc406Sopenharmony_ci { 3652141cc406Sopenharmony_ci case OPT_GAMMA_BIND: 3653141cc406Sopenharmony_ci scanner->gamma_bind = (*(SANE_Word *) val == SANE_TRUE); 3654141cc406Sopenharmony_ci if (scanner->LS != 1) 3655141cc406Sopenharmony_ci { 3656141cc406Sopenharmony_ci if (scanner->gamma_bind) 3657141cc406Sopenharmony_ci { 3658141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 3659141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 3660141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 3661141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 3662141cc406Sopenharmony_ci 3663141cc406Sopenharmony_ci } 3664141cc406Sopenharmony_ci else 3665141cc406Sopenharmony_ci { 3666141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 3667141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 3668141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 3669141cc406Sopenharmony_ci scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 3670141cc406Sopenharmony_ci 3671141cc406Sopenharmony_ci } 3672141cc406Sopenharmony_ci } 3673141cc406Sopenharmony_ci if (info) 3674141cc406Sopenharmony_ci { 3675141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3676141cc406Sopenharmony_ci } 3677141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3678141cc406Sopenharmony_ci 3679141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA: 3680141cc406Sopenharmony_ci scanner->analog_gamma_r = scanner->analog_gamma_g = 3681141cc406Sopenharmony_ci scanner->analog_gamma_b = (*(SANE_Word *) val == SANE_TRUE); 3682141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3683141cc406Sopenharmony_ci 3684141cc406Sopenharmony_ci case OPT_AVERAGING: 3685141cc406Sopenharmony_ci scanner->averaging = (*(SANE_Word *) val == SANE_TRUE); 3686141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3687141cc406Sopenharmony_ci 3688141cc406Sopenharmony_ci case OPT_PRESCAN: 3689141cc406Sopenharmony_ci scanner->prescan = (*(SANE_Word *) val == SANE_TRUE); 3690141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3691141cc406Sopenharmony_ci 3692141cc406Sopenharmony_ci case OPT_PRESCAN_NOW: 3693141cc406Sopenharmony_ci do_prescan_now(scanner); 3694141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3695141cc406Sopenharmony_ci 3696141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 3697141cc406Sopenharmony_ci scanner->bits_per_color=(*(SANE_Word *)val); 3698141cc406Sopenharmony_ci if (info) 3699141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3700141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3701141cc406Sopenharmony_ci 3702141cc406Sopenharmony_ci 3703141cc406Sopenharmony_ci case OPT_RGB_CONTROL: 3704141cc406Sopenharmony_ci scanner->rgb_control = (*(SANE_Word *) val == SANE_TRUE); 3705141cc406Sopenharmony_ci if (scanner->rgb_control) 3706141cc406Sopenharmony_ci { 3707141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 3708141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 3709141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3710141cc406Sopenharmony_ci 3711141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 3712141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 3713141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 3714141cc406Sopenharmony_ci 3715141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 3716141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 3717141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 3718141cc406Sopenharmony_ci 3719141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3720141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3721141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3722141cc406Sopenharmony_ci 3723141cc406Sopenharmony_ci scanner->contrast_R = 128; 3724141cc406Sopenharmony_ci scanner->contrast_G = 128; 3725141cc406Sopenharmony_ci scanner->contrast_B = 128; 3726141cc406Sopenharmony_ci scanner->brightness_R = 128; 3727141cc406Sopenharmony_ci scanner->brightness_G = 128; 3728141cc406Sopenharmony_ci scanner->brightness_B = 128; 3729141cc406Sopenharmony_ci scanner->exposure_R = 50; 3730141cc406Sopenharmony_ci scanner->exposure_G = 50; 3731141cc406Sopenharmony_ci scanner->exposure_B = 50; 3732141cc406Sopenharmony_ci } 3733141cc406Sopenharmony_ci else 3734141cc406Sopenharmony_ci { 3735141cc406Sopenharmony_ci scanner->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 3736141cc406Sopenharmony_ci scanner->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 3737141cc406Sopenharmony_ci scanner->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3738141cc406Sopenharmony_ci 3739141cc406Sopenharmony_ci scanner->contrast = 128; 3740141cc406Sopenharmony_ci scanner->brightness = 128; 3741141cc406Sopenharmony_ci scanner->exposure_R = 50; 3742141cc406Sopenharmony_ci scanner->exposure_G = 50; 3743141cc406Sopenharmony_ci scanner->exposure_B = 50; 3744141cc406Sopenharmony_ci 3745141cc406Sopenharmony_ci scanner->opt[OPT_R_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 3746141cc406Sopenharmony_ci scanner->opt[OPT_G_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 3747141cc406Sopenharmony_ci scanner->opt[OPT_B_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 3748141cc406Sopenharmony_ci 3749141cc406Sopenharmony_ci scanner->opt[OPT_R_CONTRAST].cap |= SANE_CAP_INACTIVE; 3750141cc406Sopenharmony_ci scanner->opt[OPT_G_CONTRAST].cap |= SANE_CAP_INACTIVE; 3751141cc406Sopenharmony_ci scanner->opt[OPT_B_CONTRAST].cap |= SANE_CAP_INACTIVE; 3752141cc406Sopenharmony_ci 3753141cc406Sopenharmony_ci scanner->opt[OPT_R_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3754141cc406Sopenharmony_ci scanner->opt[OPT_G_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3755141cc406Sopenharmony_ci scanner->opt[OPT_B_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3756141cc406Sopenharmony_ci } 3757141cc406Sopenharmony_ci if (info) 3758141cc406Sopenharmony_ci { 3759141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3760141cc406Sopenharmony_ci } 3761141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3762141cc406Sopenharmony_ci 3763141cc406Sopenharmony_ci case OPT_RESOLUTION: 3764141cc406Sopenharmony_ci scanner->y_nres = scanner->x_nres = 3765141cc406Sopenharmony_ci resValToDiv (*(SANE_Word *) val); 3766141cc406Sopenharmony_ci 3767141cc406Sopenharmony_ci if (info) 3768141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3769141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3770141cc406Sopenharmony_ci 3771141cc406Sopenharmony_ci case OPT_PREVIEW_RESOLUTION: 3772141cc406Sopenharmony_ci scanner->y_p_nres = scanner->x_p_nres = 3773141cc406Sopenharmony_ci resValToDiv (*(SANE_Word *) val); 3774141cc406Sopenharmony_ci 3775141cc406Sopenharmony_ci if (info) 3776141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3777141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3778141cc406Sopenharmony_ci 3779141cc406Sopenharmony_ci case OPT_TL_X: 3780141cc406Sopenharmony_ci scanner->tlx = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 3781141cc406Sopenharmony_ci if (info) 3782141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3783141cc406Sopenharmony_ci 3784141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3785141cc406Sopenharmony_ci 3786141cc406Sopenharmony_ci case OPT_TL_Y: 3787141cc406Sopenharmony_ci scanner->tly = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 3788141cc406Sopenharmony_ci if (info) 3789141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3790141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3791141cc406Sopenharmony_ci 3792141cc406Sopenharmony_ci case OPT_BR_X: 3793141cc406Sopenharmony_ci scanner->brx = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 3794141cc406Sopenharmony_ci if (info) 3795141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3796141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3797141cc406Sopenharmony_ci 3798141cc406Sopenharmony_ci case OPT_BR_Y: 3799141cc406Sopenharmony_ci scanner->bry = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 3800141cc406Sopenharmony_ci if (info) 3801141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3802141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3803141cc406Sopenharmony_ci 3804141cc406Sopenharmony_ci case OPT_NUM_OPTS: 3805141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3806141cc406Sopenharmony_ci 3807141cc406Sopenharmony_ci case OPT_PREVIEW: 3808141cc406Sopenharmony_ci scanner->preview = *(SANE_Word *) val; 3809141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3810141cc406Sopenharmony_ci 3811141cc406Sopenharmony_ci case OPT_AUTOFOCUS: 3812141cc406Sopenharmony_ci if(strcmp(val,neverStr)==0) 3813141cc406Sopenharmony_ci { scanner->autofocus=AF_NEVER; 3814141cc406Sopenharmony_ci } 3815141cc406Sopenharmony_ci if(strcmp(val,previewStr)==0) 3816141cc406Sopenharmony_ci { scanner->autofocus=AF_PREVIEW; 3817141cc406Sopenharmony_ci } 3818141cc406Sopenharmony_ci if(strcmp(val,scanStr)==0) 3819141cc406Sopenharmony_ci { scanner->autofocus=AF_SCAN; 3820141cc406Sopenharmony_ci } 3821141cc406Sopenharmony_ci if(strcmp(val,preandscanStr)==0) 3822141cc406Sopenharmony_ci { scanner->autofocus=AF_PREANDSCAN;; 3823141cc406Sopenharmony_ci } 3824141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3825141cc406Sopenharmony_ci 3826141cc406Sopenharmony_ci case OPT_CONTRAST: 3827141cc406Sopenharmony_ci scanner->contrast = *(SANE_Word *) val + 128; 3828141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3829141cc406Sopenharmony_ci case OPT_R_CONTRAST: 3830141cc406Sopenharmony_ci scanner->contrast_R = *(SANE_Word *) val + 128; 3831141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3832141cc406Sopenharmony_ci case OPT_G_CONTRAST: 3833141cc406Sopenharmony_ci scanner->contrast_G = *(SANE_Word *) val + 128; 3834141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3835141cc406Sopenharmony_ci case OPT_B_CONTRAST: 3836141cc406Sopenharmony_ci scanner->contrast_B = *(SANE_Word *) val + 128; 3837141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3838141cc406Sopenharmony_ci 3839141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3840141cc406Sopenharmony_ci scanner->brightness = *(SANE_Word *) val + 128; 3841141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3842141cc406Sopenharmony_ci case OPT_R_BRIGHTNESS: 3843141cc406Sopenharmony_ci scanner->brightness_R = *(SANE_Word *) val + 128; 3844141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3845141cc406Sopenharmony_ci case OPT_G_BRIGHTNESS: 3846141cc406Sopenharmony_ci scanner->brightness_G = *(SANE_Word *) val + 128; 3847141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3848141cc406Sopenharmony_ci case OPT_B_BRIGHTNESS: 3849141cc406Sopenharmony_ci scanner->brightness_B = *(SANE_Word *) val + 128; 3850141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3851141cc406Sopenharmony_ci 3852141cc406Sopenharmony_ci case OPT_EXPOSURE: 3853141cc406Sopenharmony_ci scanner->exposure_R = *(SANE_Word *) val / 2; 3854141cc406Sopenharmony_ci scanner->exposure_G = *(SANE_Word *) val / 2; 3855141cc406Sopenharmony_ci scanner->exposure_B = *(SANE_Word *) val / 2; 3856141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3857141cc406Sopenharmony_ci case OPT_R_EXPOSURE: 3858141cc406Sopenharmony_ci scanner->exposure_R = *(SANE_Word *) val / 2; 3859141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3860141cc406Sopenharmony_ci case OPT_G_EXPOSURE: 3861141cc406Sopenharmony_ci scanner->exposure_G = *(SANE_Word *) val / 2; 3862141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3863141cc406Sopenharmony_ci case OPT_B_EXPOSURE: 3864141cc406Sopenharmony_ci scanner->exposure_B = *(SANE_Word *) val / 2; 3865141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3866141cc406Sopenharmony_ci 3867141cc406Sopenharmony_ci case OPT_R_SHIFT: 3868141cc406Sopenharmony_ci scanner->shift_R = *(SANE_Word *) val + 128; 3869141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3870141cc406Sopenharmony_ci case OPT_G_SHIFT: 3871141cc406Sopenharmony_ci scanner->shift_G = *(SANE_Word *) val + 128; 3872141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3873141cc406Sopenharmony_ci case OPT_B_SHIFT: 3874141cc406Sopenharmony_ci scanner->shift_B = *(SANE_Word *) val + 128; 3875141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3876141cc406Sopenharmony_ci 3877141cc406Sopenharmony_ci case OPT_IRED_RED: 3878141cc406Sopenharmony_ci scanner->ired_red= *(SANE_Word *) val; 3879141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3880141cc406Sopenharmony_ci 3881141cc406Sopenharmony_ci case OPT_SOURCE: 3882141cc406Sopenharmony_ci scanner->asf = (strcmp (val, "Automatic...") == 0); 3883141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3884141cc406Sopenharmony_ci 3885141cc406Sopenharmony_ci case OPT_TYPE: 3886141cc406Sopenharmony_ci scanner->negative = (strcmp (val, negativeStr) == 0); 3887141cc406Sopenharmony_ci if (info) 3888141cc406Sopenharmony_ci { 3889141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3890141cc406Sopenharmony_ci } 3891141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3892141cc406Sopenharmony_ci case OPT_MODE: 3893141cc406Sopenharmony_ci if(strcmp(val,colorStr)==0) 3894141cc406Sopenharmony_ci { scanner->colormode=RGB; 3895141cc406Sopenharmony_ci scanner->colormode_p=RGB; 3896141cc406Sopenharmony_ci } 3897141cc406Sopenharmony_ci if(strcmp(val,grayStr)==0) 3898141cc406Sopenharmony_ci { scanner->colormode=GREYSCALE; 3899141cc406Sopenharmony_ci scanner->colormode_p=GREYSCALE; 3900141cc406Sopenharmony_ci } 3901141cc406Sopenharmony_ci if(strcmp(val,rgbiStr)==0) 3902141cc406Sopenharmony_ci { scanner->colormode=RGBI; 3903141cc406Sopenharmony_ci scanner->colormode_p=RGB; 3904141cc406Sopenharmony_ci } 3905141cc406Sopenharmony_ci if(strcmp(val,iredStr)==0) 3906141cc406Sopenharmony_ci { scanner->colormode=IRED; 3907141cc406Sopenharmony_ci scanner->colormode_p=GREYSCALE; 3908141cc406Sopenharmony_ci } 3909141cc406Sopenharmony_ci if (info) 3910141cc406Sopenharmony_ci { 3911141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 3912141cc406Sopenharmony_ci } 3913141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3914141cc406Sopenharmony_ci 3915141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 3916141cc406Sopenharmony_ci memcpy (scanner->gamma, val, scanner->opt[option].size); 3917141cc406Sopenharmony_ci if(scanner->LS>2) Calc_fix_LUT(scanner); 3918141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3919141cc406Sopenharmony_ci 3920141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3921141cc406Sopenharmony_ci memcpy (scanner->gamma_r, val, scanner->opt[option].size); 3922141cc406Sopenharmony_ci if(scanner->LS>2) Calc_fix_LUT(scanner); 3923141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3924141cc406Sopenharmony_ci 3925141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3926141cc406Sopenharmony_ci memcpy (scanner->gamma_g, val, scanner->opt[option].size); 3927141cc406Sopenharmony_ci if(scanner->LS>2) Calc_fix_LUT(scanner); 3928141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3929141cc406Sopenharmony_ci 3930141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3931141cc406Sopenharmony_ci memcpy (scanner->gamma_b, val, scanner->opt[option].size); 3932141cc406Sopenharmony_ci if(scanner->LS>2) Calc_fix_LUT(scanner); 3933141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3934141cc406Sopenharmony_ci 3935141cc406Sopenharmony_ci } /* switch */ 3936141cc406Sopenharmony_ci } /* else */ 3937141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3938141cc406Sopenharmony_ci} 3939141cc406Sopenharmony_ci 3940141cc406Sopenharmony_ciSANE_Status 3941141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 3942141cc406Sopenharmony_ci{ 3943141cc406Sopenharmony_ci Coolscan_t *scanner = handle; 3944141cc406Sopenharmony_ci 3945141cc406Sopenharmony_ci DBG (10, "sane_get_parameters"); 3946141cc406Sopenharmony_ci switch(scanner->colormode) 3947141cc406Sopenharmony_ci { case RGB: 3948141cc406Sopenharmony_ci params->format = SANE_FRAME_RGB; 3949141cc406Sopenharmony_ci break; 3950141cc406Sopenharmony_ci#ifdef HAS_IRED 3951141cc406Sopenharmony_ci case RGBI: 3952141cc406Sopenharmony_ci params->format = SANE_FRAME_RGBA; 3953141cc406Sopenharmony_ci break; 3954141cc406Sopenharmony_ci#endif /* HAS_RGBI */ 3955141cc406Sopenharmony_ci case GREYSCALE: 3956141cc406Sopenharmony_ci params->format = SANE_FRAME_GRAY; 3957141cc406Sopenharmony_ci break; 3958141cc406Sopenharmony_ci } 3959141cc406Sopenharmony_ci 3960141cc406Sopenharmony_ci params->depth = scanner->bits_per_color>8?16:8; 3961141cc406Sopenharmony_ci params->pixels_per_line = pixels_per_line (scanner); 3962141cc406Sopenharmony_ci params->lines = lines_per_scan (scanner); 3963141cc406Sopenharmony_ci params->bytes_per_line = write_bytes_per_line (scanner); 3964141cc406Sopenharmony_ci params->last_frame = 1; 3965141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3966141cc406Sopenharmony_ci} 3967141cc406Sopenharmony_cistatic int 3968141cc406Sopenharmony_ciswap_res (Coolscan_t * s) 3969141cc406Sopenharmony_ci{ 3970141cc406Sopenharmony_ci if (s->preview) 3971141cc406Sopenharmony_ci { 3972141cc406Sopenharmony_ci /* swap preview/scan resolutions */ 3973141cc406Sopenharmony_ci int xres, yres, cmode; 3974141cc406Sopenharmony_ci xres = s->x_nres; 3975141cc406Sopenharmony_ci yres = s->y_nres; 3976141cc406Sopenharmony_ci s->x_nres = s->x_p_nres; 3977141cc406Sopenharmony_ci s->y_nres = s->y_p_nres; 3978141cc406Sopenharmony_ci 3979141cc406Sopenharmony_ci s->x_p_nres = xres; 3980141cc406Sopenharmony_ci s->y_p_nres = yres; 3981141cc406Sopenharmony_ci cmode=s->colormode; 3982141cc406Sopenharmony_ci s->colormode=s->colormode_p; 3983141cc406Sopenharmony_ci s->colormode_p=cmode; 3984141cc406Sopenharmony_ci } 3985141cc406Sopenharmony_ci return 0; 3986141cc406Sopenharmony_ci} 3987141cc406Sopenharmony_ciSANE_Status 3988141cc406Sopenharmony_cisane_start (SANE_Handle handle) 3989141cc406Sopenharmony_ci{ 3990141cc406Sopenharmony_ci Coolscan_t *scanner = handle; 3991141cc406Sopenharmony_ci int fds[2]; 3992141cc406Sopenharmony_ci 3993141cc406Sopenharmony_ci DBG (10, "sane_start\n"); 3994141cc406Sopenharmony_ci if (scanner->scanning == SANE_TRUE) 3995141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 3996141cc406Sopenharmony_ci 3997141cc406Sopenharmony_ci if (scanner->sfd < 0) 3998141cc406Sopenharmony_ci { /* first call */ 3999141cc406Sopenharmony_ci if (sanei_scsi_open (scanner->sane.name, 4000141cc406Sopenharmony_ci &(scanner->sfd), 4001141cc406Sopenharmony_ci sense_handler, 0) != SANE_STATUS_GOOD) 4002141cc406Sopenharmony_ci { 4003141cc406Sopenharmony_ci DBG (1, "sane_start: open of %s failed:\n", 4004141cc406Sopenharmony_ci scanner->sane.name); 4005141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4006141cc406Sopenharmony_ci } 4007141cc406Sopenharmony_ci } 4008141cc406Sopenharmony_ci scanner->scanning = SANE_TRUE; 4009141cc406Sopenharmony_ci 4010141cc406Sopenharmony_ci 4011141cc406Sopenharmony_ci if (coolscan_check_values (scanner) != 0) 4012141cc406Sopenharmony_ci { /* Verify values */ 4013141cc406Sopenharmony_ci DBG (1, "ERROR: invalid scan-values\n"); 4014141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 4015141cc406Sopenharmony_ci coolscan_give_scanner (scanner); 4016141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 4017141cc406Sopenharmony_ci scanner->sfd = -1; 4018141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4019141cc406Sopenharmony_ci } 4020141cc406Sopenharmony_ci 4021141cc406Sopenharmony_ci if (coolscan_grab_scanner (scanner)) 4022141cc406Sopenharmony_ci { 4023141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 4024141cc406Sopenharmony_ci scanner->sfd = -1; 4025141cc406Sopenharmony_ci DBG (5, "WARNING: unable to reserve scanner: device busy\n"); 4026141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 4027141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 4028141cc406Sopenharmony_ci } 4029141cc406Sopenharmony_ci 4030141cc406Sopenharmony_ci /* hoho, step 2c, -perm */ 4031141cc406Sopenharmony_ci coolscan_object_feed (scanner); 4032141cc406Sopenharmony_ci 4033141cc406Sopenharmony_ci swap_res (scanner); 4034141cc406Sopenharmony_ci if (!scanner->preview) 4035141cc406Sopenharmony_ci { if(scanner->autofocus & 0x02) 4036141cc406Sopenharmony_ci { coolscan_autofocus (scanner); 4037141cc406Sopenharmony_ci } 4038141cc406Sopenharmony_ci } 4039141cc406Sopenharmony_ci else 4040141cc406Sopenharmony_ci { 4041141cc406Sopenharmony_ci if(scanner->autofocus & 0x01) 4042141cc406Sopenharmony_ci { coolscan_autofocus (scanner); 4043141cc406Sopenharmony_ci } 4044141cc406Sopenharmony_ci if (scanner->prescan) { 4045141cc406Sopenharmony_ci prescan (scanner); 4046141cc406Sopenharmony_ci if(scanner->LS<2) 4047141cc406Sopenharmony_ci { get_internal_info(scanner); 4048141cc406Sopenharmony_ci } 4049141cc406Sopenharmony_ci coolscan_get_window_param (scanner,1); 4050141cc406Sopenharmony_ci } 4051141cc406Sopenharmony_ci } 4052141cc406Sopenharmony_ci /*read_LUT(scanner); */ 4053141cc406Sopenharmony_ci if(scanner->LS<2) 4054141cc406Sopenharmony_ci { send_LUT (scanner); 4055141cc406Sopenharmony_ci coolscan_set_window_param (scanner, 0); 4056141cc406Sopenharmony_ci coolscan_get_window_param (scanner,0); 4057141cc406Sopenharmony_ci coolscan_start_scan (scanner); 4058141cc406Sopenharmony_ci } 4059141cc406Sopenharmony_ci else 4060141cc406Sopenharmony_ci { coolscan_set_window_param (scanner, 0); 4061141cc406Sopenharmony_ci send_LUT (scanner); 4062141cc406Sopenharmony_ci Calc_fix_LUT(scanner); 4063141cc406Sopenharmony_ci coolscan_start_scan (scanner); 4064141cc406Sopenharmony_ci wait_scanner (scanner); 4065141cc406Sopenharmony_ci coolscan_get_window_param (scanner,0); 4066141cc406Sopenharmony_ci } 4067141cc406Sopenharmony_ci 4068141cc406Sopenharmony_ci DBG (10, "bytes per line = %d\n", scan_bytes_per_line (scanner)); 4069141cc406Sopenharmony_ci DBG (10, "pixels_per_line = %d\n", pixels_per_line (scanner)); 4070141cc406Sopenharmony_ci DBG (10, "lines = %d\n", lines_per_scan (scanner)); 4071141cc406Sopenharmony_ci DBG (10, "negative = %d\n", scanner->negative); 4072141cc406Sopenharmony_ci DBG (10, "brightness (halftone) = %d\n", scanner->brightness); 4073141cc406Sopenharmony_ci DBG (10, "contrast (halftone) = %d\n", scanner->contrast); 4074141cc406Sopenharmony_ci DBG (10, "fast preview function = %d\n", scanner->preview); 4075141cc406Sopenharmony_ci 4076141cc406Sopenharmony_ci /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */ 4077141cc406Sopenharmony_ci if (pipe (fds) < 0) 4078141cc406Sopenharmony_ci { 4079141cc406Sopenharmony_ci DBG (1, "ERROR: could not create pipe\n"); 4080141cc406Sopenharmony_ci 4081141cc406Sopenharmony_ci swap_res (scanner); 4082141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 4083141cc406Sopenharmony_ci coolscan_give_scanner (scanner); 4084141cc406Sopenharmony_ci sanei_scsi_close (scanner->sfd); 4085141cc406Sopenharmony_ci scanner->sfd = -1; 4086141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4087141cc406Sopenharmony_ci } 4088141cc406Sopenharmony_ci 4089141cc406Sopenharmony_ci scanner->pipe = fds[0]; 4090141cc406Sopenharmony_ci scanner->reader_fds = fds[1]; 4091141cc406Sopenharmony_ci scanner->reader_pid = sanei_thread_begin( reader_process, (void*)scanner ); 4092141cc406Sopenharmony_ci if (!sanei_thread_is_valid (scanner->reader_pid)) 4093141cc406Sopenharmony_ci { 4094141cc406Sopenharmony_ci DBG (1, "sane_start: sanei_thread_begin failed (%s)\n", 4095141cc406Sopenharmony_ci strerror (errno)); 4096141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 4097141cc406Sopenharmony_ci } 4098141cc406Sopenharmony_ci 4099141cc406Sopenharmony_ci if (sanei_thread_is_forked ()) 4100141cc406Sopenharmony_ci { 4101141cc406Sopenharmony_ci close (scanner->reader_fds); 4102141cc406Sopenharmony_ci scanner->reader_fds = -1; 4103141cc406Sopenharmony_ci } 4104141cc406Sopenharmony_ci 4105141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4106141cc406Sopenharmony_ci} 4107141cc406Sopenharmony_ci 4108141cc406Sopenharmony_ci 4109141cc406Sopenharmony_ciSANE_Status 4110141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, 4111141cc406Sopenharmony_ci SANE_Int max_len, SANE_Int * len) 4112141cc406Sopenharmony_ci{ 4113141cc406Sopenharmony_ci Coolscan_t *scanner = handle; 4114141cc406Sopenharmony_ci ssize_t nread; 4115141cc406Sopenharmony_ci 4116141cc406Sopenharmony_ci *len = 0; 4117141cc406Sopenharmony_ci 4118141cc406Sopenharmony_ci nread = read (scanner->pipe, buf, max_len); 4119141cc406Sopenharmony_ci DBG (10, "sane_read: read %ld bytes\n", (long) nread); 4120141cc406Sopenharmony_ci 4121141cc406Sopenharmony_ci if (!(scanner->scanning)) 4122141cc406Sopenharmony_ci { 4123141cc406Sopenharmony_ci return do_cancel (scanner); 4124141cc406Sopenharmony_ci } 4125141cc406Sopenharmony_ci 4126141cc406Sopenharmony_ci if (nread < 0) 4127141cc406Sopenharmony_ci { 4128141cc406Sopenharmony_ci if (errno == EAGAIN) 4129141cc406Sopenharmony_ci { 4130141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4131141cc406Sopenharmony_ci } 4132141cc406Sopenharmony_ci else 4133141cc406Sopenharmony_ci { 4134141cc406Sopenharmony_ci do_cancel (scanner); 4135141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4136141cc406Sopenharmony_ci } 4137141cc406Sopenharmony_ci } 4138141cc406Sopenharmony_ci 4139141cc406Sopenharmony_ci *len = nread; 4140141cc406Sopenharmony_ci 4141141cc406Sopenharmony_ci if (nread == 0) 4142141cc406Sopenharmony_ci return do_eof (scanner); /* close pipe */ 4143141cc406Sopenharmony_ci 4144141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4145141cc406Sopenharmony_ci} 4146141cc406Sopenharmony_ci 4147141cc406Sopenharmony_civoid 4148141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 4149141cc406Sopenharmony_ci{ 4150141cc406Sopenharmony_ci Coolscan_t *s = handle; 4151141cc406Sopenharmony_ci 4152141cc406Sopenharmony_ci if (sanei_thread_is_valid (s->reader_pid)) 4153141cc406Sopenharmony_ci { 4154141cc406Sopenharmony_ci sanei_thread_kill ( s->reader_pid ); 4155141cc406Sopenharmony_ci sanei_thread_waitpid( s->reader_pid, NULL ); 4156141cc406Sopenharmony_ci sanei_thread_invalidate (s->reader_pid); 4157141cc406Sopenharmony_ci } 4158141cc406Sopenharmony_ci swap_res (s); 4159141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 4160141cc406Sopenharmony_ci} 4161141cc406Sopenharmony_ci 4162141cc406Sopenharmony_ci 4163141cc406Sopenharmony_ciSANE_Status 4164141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 4165141cc406Sopenharmony_ci{ 4166141cc406Sopenharmony_ci Coolscan_t *scanner = handle; 4167141cc406Sopenharmony_ci 4168141cc406Sopenharmony_ci DBG (10, "sane_set_io_mode: non_blocking=%d\n", non_blocking); 4169141cc406Sopenharmony_ci 4170141cc406Sopenharmony_ci if (!scanner->scanning) 4171141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4172141cc406Sopenharmony_ci 4173141cc406Sopenharmony_ci if (fcntl (scanner->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) 4174141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4175141cc406Sopenharmony_ci 4176141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4177141cc406Sopenharmony_ci} 4178141cc406Sopenharmony_ci 4179141cc406Sopenharmony_ciSANE_Status 4180141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 4181141cc406Sopenharmony_ci{ 4182141cc406Sopenharmony_ci Coolscan_t *scanner = handle; 4183141cc406Sopenharmony_ci 4184141cc406Sopenharmony_ci DBG (10, "sane_get_select_fd\n"); 4185141cc406Sopenharmony_ci 4186141cc406Sopenharmony_ci if (!scanner->scanning) 4187141cc406Sopenharmony_ci { 4188141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4189141cc406Sopenharmony_ci } 4190141cc406Sopenharmony_ci *fd = scanner->pipe; 4191141cc406Sopenharmony_ci 4192141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4193141cc406Sopenharmony_ci} 4194