1141cc406Sopenharmony_ci/** @file plustek_pp.c 2141cc406Sopenharmony_ci * @brief SANE backend for Plustek parallelport scanner 3141cc406Sopenharmony_ci * 4141cc406Sopenharmony_ci * Based on Kazuhiro Sasayama previous work on 5141cc406Sopenharmony_ci * plustek.[ch] file from the SANE package.<br> 6141cc406Sopenharmony_ci * Original code taken from sane-0.71<br> 7141cc406Sopenharmony_ci * Copyright (C) 1997 Hypercore Software Design, Ltd.<br> 8141cc406Sopenharmony_ci * Also based on the work done by Rick Bronson<br> 9141cc406Sopenharmony_ci * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de><br> 10141cc406Sopenharmony_ci * 11141cc406Sopenharmony_ci * History: 12141cc406Sopenharmony_ci * - 0.01 - initial version, imported from the kernel-module 0.42-11 13141cc406Sopenharmony_ci * - 0.43 - bumped up version to reflect the former module code version 14141cc406Sopenharmony_ci * - 0.44 - bumped up version to reflect the recent changes 15141cc406Sopenharmony_ci * - minor cleanup 16141cc406Sopenharmony_ci *. 17141cc406Sopenharmony_ci * <hr> 18141cc406Sopenharmony_ci * This file is part of the SANE package. 19141cc406Sopenharmony_ci * 20141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 21141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 22141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the 23141cc406Sopenharmony_ci * License, or (at your option) any later version. 24141cc406Sopenharmony_ci * 25141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 26141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 27141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28141cc406Sopenharmony_ci * General Public License for more details. 29141cc406Sopenharmony_ci * 30141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License 31141cc406Sopenharmony_ci * along with this program. If not, see <https://www.gnu.org/licenses/>. 32141cc406Sopenharmony_ci * 33141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for 34141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE. 35141cc406Sopenharmony_ci * 36141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files 37141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the 38141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public 39141cc406Sopenharmony_ci * License. Your use of that executable is in no way restricted on 40141cc406Sopenharmony_ci * account of linking the SANE library code into it. 41141cc406Sopenharmony_ci * 42141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why 43141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public 44141cc406Sopenharmony_ci * License. 45141cc406Sopenharmony_ci * 46141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in 47141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that 48141cc406Sopenharmony_ci * those changes may be distributed with this exception intact. 49141cc406Sopenharmony_ci * 50141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice 51141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications. 52141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice. 53141cc406Sopenharmony_ci * <hr> 54141cc406Sopenharmony_ci */ 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci/** @mainpage 57141cc406Sopenharmony_ci * @verbinclude Plustek-PARPORT.txt 58141cc406Sopenharmony_ci */ 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci#ifdef _AIX 61141cc406Sopenharmony_ci# include "../include/lalloca.h" /* MUST come first for AIX! */ 62141cc406Sopenharmony_ci#endif 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_ci#include "../include/sane/config.h" 65141cc406Sopenharmony_ci#include "../include/lalloca.h" 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci#include <errno.h> 68141cc406Sopenharmony_ci#include <fcntl.h> 69141cc406Sopenharmony_ci#include <limits.h> 70141cc406Sopenharmony_ci#include <signal.h> 71141cc406Sopenharmony_ci#include <stdlib.h> 72141cc406Sopenharmony_ci#include <string.h> 73141cc406Sopenharmony_ci#include <ctype.h> 74141cc406Sopenharmony_ci#include <unistd.h> 75141cc406Sopenharmony_ci#include <time.h> 76141cc406Sopenharmony_ci#include <math.h> 77141cc406Sopenharmony_ci#include <stdint.h> 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci#include <sys/time.h> 80141cc406Sopenharmony_ci#include <sys/types.h> 81141cc406Sopenharmony_ci#include <sys/ioctl.h> 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_ci#include "../include/sane/sane.h" 84141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 85141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci#define BACKEND_VERSION "0.44-1" 88141cc406Sopenharmony_ci#define BACKEND_NAME plustek_pp 89141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 90141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 91141cc406Sopenharmony_ci#include "../include/sane/sanei_thread.h" 92141cc406Sopenharmony_ci#include "../include/sane/sanei_pp.h" 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_ci#define _BACKEND_ENABLED 95141cc406Sopenharmony_ci#define _USER_MODE 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci#include "plustek-pp.h" 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci/*********************** the debug levels ************************************/ 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci#define _DBG_FATAL 0 102141cc406Sopenharmony_ci#define _DBG_ERROR 1 103141cc406Sopenharmony_ci#define _DBG_WARNING 3 104141cc406Sopenharmony_ci#define _DBG_INFO 5 105141cc406Sopenharmony_ci#define _DBG_PROC 7 106141cc406Sopenharmony_ci#define _DBG_SANE_INIT 10 107141cc406Sopenharmony_ci#define _DBG_INFO2 13 108141cc406Sopenharmony_ci#define _DBG_DUMP 20 109141cc406Sopenharmony_ci#define _DBG_READ 25 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci/*****************************************************************************/ 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci/* 114141cc406Sopenharmony_ci * see plustek-share.h 115141cc406Sopenharmony_ci */ 116141cc406Sopenharmony_ciMODELSTR; 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci#ifdef _BACKEND_ENABLED 119141cc406Sopenharmony_ci#ifndef NDEBUG 120141cc406Sopenharmony_ci# define DEBUG 121141cc406Sopenharmony_ci#endif 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci/* I know this is in general no good idea, but it works */ 124141cc406Sopenharmony_ci# include "plustek-pp_io.c" 125141cc406Sopenharmony_ci# include "plustek-pp_dac.c" 126141cc406Sopenharmony_ci# include "plustek-pp_detect.c" 127141cc406Sopenharmony_ci# include "plustek-pp_genericio.c" 128141cc406Sopenharmony_ci# include "plustek-pp_image.c" 129141cc406Sopenharmony_ci# include "plustek-pp_map.c" 130141cc406Sopenharmony_ci# include "plustek-pp_misc.c" 131141cc406Sopenharmony_ci# include "plustek-pp_models.c" 132141cc406Sopenharmony_ci# include "plustek-pp_motor.c" 133141cc406Sopenharmony_ci# include "plustek-pp_p12.c" 134141cc406Sopenharmony_ci# include "plustek-pp_p12ccd.c" 135141cc406Sopenharmony_ci# include "plustek-pp_p48xx.c" 136141cc406Sopenharmony_ci# include "plustek-pp_p9636.c" 137141cc406Sopenharmony_ci# include "plustek-pp_procfs.c" 138141cc406Sopenharmony_ci# include "plustek-pp_scale.c" 139141cc406Sopenharmony_ci# include "plustek-pp_tpa.c" 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci#define _DEFAULT_DEVICE "0x378" 142141cc406Sopenharmony_ci#else 143141cc406Sopenharmony_ci#define _DEFAULT_DEVICE "/dev/pt_drv" 144141cc406Sopenharmony_ci#endif 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci#ifdef _BACKEND_ENABLED 147141cc406Sopenharmony_ci# include "plustek-pp_ptdrv.c" 148141cc406Sopenharmony_ci#endif 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci#include "plustek-pp_wrapper.c" 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_ci/************************** global vars **************************************/ 154141cc406Sopenharmony_ci 155141cc406Sopenharmony_cistatic int num_devices; 156141cc406Sopenharmony_cistatic Plustek_Device *first_dev; 157141cc406Sopenharmony_cistatic Plustek_Scanner *first_handle; 158141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 159141cc406Sopenharmony_cistatic unsigned long tsecs = 0; 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_cistatic ModeParam mode_params[] = 162141cc406Sopenharmony_ci{ 163141cc406Sopenharmony_ci {0, 1, COLOR_BW}, 164141cc406Sopenharmony_ci {0, 1, COLOR_HALFTONE}, 165141cc406Sopenharmony_ci {0, 8, COLOR_256GRAY}, 166141cc406Sopenharmony_ci {1, 8, COLOR_TRUE24}, 167141cc406Sopenharmony_ci {1, 16, COLOR_TRUE32}, 168141cc406Sopenharmony_ci {1, 16, COLOR_TRUE36} 169141cc406Sopenharmony_ci}; 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_cistatic ModeParam mode_9800x_params[] = 172141cc406Sopenharmony_ci{ 173141cc406Sopenharmony_ci {0, 1, COLOR_BW}, 174141cc406Sopenharmony_ci {0, 1, COLOR_HALFTONE}, 175141cc406Sopenharmony_ci {0, 8, COLOR_256GRAY}, 176141cc406Sopenharmony_ci {1, 8, COLOR_TRUE24}, 177141cc406Sopenharmony_ci {1, 16, COLOR_TRUE48} 178141cc406Sopenharmony_ci}; 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] = 181141cc406Sopenharmony_ci{ 182141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 183141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_HALFTONE, 184141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 185141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 186141cc406Sopenharmony_ci NULL 187141cc406Sopenharmony_ci}; 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_cistatic const SANE_String_Const mode_9800x_list[] = 190141cc406Sopenharmony_ci{ 191141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 192141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_HALFTONE, 193141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 194141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 195141cc406Sopenharmony_ci SANE_I18N("Color36"), 196141cc406Sopenharmony_ci NULL 197141cc406Sopenharmony_ci}; 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_cistatic const SANE_String_Const ext_mode_list[] = 200141cc406Sopenharmony_ci{ 201141cc406Sopenharmony_ci SANE_I18N("Normal"), 202141cc406Sopenharmony_ci SANE_I18N("Transparency"), 203141cc406Sopenharmony_ci SANE_I18N("Negative"), 204141cc406Sopenharmony_ci NULL 205141cc406Sopenharmony_ci}; 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list[] = 208141cc406Sopenharmony_ci{ 209141cc406Sopenharmony_ci SANE_I18N("Dithermap 1"), 210141cc406Sopenharmony_ci SANE_I18N("Dithermap 2"), 211141cc406Sopenharmony_ci SANE_I18N("Randomize"), 212141cc406Sopenharmony_ci NULL 213141cc406Sopenharmony_ci}; 214141cc406Sopenharmony_ci 215141cc406Sopenharmony_cistatic const SANE_Range percentage_range = 216141cc406Sopenharmony_ci{ 217141cc406Sopenharmony_ci SANE_FIX(-100), /* minimum */ 218141cc406Sopenharmony_ci SANE_FIX( 100), /* maximum */ 219141cc406Sopenharmony_ci SANE_FIX( 1) /* quantization */ 220141cc406Sopenharmony_ci}; 221141cc406Sopenharmony_ci 222141cc406Sopenharmony_ci/* 223141cc406Sopenharmony_ci * lens info 224141cc406Sopenharmony_ci */ 225141cc406Sopenharmony_cistatic LensInfo lens = {{0,0,0,0,},{0,0,0,0,},{0,0,0,0,},{0,0,0,0,},0,0}; 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci/* authorization stuff */ 228141cc406Sopenharmony_cistatic SANE_Auth_Callback auth = NULL; 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci/****************************** the backend... *******************************/ 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci#define _YN(x) (x?"yes":"no") 233141cc406Sopenharmony_ci 234141cc406Sopenharmony_ci/** 235141cc406Sopenharmony_ci * function to display the configuration options for the current device 236141cc406Sopenharmony_ci * @param cnf - pointer to the configuration structure whose content should be 237141cc406Sopenharmony_ci * displayed 238141cc406Sopenharmony_ci */ 239141cc406Sopenharmony_cistatic void show_cnf( pCnfDef cnf ) 240141cc406Sopenharmony_ci{ 241141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"Device configuration:\n" ); 242141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"device name : >%s<\n", cnf->devName ); 243141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"direct I/O : %s\n", _YN(cnf->adj.direct_io )); 244141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"warmup : %ds\n", cnf->adj.warmup ); 245141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"lampOff : %d\n", cnf->adj.lampOff ); 246141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"lampOffOnEnd : %s\n", _YN(cnf->adj.lampOffOnEnd )); 247141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"model override: %d\n", cnf->adj.mov ); 248141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT,"---------------------\n" ); 249141cc406Sopenharmony_ci} 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci/** open the device specific driver and reset the internal timing stuff 252141cc406Sopenharmony_ci * @param dev - pointer to the device specific structure 253141cc406Sopenharmony_ci * @return the function returns the result of the open call, on success 254141cc406Sopenharmony_ci * of course the handle 255141cc406Sopenharmony_ci */ 256141cc406Sopenharmony_cistatic int drvopen( Plustek_Device *dev ) 257141cc406Sopenharmony_ci{ 258141cc406Sopenharmony_ci int handle; 259141cc406Sopenharmony_ci 260141cc406Sopenharmony_ci DBG( _DBG_INFO, "drvopen()\n" ); 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci handle = dev->open((const char*)dev->name, (void *)dev ); 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci tsecs = 0; 265141cc406Sopenharmony_ci 266141cc406Sopenharmony_ci return handle; 267141cc406Sopenharmony_ci} 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci/** Calls the device specific stop and close functions. 270141cc406Sopenharmony_ci * @param dev - pointer to the device specific structure 271141cc406Sopenharmony_ci * @return The function always returns SANE_STATUS_GOOD 272141cc406Sopenharmony_ci */ 273141cc406Sopenharmony_cistatic SANE_Status drvclose( Plustek_Device *dev ) 274141cc406Sopenharmony_ci{ 275141cc406Sopenharmony_ci short int_cnt; 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci if( dev->fd >= 0 ) { 278141cc406Sopenharmony_ci 279141cc406Sopenharmony_ci DBG( _DBG_INFO, "drvclose()\n" ); 280141cc406Sopenharmony_ci 281141cc406Sopenharmony_ci if( 0 != tsecs ) { 282141cc406Sopenharmony_ci DBG( _DBG_INFO, "TIME END 1: %lus\n", time(NULL)-tsecs); 283141cc406Sopenharmony_ci } 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci /* 286141cc406Sopenharmony_ci * don't check the return values, simply do it and close the driver 287141cc406Sopenharmony_ci */ 288141cc406Sopenharmony_ci int_cnt = 0; 289141cc406Sopenharmony_ci dev->stopScan( dev, &int_cnt ); 290141cc406Sopenharmony_ci dev->close( dev ); 291141cc406Sopenharmony_ci } 292141cc406Sopenharmony_ci dev->fd = -1; 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 295141cc406Sopenharmony_ci} 296141cc406Sopenharmony_ci 297141cc406Sopenharmony_ci/** according to the mode and source we return the corresponding mode list 298141cc406Sopenharmony_ci */ 299141cc406Sopenharmony_cistatic pModeParam getModeList( Plustek_Scanner *scanner ) 300141cc406Sopenharmony_ci{ 301141cc406Sopenharmony_ci pModeParam mp; 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci if((_ASIC_IS_98003 == scanner->hw->caps.AsicID) || 304141cc406Sopenharmony_ci (_ASIC_IS_98001 == scanner->hw->caps.AsicID)) { 305141cc406Sopenharmony_ci mp = mode_9800x_params; 306141cc406Sopenharmony_ci } else { 307141cc406Sopenharmony_ci mp = mode_params; 308141cc406Sopenharmony_ci } 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci /* 311141cc406Sopenharmony_ci * the transparency/negative mode supports only GRAY/COLOR/COLOR32/COLOR48 312141cc406Sopenharmony_ci */ 313141cc406Sopenharmony_ci if( 0 != scanner->val[OPT_EXT_MODE].w ) { 314141cc406Sopenharmony_ci mp = &mp[_TPAModeSupportMin]; 315141cc406Sopenharmony_ci } 316141cc406Sopenharmony_ci 317141cc406Sopenharmony_ci return mp; 318141cc406Sopenharmony_ci} 319141cc406Sopenharmony_ci 320141cc406Sopenharmony_ci/** 321141cc406Sopenharmony_ci */ 322141cc406Sopenharmony_cistatic SANE_Status close_pipe( Plustek_Scanner *scanner ) 323141cc406Sopenharmony_ci{ 324141cc406Sopenharmony_ci if( scanner->r_pipe >= 0 ) { 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci DBG( _DBG_PROC, "close r_pipe\n" ); 327141cc406Sopenharmony_ci close( scanner->r_pipe ); 328141cc406Sopenharmony_ci scanner->r_pipe = -1; 329141cc406Sopenharmony_ci } 330141cc406Sopenharmony_ci if( scanner->w_pipe >= 0 ) { 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci DBG( _DBG_PROC, "close w_pipe\n" ); 333141cc406Sopenharmony_ci close( scanner->w_pipe ); 334141cc406Sopenharmony_ci scanner->w_pipe = -1; 335141cc406Sopenharmony_ci } 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci return SANE_STATUS_EOF; 338141cc406Sopenharmony_ci} 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ci/** 341141cc406Sopenharmony_ci */ 342141cc406Sopenharmony_cistatic void sig_chldhandler( int signo ) 343141cc406Sopenharmony_ci{ 344141cc406Sopenharmony_ci DBG( _DBG_PROC, "Child is down (signal=%d)\n", signo ); 345141cc406Sopenharmony_ci} 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci/** signal handler to kill the child process 348141cc406Sopenharmony_ci */ 349141cc406Sopenharmony_cistatic void reader_process_sigterm_handler( int signo ) 350141cc406Sopenharmony_ci{ 351141cc406Sopenharmony_ci DBG( _DBG_PROC, "reader_process: terminated by signal %d\n", signo ); 352141cc406Sopenharmony_ci _exit( SANE_STATUS_GOOD ); 353141cc406Sopenharmony_ci} 354141cc406Sopenharmony_ci 355141cc406Sopenharmony_cistatic void sigalarm_handler( int signo ) 356141cc406Sopenharmony_ci{ 357141cc406Sopenharmony_ci _VAR_NOT_USED( signo ); 358141cc406Sopenharmony_ci DBG( _DBG_PROC, "ALARM!!!\n" ); 359141cc406Sopenharmony_ci} 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci/** executed as a child process 362141cc406Sopenharmony_ci * read the data from the driver and send them to the parent process 363141cc406Sopenharmony_ci */ 364141cc406Sopenharmony_cistatic int reader_process( void *args ) 365141cc406Sopenharmony_ci{ 366141cc406Sopenharmony_ci int line; 367141cc406Sopenharmony_ci unsigned long status; 368141cc406Sopenharmony_ci unsigned long data_length; 369141cc406Sopenharmony_ci struct SIGACTION act; 370141cc406Sopenharmony_ci sigset_t ignore_set; 371141cc406Sopenharmony_ci Plustek_Scanner *scanner = (Plustek_Scanner *)args; 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci if( sanei_thread_is_forked()) { 374141cc406Sopenharmony_ci DBG( _DBG_PROC, "reader_process started (forked)\n" ); 375141cc406Sopenharmony_ci close( scanner->r_pipe ); 376141cc406Sopenharmony_ci scanner->r_pipe = -1; 377141cc406Sopenharmony_ci } else { 378141cc406Sopenharmony_ci DBG( _DBG_PROC, "reader_process started (as thread)\n" ); 379141cc406Sopenharmony_ci } 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci sigfillset ( &ignore_set ); 382141cc406Sopenharmony_ci sigdelset ( &ignore_set, SIGTERM ); 383141cc406Sopenharmony_ci#if defined (__APPLE__) && defined (__MACH__) 384141cc406Sopenharmony_ci sigdelset ( &ignore_set, SIGUSR2 ); 385141cc406Sopenharmony_ci#endif 386141cc406Sopenharmony_ci sigprocmask( SIG_SETMASK, &ignore_set, 0 ); 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ci memset ( &act, 0, sizeof (act)); 389141cc406Sopenharmony_ci sigaction( SIGTERM, &act, 0 ); 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci /* install the signal handler */ 392141cc406Sopenharmony_ci sigemptyset(&(act.sa_mask)); 393141cc406Sopenharmony_ci act.sa_flags = 0; 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci act.sa_handler = reader_process_sigterm_handler; 396141cc406Sopenharmony_ci sigaction( SIGTERM, &act, 0 ); 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci data_length = scanner->params.lines * scanner->params.bytes_per_line; 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci DBG( _DBG_PROC, "reader_process:" 401141cc406Sopenharmony_ci "starting to READ data (%lu bytes)\n", data_length ); 402141cc406Sopenharmony_ci DBG( _DBG_PROC, "buf = 0x%08lx\n", (unsigned long)scanner->buf ); 403141cc406Sopenharmony_ci 404141cc406Sopenharmony_ci if( NULL == scanner->buf ) { 405141cc406Sopenharmony_ci DBG( _DBG_FATAL, "NULL Pointer !!!!\n" ); 406141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 407141cc406Sopenharmony_ci } 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci /* here we read all data from the driver... */ 410141cc406Sopenharmony_ci if( scanner->hw->readImage ) { 411141cc406Sopenharmony_ci 412141cc406Sopenharmony_ci status = (unsigned long)scanner->hw->readImage( scanner->hw, 413141cc406Sopenharmony_ci scanner->buf, data_length); 414141cc406Sopenharmony_ci } else { 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci unsigned char *buf = scanner->buf; 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci status = scanner->hw->prepare( scanner->hw, buf ); 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci if( 0 == status ) { 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_ci for( line = 0; line < scanner->params.lines; line++ ) { 424141cc406Sopenharmony_ci 425141cc406Sopenharmony_ci status = scanner->hw->readLine( scanner->hw ); 426141cc406Sopenharmony_ci if((int)status < 0 ) { 427141cc406Sopenharmony_ci break; 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci write( scanner->w_pipe, buf, scanner->params.bytes_per_line ); 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_ci buf += scanner->params.bytes_per_line; 433141cc406Sopenharmony_ci } 434141cc406Sopenharmony_ci } 435141cc406Sopenharmony_ci } 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci /* on error, there's no need to clean up, as this is done by the parent */ 438141cc406Sopenharmony_ci if((int)status < 0 ) { 439141cc406Sopenharmony_ci DBG( _DBG_ERROR, "read failed, status = %i, errno %i\n", 440141cc406Sopenharmony_ci (int)status, errno ); 441141cc406Sopenharmony_ci if( -9009 == (int)status ) 442141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 443141cc406Sopenharmony_ci 444141cc406Sopenharmony_ci if( errno == EBUSY ) 445141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 448141cc406Sopenharmony_ci } 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci /* send to parent */ 451141cc406Sopenharmony_ci if( scanner->hw->readImage ) { 452141cc406Sopenharmony_ci DBG( _DBG_PROC, "sending %lu bytes to parent\n", status ); 453141cc406Sopenharmony_ci write( scanner->w_pipe, scanner->buf, status ); 454141cc406Sopenharmony_ci } 455141cc406Sopenharmony_ci 456141cc406Sopenharmony_ci DBG( _DBG_PROC, "reader_process: finished reading data\n" ); 457141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 458141cc406Sopenharmony_ci} 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci/** stop the current scan process 461141cc406Sopenharmony_ci */ 462141cc406Sopenharmony_cistatic SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe ) 463141cc406Sopenharmony_ci{ 464141cc406Sopenharmony_ci struct SIGACTION act; 465141cc406Sopenharmony_ci SANE_Pid res; 466141cc406Sopenharmony_ci short int_cnt; 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci DBG( _DBG_PROC,"do_cancel\n" ); 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci if( sanei_thread_is_valid( scanner->reader_pid )) { 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci DBG( _DBG_PROC, "---- killing reader_process ----\n" ); 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci /* tell the driver to stop scanning */ 477141cc406Sopenharmony_ci if( -1 != scanner->hw->fd ) { 478141cc406Sopenharmony_ci int_cnt = 1; 479141cc406Sopenharmony_ci scanner->hw->stopScan( scanner->hw, &int_cnt ); 480141cc406Sopenharmony_ci } 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci sigemptyset(&(act.sa_mask)); 483141cc406Sopenharmony_ci act.sa_flags = 0; 484141cc406Sopenharmony_ci 485141cc406Sopenharmony_ci act.sa_handler = sigalarm_handler; 486141cc406Sopenharmony_ci sigaction( SIGALRM, &act, 0 ); 487141cc406Sopenharmony_ci 488141cc406Sopenharmony_ci /* kill our child process and wait until done */ 489141cc406Sopenharmony_ci sanei_thread_kill( scanner->reader_pid ); 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_ci /* give'em 10 seconds 'til done...*/ 492141cc406Sopenharmony_ci alarm(10); 493141cc406Sopenharmony_ci res = sanei_thread_waitpid( scanner->reader_pid, 0 ); 494141cc406Sopenharmony_ci alarm(0); 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci if( res != scanner->reader_pid ) { 497141cc406Sopenharmony_ci DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n"); 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci /* do it the hard way...*/ 500141cc406Sopenharmony_ci#ifdef USE_PTHREAD 501141cc406Sopenharmony_ci sanei_thread_kill( scanner->reader_pid ); 502141cc406Sopenharmony_ci#else 503141cc406Sopenharmony_ci sanei_thread_sendsig( scanner->reader_pid, SIGKILL ); 504141cc406Sopenharmony_ci#endif 505141cc406Sopenharmony_ci } 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci sanei_thread_invalidate( scanner->reader_pid ); 508141cc406Sopenharmony_ci DBG( _DBG_PROC,"reader_process killed\n"); 509141cc406Sopenharmony_ci } 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci if( SANE_TRUE == closepipe ) { 512141cc406Sopenharmony_ci close_pipe( scanner ); 513141cc406Sopenharmony_ci } 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci drvclose( scanner->hw ); 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci if( tsecs != 0 ) { 518141cc406Sopenharmony_ci DBG( _DBG_INFO, "TIME END 2: %lus\n", time(NULL)-tsecs); 519141cc406Sopenharmony_ci tsecs = 0; 520141cc406Sopenharmony_ci } 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 523141cc406Sopenharmony_ci} 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci/** because of some internal problems (inside the parport driver), we have to 526141cc406Sopenharmony_ci * limit the max resolution to optical resolution. This is done by this 527141cc406Sopenharmony_ci * function 528141cc406Sopenharmony_ci * @param dev - pointer to the device specific structure 529141cc406Sopenharmony_ci * @return The function always returns SANE_STATUS_GOOD 530141cc406Sopenharmony_ci */ 531141cc406Sopenharmony_cistatic void limitResolution( Plustek_Device *dev ) 532141cc406Sopenharmony_ci{ 533141cc406Sopenharmony_ci dev->dpi_range.min = _DEF_DPI; 534141cc406Sopenharmony_ci if( dev->dpi_range.min < _DEF_DPI ) 535141cc406Sopenharmony_ci dev->dpi_range.min = _DEF_DPI; 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci /* 538141cc406Sopenharmony_ci * CHANGE: limit resolution to max. physical available one 539141cc406Sopenharmony_ci * Note: the resolution for the Asic 96001/3 models is limited to 540141cc406Sopenharmony_ci * the X-Resolution 541141cc406Sopenharmony_ci */ 542141cc406Sopenharmony_ci if((_ASIC_IS_96003 == dev->caps.AsicID) || 543141cc406Sopenharmony_ci (_ASIC_IS_96001 == dev->caps.AsicID)) { 544141cc406Sopenharmony_ci dev->dpi_range.max = lens.rDpiX.wPhyMax; 545141cc406Sopenharmony_ci } else { 546141cc406Sopenharmony_ci dev->dpi_range.max = lens.rDpiY.wPhyMax; 547141cc406Sopenharmony_ci } 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci dev->dpi_range.quant = 0; 550141cc406Sopenharmony_ci dev->x_range.min = 0; 551141cc406Sopenharmony_ci dev->x_range.max = SANE_FIX(dev->max_x); 552141cc406Sopenharmony_ci dev->x_range.quant = 0; 553141cc406Sopenharmony_ci dev->y_range.min = 0; 554141cc406Sopenharmony_ci dev->y_range.max = SANE_FIX(dev->max_y); 555141cc406Sopenharmony_ci dev->y_range.quant = 0; 556141cc406Sopenharmony_ci} 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci/** Currently we support only LM9831/2/3 chips and these use the same 559141cc406Sopenharmony_ci * sizes... 560141cc406Sopenharmony_ci * @param s - pointer to the scanner specific structure 561141cc406Sopenharmony_ci * @return The function always returns SANE_STATUS_GOOD 562141cc406Sopenharmony_ci */ 563141cc406Sopenharmony_cistatic SANE_Status initGammaSettings( Plustek_Scanner *s ) 564141cc406Sopenharmony_ci{ 565141cc406Sopenharmony_ci int i, j, val; 566141cc406Sopenharmony_ci double gamma; 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci /* 569141cc406Sopenharmony_ci * this setting is common to the ASIC98001/3 and 570141cc406Sopenharmony_ci * LM9831/2/3 based devices 571141cc406Sopenharmony_ci * older parallelport devices use 256 entries 572141cc406Sopenharmony_ci */ 573141cc406Sopenharmony_ci s->gamma_length = 4096; 574141cc406Sopenharmony_ci s->gamma_range.min = 0; 575141cc406Sopenharmony_ci s->gamma_range.max = 255; 576141cc406Sopenharmony_ci s->gamma_range.quant = 0; 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_ci if((_ASIC_IS_96003 == s->hw->caps.AsicID) || 579141cc406Sopenharmony_ci (_ASIC_IS_96001 == s->hw->caps.AsicID)) { 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci s->gamma_length = 256; 582141cc406Sopenharmony_ci } 583141cc406Sopenharmony_ci 584141cc406Sopenharmony_ci DBG( _DBG_INFO, "Presetting Gamma tables (len=%u)\n", s->gamma_length ); 585141cc406Sopenharmony_ci DBG( _DBG_INFO, "----------------------------------\n" ); 586141cc406Sopenharmony_ci 587141cc406Sopenharmony_ci /* 588141cc406Sopenharmony_ci * preset the gamma maps 589141cc406Sopenharmony_ci */ 590141cc406Sopenharmony_ci for( i = 0; i < 4; i++ ) { 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_ci switch( i ) { 593141cc406Sopenharmony_ci case 1: gamma = s->hw->adj.rgamma; break; 594141cc406Sopenharmony_ci case 2: gamma = s->hw->adj.ggamma; break; 595141cc406Sopenharmony_ci case 3: gamma = s->hw->adj.bgamma; break; 596141cc406Sopenharmony_ci default: gamma = s->hw->adj.graygamma; break; 597141cc406Sopenharmony_ci } 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci for( j = 0; j < s->gamma_length; j++ ) { 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci val = (s->gamma_range.max * 602141cc406Sopenharmony_ci pow((double) j / ((double)s->gamma_length - 1.0), 603141cc406Sopenharmony_ci 1.0 / gamma )); 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci if( val > s->gamma_range.max ) 606141cc406Sopenharmony_ci val = s->gamma_range.max; 607141cc406Sopenharmony_ci 608141cc406Sopenharmony_ci s->gamma_table[i][j] = val; 609141cc406Sopenharmony_ci } 610141cc406Sopenharmony_ci } 611141cc406Sopenharmony_ci 612141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 613141cc406Sopenharmony_ci} 614141cc406Sopenharmony_ci 615141cc406Sopenharmony_ci/** Check the gamma vectors we got back and limit if necessary 616141cc406Sopenharmony_ci * @param s - pointer to the scanner specific structure 617141cc406Sopenharmony_ci * @return nothing 618141cc406Sopenharmony_ci */ 619141cc406Sopenharmony_cistatic void checkGammaSettings( Plustek_Scanner *s ) 620141cc406Sopenharmony_ci{ 621141cc406Sopenharmony_ci int i, j; 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci for( i = 0; i < 4 ; i++ ) { 624141cc406Sopenharmony_ci for( j = 0; j < s->gamma_length; j++ ) { 625141cc406Sopenharmony_ci if( s->gamma_table[i][j] > s->gamma_range.max ) { 626141cc406Sopenharmony_ci s->gamma_table[i][j] = s->gamma_range.max; 627141cc406Sopenharmony_ci } 628141cc406Sopenharmony_ci } 629141cc406Sopenharmony_ci } 630141cc406Sopenharmony_ci} 631141cc406Sopenharmony_ci 632141cc406Sopenharmony_ci/** initialize the options for the backend according to the device we have 633141cc406Sopenharmony_ci */ 634141cc406Sopenharmony_cistatic SANE_Status init_options( Plustek_Scanner *s ) 635141cc406Sopenharmony_ci{ 636141cc406Sopenharmony_ci int i; 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci memset( s->opt, 0, sizeof(s->opt)); 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci for( i = 0; i < NUM_OPTIONS; ++i ) { 641141cc406Sopenharmony_ci s->opt[i].size = sizeof (SANE_Word); 642141cc406Sopenharmony_ci s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 643141cc406Sopenharmony_ci } 644141cc406Sopenharmony_ci 645141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 646141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 647141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 648141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 649141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; 650141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 651141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; 652141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci /* "Scan Mode" group: */ 655141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].name = "scanmode-group"; 656141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); 657141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 658141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 659141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci /* scan mode */ 662141cc406Sopenharmony_ci s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 663141cc406Sopenharmony_ci s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 664141cc406Sopenharmony_ci s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 665141cc406Sopenharmony_ci s->opt[OPT_MODE].type = SANE_TYPE_STRING; 666141cc406Sopenharmony_ci s->opt[OPT_MODE].size = 32; 667141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci if((_ASIC_IS_98001 == s->hw->caps.AsicID) || 670141cc406Sopenharmony_ci (_ASIC_IS_98003 == s->hw->caps.AsicID)) { 671141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_9800x_list; 672141cc406Sopenharmony_ci } else { 673141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_list; 674141cc406Sopenharmony_ci } 675141cc406Sopenharmony_ci s->val[OPT_MODE].w = 3; /* Color */ 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci /* scan source */ 678141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].name = SANE_NAME_SCAN_SOURCE; 679141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].title = SANE_TITLE_SCAN_SOURCE; 680141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].desc = SANE_DESC_SCAN_SOURCE; 681141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].type = SANE_TYPE_STRING; 682141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].size = 32; 683141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 684141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].constraint.string_list = ext_mode_list; 685141cc406Sopenharmony_ci s->val[OPT_EXT_MODE].w = 0; /* Normal */ 686141cc406Sopenharmony_ci 687141cc406Sopenharmony_ci /* halftone */ 688141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE_PATTERN; 689141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; 690141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].desc = SANE_DESC_HALFTONE_PATTERN; 691141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING; 692141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].size = 32; 693141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 694141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].constraint.string_list = halftone_list; 695141cc406Sopenharmony_ci s->val[OPT_HALFTONE].w = 0; /* Standard dithermap */ 696141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci /* brightness */ 699141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 700141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 701141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 702141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; 703141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; 704141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 705141cc406Sopenharmony_ci s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; 706141cc406Sopenharmony_ci s->val[OPT_BRIGHTNESS].w = 0; 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci /* contrast */ 709141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 710141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 711141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 712141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; 713141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; 714141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 715141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].constraint.range = &percentage_range; 716141cc406Sopenharmony_ci s->val[OPT_CONTRAST].w = 0; 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci /* resolution */ 719141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 720141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 721141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 722141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 723141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 724141cc406Sopenharmony_ci 725141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 726141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; 727141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; 728141cc406Sopenharmony_ci 729141cc406Sopenharmony_ci /* custom-gamma table */ 730141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 731141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 732141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 733141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 734141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci /* preview */ 737141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 738141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 739141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 740141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 741141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = 0; 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci /* "Geometry" group: */ 744141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].name = "geometry-group"; 745141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); 746141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 747141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 748141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 749141cc406Sopenharmony_ci 750141cc406Sopenharmony_ci /* top-left x */ 751141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 752141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 753141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 754141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 755141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 756141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 757141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; 758141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); 759141cc406Sopenharmony_ci 760141cc406Sopenharmony_ci /* top-left y */ 761141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 762141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 763141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 764141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 765141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 766141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 767141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; 768141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); 769141cc406Sopenharmony_ci 770141cc406Sopenharmony_ci /* bottom-right x */ 771141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 772141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 773141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 774141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 775141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 776141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 777141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; 778141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ci /* bottom-right y */ 781141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 782141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 783141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 784141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 785141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 786141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 787141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; 788141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci /* "Enhancement" group: */ 791141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement"); 792141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 793141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 794141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; 795141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_ci initGammaSettings( s ); 798141cc406Sopenharmony_ci 799141cc406Sopenharmony_ci /* grayscale gamma vector */ 800141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 801141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 802141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 803141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 804141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 805141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 806141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR].wa = &(s->gamma_table[0][0]); 807141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint.range = &(s->gamma_range); 808141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].size = s->gamma_length * sizeof(SANE_Word); 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci /* red gamma vector */ 811141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 812141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 813141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 814141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 815141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 816141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 817141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_R].wa = &(s->gamma_table[1][0]); 818141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(s->gamma_range); 819141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].size = s->gamma_length * sizeof(SANE_Word); 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci /* green gamma vector */ 822141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 823141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 824141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 825141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 826141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 827141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 828141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_G].wa = &(s->gamma_table[2][0]); 829141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(s->gamma_range); 830141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].size = s->gamma_length * sizeof(SANE_Word); 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci /* blue gamma vector */ 833141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 834141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 835141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 836141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 837141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 838141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 839141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_B].wa = &(s->gamma_table[3][0]); 840141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(s->gamma_range); 841141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].size = s->gamma_length * sizeof(SANE_Word); 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci /* GAMMA stuff is disabled per default */ 844141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 845141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 846141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 847141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 848141cc406Sopenharmony_ci 849141cc406Sopenharmony_ci /* disable extended mode list for devices without TPA */ 850141cc406Sopenharmony_ci if( 0 == (s->hw->caps.dwFlag & SFLAG_TPA)) { 851141cc406Sopenharmony_ci s->opt[OPT_EXT_MODE].cap |= SANE_CAP_INACTIVE; 852141cc406Sopenharmony_ci } 853141cc406Sopenharmony_ci 854141cc406Sopenharmony_ci /* disable custom gamma, if not supported by the driver... */ 855141cc406Sopenharmony_ci if( 0 == (s->hw->caps.dwFlag & SFLAG_CUSTOM_GAMMA)) { 856141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 857141cc406Sopenharmony_ci } 858141cc406Sopenharmony_ci 859141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 860141cc406Sopenharmony_ci} 861141cc406Sopenharmony_ci 862141cc406Sopenharmony_ci#define _INT 0 863141cc406Sopenharmony_ci#define _FLOAT 1 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci/** function to decode an value and give it back to the caller. 866141cc406Sopenharmony_ci * @param src - pointer to the source string to check 867141cc406Sopenharmony_ci * @param opt - string that keeps the option name to check src for 868141cc406Sopenharmony_ci * @param what - _FLOAT or _INT 869141cc406Sopenharmony_ci * @param result - pointer to the var that should receive our result 870141cc406Sopenharmony_ci * @param def - default value that result should be in case of any error 871141cc406Sopenharmony_ci * @return The function returns SANE_TRUE if the option has been found, 872141cc406Sopenharmony_ci * if not, it returns SANE_FALSE 873141cc406Sopenharmony_ci */ 874141cc406Sopenharmony_cistatic SANE_Bool decodeVal( char *src, char *opt, 875141cc406Sopenharmony_ci int what, void *result, void *def ) 876141cc406Sopenharmony_ci{ 877141cc406Sopenharmony_ci char *tmp, *tmp2; 878141cc406Sopenharmony_ci const char *name; 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ci /* skip the option string */ 881141cc406Sopenharmony_ci name = (const char*)&src[strlen("option")]; 882141cc406Sopenharmony_ci 883141cc406Sopenharmony_ci /* get the name of the option */ 884141cc406Sopenharmony_ci name = sanei_config_get_string( name, &tmp ); 885141cc406Sopenharmony_ci 886141cc406Sopenharmony_ci if( tmp ) { 887141cc406Sopenharmony_ci 888141cc406Sopenharmony_ci /* on success, compare with the given one */ 889141cc406Sopenharmony_ci if( 0 == strcmp( tmp, opt )) { 890141cc406Sopenharmony_ci 891141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "Decoding option >%s<\n", opt ); 892141cc406Sopenharmony_ci 893141cc406Sopenharmony_ci if( _INT == what ) { 894141cc406Sopenharmony_ci 895141cc406Sopenharmony_ci /* assign the default value for this option... */ 896141cc406Sopenharmony_ci *((int*)result) = *((int*)def); 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci if( *name ) { 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci /* get the configuration value and decode it */ 901141cc406Sopenharmony_ci name = sanei_config_get_string( name, &tmp2 ); 902141cc406Sopenharmony_ci 903141cc406Sopenharmony_ci if( tmp2 ) { 904141cc406Sopenharmony_ci *((int*)result) = strtol( tmp2, 0, 0 ); 905141cc406Sopenharmony_ci free( tmp2 ); 906141cc406Sopenharmony_ci } 907141cc406Sopenharmony_ci } 908141cc406Sopenharmony_ci free( tmp ); 909141cc406Sopenharmony_ci return SANE_TRUE; 910141cc406Sopenharmony_ci 911141cc406Sopenharmony_ci } else if( _FLOAT == what ) { 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci /* assign the default value for this option... */ 914141cc406Sopenharmony_ci *((double*)result) = *((double*)def); 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci if( *name ) { 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci /* get the configuration value and decode it */ 919141cc406Sopenharmony_ci name = sanei_config_get_string( name, &tmp2 ); 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci if( tmp2 ) { 922141cc406Sopenharmony_ci *((double*)result) = strtod( tmp2, 0 ); 923141cc406Sopenharmony_ci free( tmp2 ); 924141cc406Sopenharmony_ci } 925141cc406Sopenharmony_ci } 926141cc406Sopenharmony_ci free( tmp ); 927141cc406Sopenharmony_ci return SANE_TRUE; 928141cc406Sopenharmony_ci } 929141cc406Sopenharmony_ci } 930141cc406Sopenharmony_ci free( tmp ); 931141cc406Sopenharmony_ci } 932141cc406Sopenharmony_ci 933141cc406Sopenharmony_ci return SANE_FALSE; 934141cc406Sopenharmony_ci} 935141cc406Sopenharmony_ci 936141cc406Sopenharmony_ci/** function to retrieve the device name of a given string 937141cc406Sopenharmony_ci * @param src - string that keeps the option name to check src for 938141cc406Sopenharmony_ci * @param dest - pointer to the string, that should receive the detected 939141cc406Sopenharmony_ci * devicename 940141cc406Sopenharmony_ci * @return The function returns SANE_TRUE if the devicename has been found, 941141cc406Sopenharmony_ci * if not, it returns SANE_FALSE 942141cc406Sopenharmony_ci */ 943141cc406Sopenharmony_cistatic SANE_Bool decodeDevName( char *src, char *dest ) 944141cc406Sopenharmony_ci{ 945141cc406Sopenharmony_ci char *tmp; 946141cc406Sopenharmony_ci const char *name; 947141cc406Sopenharmony_ci 948141cc406Sopenharmony_ci if( 0 == strncmp( "device", src, 6 )) { 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci name = (const char*)&src[strlen("device")]; 951141cc406Sopenharmony_ci name = sanei_config_skip_whitespace( name ); 952141cc406Sopenharmony_ci 953141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "Decoding device name >%s<\n", name ); 954141cc406Sopenharmony_ci 955141cc406Sopenharmony_ci if( *name ) { 956141cc406Sopenharmony_ci name = sanei_config_get_string( name, &tmp ); 957141cc406Sopenharmony_ci if( tmp ) { 958141cc406Sopenharmony_ci 959141cc406Sopenharmony_ci strcpy( dest, tmp ); 960141cc406Sopenharmony_ci free( tmp ); 961141cc406Sopenharmony_ci return SANE_TRUE; 962141cc406Sopenharmony_ci } 963141cc406Sopenharmony_ci } 964141cc406Sopenharmony_ci } 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci return SANE_FALSE; 967141cc406Sopenharmony_ci} 968141cc406Sopenharmony_ci 969141cc406Sopenharmony_ci/** attach a device to the backend 970141cc406Sopenharmony_ci */ 971141cc406Sopenharmony_cistatic SANE_Status attach( const char *dev_name, pCnfDef cnf, 972141cc406Sopenharmony_ci Plustek_Device **devp ) 973141cc406Sopenharmony_ci{ 974141cc406Sopenharmony_ci int cntr; 975141cc406Sopenharmony_ci int result; 976141cc406Sopenharmony_ci int handle; 977141cc406Sopenharmony_ci Plustek_Device *dev; 978141cc406Sopenharmony_ci 979141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "attach (%s, %p, %p)\n", 980141cc406Sopenharmony_ci dev_name, (void *)cnf, (void *)devp); 981141cc406Sopenharmony_ci 982141cc406Sopenharmony_ci /* already attached ?*/ 983141cc406Sopenharmony_ci for( dev = first_dev; dev; dev = dev->next ) { 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci if( 0 == strcmp( dev->sane.name, dev_name )) { 986141cc406Sopenharmony_ci if( devp ) 987141cc406Sopenharmony_ci *devp = dev; 988141cc406Sopenharmony_ci 989141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 990141cc406Sopenharmony_ci } 991141cc406Sopenharmony_ci } 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ci /* allocate some memory for the device */ 994141cc406Sopenharmony_ci dev = malloc( sizeof (*dev)); 995141cc406Sopenharmony_ci if( NULL == dev ) 996141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 997141cc406Sopenharmony_ci 998141cc406Sopenharmony_ci /* assign all the stuff we need for this device... */ 999141cc406Sopenharmony_ci 1000141cc406Sopenharmony_ci memset(dev, 0, sizeof (*dev)); 1001141cc406Sopenharmony_ci 1002141cc406Sopenharmony_ci dev->fd = -1; 1003141cc406Sopenharmony_ci dev->name = strdup(dev_name); /* hold it double to avoid */ 1004141cc406Sopenharmony_ci dev->sane.name = dev->name; /* compiler warnings */ 1005141cc406Sopenharmony_ci dev->sane.vendor = "Plustek"; 1006141cc406Sopenharmony_ci dev->initialized = -1; /* will be used as index too */ 1007141cc406Sopenharmony_ci 1008141cc406Sopenharmony_ci memcpy( &dev->adj, &cnf->adj, sizeof(AdjDef)); 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci show_cnf( cnf ); 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci dev->sane.type = SANE_I18N ("flatbed scanner"); 1013141cc406Sopenharmony_ci dev->open = ppDev_open; 1014141cc406Sopenharmony_ci dev->close = ppDev_close; 1015141cc406Sopenharmony_ci dev->getCaps = ppDev_getCaps; 1016141cc406Sopenharmony_ci dev->getLensInfo = ppDev_getLensInfo; 1017141cc406Sopenharmony_ci dev->getCropInfo = ppDev_getCropInfo; 1018141cc406Sopenharmony_ci dev->putImgInfo = ppDev_putImgInfo; 1019141cc406Sopenharmony_ci dev->setScanEnv = ppDev_setScanEnv; 1020141cc406Sopenharmony_ci dev->startScan = ppDev_startScan; 1021141cc406Sopenharmony_ci dev->stopScan = ppDev_stopScan; 1022141cc406Sopenharmony_ci dev->setMap = ppDev_setMap; 1023141cc406Sopenharmony_ci dev->readImage = ppDev_readImage; 1024141cc406Sopenharmony_ci dev->shutdown = NULL; 1025141cc406Sopenharmony_ci dev->readLine = NULL; 1026141cc406Sopenharmony_ci dev->prepare = NULL; 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci /* 1029141cc406Sopenharmony_ci * go ahead and open the scanner device 1030141cc406Sopenharmony_ci */ 1031141cc406Sopenharmony_ci handle = drvopen( dev ); 1032141cc406Sopenharmony_ci if( handle < 0 ) { 1033141cc406Sopenharmony_ci DBG( _DBG_ERROR,"open failed: %d\n", handle ); 1034141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1035141cc406Sopenharmony_ci } 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci /* okay, so assign the handle... */ 1038141cc406Sopenharmony_ci dev->fd = handle; 1039141cc406Sopenharmony_ci 1040141cc406Sopenharmony_ci result = dev->getCaps( dev ); 1041141cc406Sopenharmony_ci if( result < 0 ) { 1042141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->getCaps() failed(%d)\n", result); 1043141cc406Sopenharmony_ci dev->close(dev); 1044141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1045141cc406Sopenharmony_ci } 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci result = dev->getLensInfo( dev, &lens ); 1048141cc406Sopenharmony_ci if( result < 0 ) { 1049141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->getLensInfo() failed(%d)\n", result ); 1050141cc406Sopenharmony_ci dev->close(dev); 1051141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1052141cc406Sopenharmony_ci } 1053141cc406Sopenharmony_ci 1054141cc406Sopenharmony_ci /* did we fail on connection? */ 1055141cc406Sopenharmony_ci if( _NO_BASE == dev->caps.wIOBase ) { 1056141cc406Sopenharmony_ci DBG( _DBG_ERROR, "failed to find Plustek scanner\n" ); 1057141cc406Sopenharmony_ci dev->close(dev); 1058141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1059141cc406Sopenharmony_ci } 1060141cc406Sopenharmony_ci 1061141cc406Sopenharmony_ci /* save the info we got from the driver */ 1062141cc406Sopenharmony_ci DBG( _DBG_INFO, "Scanner information:\n" ); 1063141cc406Sopenharmony_ci if( dev->caps.Model < MODEL_UNKNOWN ) { 1064141cc406Sopenharmony_ci dev->sane.model = ModelStr[dev->caps.Model]; 1065141cc406Sopenharmony_ci } else { 1066141cc406Sopenharmony_ci dev->sane.model = ModelStr[0]; 1067141cc406Sopenharmony_ci } 1068141cc406Sopenharmony_ci 1069141cc406Sopenharmony_ci DBG( _DBG_INFO, "Vendor : %s\n", dev->sane.vendor ); 1070141cc406Sopenharmony_ci DBG( _DBG_INFO, "Model : %s\n", dev->sane.model ); 1071141cc406Sopenharmony_ci DBG( _DBG_INFO, "Asic : 0x%02x\n", dev->caps.AsicID ); 1072141cc406Sopenharmony_ci DBG( _DBG_INFO, "Flags : 0x%08lx\n", dev->caps.dwFlag ); 1073141cc406Sopenharmony_ci 1074141cc406Sopenharmony_ci dev->max_x = dev->caps.wMaxExtentX*MM_PER_INCH/_MEASURE_BASE; 1075141cc406Sopenharmony_ci dev->max_y = dev->caps.wMaxExtentY*MM_PER_INCH/_MEASURE_BASE; 1076141cc406Sopenharmony_ci 1077141cc406Sopenharmony_ci dev->res_list = (SANE_Int *)calloc(((lens.rDpiX.wMax -_DEF_DPI)/25 + 1), 1078141cc406Sopenharmony_ci sizeof (SANE_Int)); /* one more to avoid a buffer overflow */ 1079141cc406Sopenharmony_ci 1080141cc406Sopenharmony_ci if (NULL == dev->res_list) { 1081141cc406Sopenharmony_ci DBG( _DBG_ERROR, "alloc fail, resolution problem\n" ); 1082141cc406Sopenharmony_ci dev->close(dev); 1083141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1084141cc406Sopenharmony_ci } 1085141cc406Sopenharmony_ci 1086141cc406Sopenharmony_ci /* build up the resolution table */ 1087141cc406Sopenharmony_ci dev->res_list_size = 0; 1088141cc406Sopenharmony_ci for( cntr = _DEF_DPI; cntr <= lens.rDpiX.wMax; cntr += 25 ) { 1089141cc406Sopenharmony_ci dev->res_list_size++; 1090141cc406Sopenharmony_ci dev->res_list[dev->res_list_size - 1] = (SANE_Int)cntr; 1091141cc406Sopenharmony_ci } 1092141cc406Sopenharmony_ci 1093141cc406Sopenharmony_ci limitResolution( dev ); 1094141cc406Sopenharmony_ci 1095141cc406Sopenharmony_ci dev->fd = handle; 1096141cc406Sopenharmony_ci drvclose( dev ); 1097141cc406Sopenharmony_ci 1098141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "attach: model = >%s<\n", dev->sane.model ); 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci ++num_devices; 1101141cc406Sopenharmony_ci dev->next = first_dev; 1102141cc406Sopenharmony_ci first_dev = dev; 1103141cc406Sopenharmony_ci 1104141cc406Sopenharmony_ci if (devp) 1105141cc406Sopenharmony_ci *devp = dev; 1106141cc406Sopenharmony_ci 1107141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1108141cc406Sopenharmony_ci} 1109141cc406Sopenharmony_ci 1110141cc406Sopenharmony_ci/** function to preset a configuration structure 1111141cc406Sopenharmony_ci * @param cnf - pointer to the structure that should be initialized 1112141cc406Sopenharmony_ci */ 1113141cc406Sopenharmony_cistatic void init_config_struct( pCnfDef cnf, SANE_Bool direct_io ) 1114141cc406Sopenharmony_ci{ 1115141cc406Sopenharmony_ci memset( cnf, 0, sizeof(CnfDef)); 1116141cc406Sopenharmony_ci 1117141cc406Sopenharmony_ci cnf->adj.direct_io = direct_io; 1118141cc406Sopenharmony_ci 1119141cc406Sopenharmony_ci cnf->adj.warmup = -1; 1120141cc406Sopenharmony_ci cnf->adj.lampOff = -1; 1121141cc406Sopenharmony_ci cnf->adj.lampOffOnEnd = -1; 1122141cc406Sopenharmony_ci 1123141cc406Sopenharmony_ci cnf->adj.graygamma = 1.0; 1124141cc406Sopenharmony_ci cnf->adj.rgamma = 1.0; 1125141cc406Sopenharmony_ci cnf->adj.ggamma = 1.0; 1126141cc406Sopenharmony_ci cnf->adj.bgamma = 1.0; 1127141cc406Sopenharmony_ci} 1128141cc406Sopenharmony_ci 1129141cc406Sopenharmony_ci/** initialize the backend 1130141cc406Sopenharmony_ci */ 1131141cc406Sopenharmony_ciSANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize ) 1132141cc406Sopenharmony_ci{ 1133141cc406Sopenharmony_ci char str[PATH_MAX] = _DEFAULT_DEVICE; 1134141cc406Sopenharmony_ci CnfDef config; 1135141cc406Sopenharmony_ci size_t len; 1136141cc406Sopenharmony_ci FILE *fp; 1137141cc406Sopenharmony_ci SANE_Status res; 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci DBG_INIT(); 1140141cc406Sopenharmony_ci sanei_thread_init(); 1141141cc406Sopenharmony_ci 1142141cc406Sopenharmony_ci res = sanei_pp_init(); 1143141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != res ) { 1144141cc406Sopenharmony_ci DBG( _DBG_ERROR, "Could not initialize Parport library!\n" ); 1145141cc406Sopenharmony_ci return res; 1146141cc406Sopenharmony_ci } 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci#if defined PACKAGE && defined VERSION 1149141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "PlustekPP backend V"BACKEND_VERSION", part of " 1150141cc406Sopenharmony_ci PACKAGE " " VERSION "\n"); 1151141cc406Sopenharmony_ci#else 1152141cc406Sopenharmony_ci DBG( _DBG_INFO, "PlustekPP backend V"BACKEND_VERSION"\n" ); 1153141cc406Sopenharmony_ci#endif 1154141cc406Sopenharmony_ci 1155141cc406Sopenharmony_ci /* do some presettings... */ 1156141cc406Sopenharmony_ci auth = authorize; 1157141cc406Sopenharmony_ci first_dev = NULL; 1158141cc406Sopenharmony_ci first_handle = NULL; 1159141cc406Sopenharmony_ci num_devices = 0; 1160141cc406Sopenharmony_ci 1161141cc406Sopenharmony_ci /* initialize the configuration structure */ 1162141cc406Sopenharmony_ci#ifdef _BACKEND_ENABLED 1163141cc406Sopenharmony_ci init_config_struct( &config, SANE_TRUE ); 1164141cc406Sopenharmony_ci#else 1165141cc406Sopenharmony_ci init_config_struct( &config, SANE_FALSE ); 1166141cc406Sopenharmony_ci#endif 1167141cc406Sopenharmony_ci 1168141cc406Sopenharmony_ci if( version_code != NULL ) 1169141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 1170141cc406Sopenharmony_ci 1171141cc406Sopenharmony_ci fp = sanei_config_open( PLUSTEK_CONFIG_FILE ); 1172141cc406Sopenharmony_ci 1173141cc406Sopenharmony_ci /* default to _DEFAULT_DEVICE instead of insisting on config file */ 1174141cc406Sopenharmony_ci if( NULL == fp ) { 1175141cc406Sopenharmony_ci return attach( _DEFAULT_DEVICE, &config, 0 ); 1176141cc406Sopenharmony_ci } 1177141cc406Sopenharmony_ci 1178141cc406Sopenharmony_ci while( sanei_config_read( str, sizeof(str), fp)) { 1179141cc406Sopenharmony_ci 1180141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, ">%s<\n", str ); 1181141cc406Sopenharmony_ci if( str[0] == '#') /* ignore line comments */ 1182141cc406Sopenharmony_ci continue; 1183141cc406Sopenharmony_ci 1184141cc406Sopenharmony_ci len = strlen(str); 1185141cc406Sopenharmony_ci if( 0 == len ) 1186141cc406Sopenharmony_ci continue; /* ignore empty lines */ 1187141cc406Sopenharmony_ci 1188141cc406Sopenharmony_ci /* check for options */ 1189141cc406Sopenharmony_ci if( 0 == strncmp(str, "option", 6)) { 1190141cc406Sopenharmony_ci 1191141cc406Sopenharmony_ci int ival; 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci ival = -1; 1194141cc406Sopenharmony_ci decodeVal( str, "warmup", _INT, &config.adj.warmup, &ival); 1195141cc406Sopenharmony_ci decodeVal( str, "lampOff", _INT, &config.adj.lampOff, &ival); 1196141cc406Sopenharmony_ci decodeVal( str, "lOffOnEnd", _INT, &config.adj.lampOffOnEnd,&ival); 1197141cc406Sopenharmony_ci 1198141cc406Sopenharmony_ci ival = 0; 1199141cc406Sopenharmony_ci decodeVal( str, "mov", _INT, &config.adj.mov, &ival ); 1200141cc406Sopenharmony_ci continue; 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci /* check for sections: */ 1203141cc406Sopenharmony_ci } else if( 0 == strncmp( str, "[direct]", 8)) { 1204141cc406Sopenharmony_ci 1205141cc406Sopenharmony_ci /* new section, try and attach previous device */ 1206141cc406Sopenharmony_ci if( config.devName[0] != '\0' ) 1207141cc406Sopenharmony_ci attach( config.devName, &config, 0 ); 1208141cc406Sopenharmony_ci 1209141cc406Sopenharmony_ci /* re-initialize the configuration structure */ 1210141cc406Sopenharmony_ci init_config_struct( &config, SANE_TRUE ); 1211141cc406Sopenharmony_ci continue; 1212141cc406Sopenharmony_ci 1213141cc406Sopenharmony_ci } else if( 0 == strncmp( str, "[kernel]", 8 )) { 1214141cc406Sopenharmony_ci 1215141cc406Sopenharmony_ci /* new section, try and attach previous device */ 1216141cc406Sopenharmony_ci if( config.devName[0] != '\0' ) 1217141cc406Sopenharmony_ci attach( config.devName, &config, 0 ); 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_ci /* re-initialize the configuration structure */ 1220141cc406Sopenharmony_ci init_config_struct( &config, SANE_FALSE ); 1221141cc406Sopenharmony_ci continue; 1222141cc406Sopenharmony_ci 1223141cc406Sopenharmony_ci } else if( SANE_TRUE == decodeDevName( str, config.devName )) { 1224141cc406Sopenharmony_ci continue; 1225141cc406Sopenharmony_ci } 1226141cc406Sopenharmony_ci 1227141cc406Sopenharmony_ci /* ignore other stuff... */ 1228141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "ignoring >%s<\n", str ); 1229141cc406Sopenharmony_ci } 1230141cc406Sopenharmony_ci fclose (fp); 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci /* try to attach the last device in the config file... */ 1233141cc406Sopenharmony_ci if( config.devName[0] != '\0' ) 1234141cc406Sopenharmony_ci attach( config.devName, &config, 0 ); 1235141cc406Sopenharmony_ci 1236141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1237141cc406Sopenharmony_ci} 1238141cc406Sopenharmony_ci 1239141cc406Sopenharmony_ci/** cleanup the backend... 1240141cc406Sopenharmony_ci */ 1241141cc406Sopenharmony_civoid sane_exit( void ) 1242141cc406Sopenharmony_ci{ 1243141cc406Sopenharmony_ci Plustek_Device *dev, *next; 1244141cc406Sopenharmony_ci 1245141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_exit\n" ); 1246141cc406Sopenharmony_ci 1247141cc406Sopenharmony_ci for( dev = first_dev; dev; ) { 1248141cc406Sopenharmony_ci 1249141cc406Sopenharmony_ci next = dev->next; 1250141cc406Sopenharmony_ci 1251141cc406Sopenharmony_ci /* call the shutdown function of each device... */ 1252141cc406Sopenharmony_ci if( dev->shutdown ) 1253141cc406Sopenharmony_ci dev->shutdown( dev ); 1254141cc406Sopenharmony_ci 1255141cc406Sopenharmony_ci /* 1256141cc406Sopenharmony_ci * we're doin' this to avoid compiler warnings as dev->sane.name 1257141cc406Sopenharmony_ci * is defined as const char* 1258141cc406Sopenharmony_ci */ 1259141cc406Sopenharmony_ci if( dev->sane.name ) 1260141cc406Sopenharmony_ci free( dev->name ); 1261141cc406Sopenharmony_ci 1262141cc406Sopenharmony_ci if( dev->res_list ) 1263141cc406Sopenharmony_ci free( dev->res_list ); 1264141cc406Sopenharmony_ci free( dev ); 1265141cc406Sopenharmony_ci 1266141cc406Sopenharmony_ci dev = next; 1267141cc406Sopenharmony_ci } 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_ci if( devlist ) 1270141cc406Sopenharmony_ci free( devlist ); 1271141cc406Sopenharmony_ci 1272141cc406Sopenharmony_ci /* call driver specific shutdown function... */ 1273141cc406Sopenharmony_ci PtDrvShutdown(); 1274141cc406Sopenharmony_ci 1275141cc406Sopenharmony_ci devlist = NULL; 1276141cc406Sopenharmony_ci auth = NULL; 1277141cc406Sopenharmony_ci first_dev = NULL; 1278141cc406Sopenharmony_ci first_handle = NULL; 1279141cc406Sopenharmony_ci} 1280141cc406Sopenharmony_ci 1281141cc406Sopenharmony_ci/** return a list of all devices 1282141cc406Sopenharmony_ci */ 1283141cc406Sopenharmony_ciSANE_Status sane_get_devices(const SANE_Device ***device_list, 1284141cc406Sopenharmony_ci SANE_Bool local_only ) 1285141cc406Sopenharmony_ci{ 1286141cc406Sopenharmony_ci int i; 1287141cc406Sopenharmony_ci Plustek_Device *dev; 1288141cc406Sopenharmony_ci 1289141cc406Sopenharmony_ci DBG(_DBG_SANE_INIT, "sane_get_devices (%p, %ld)\n", 1290141cc406Sopenharmony_ci (void *)device_list, (long) local_only); 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci /* already called, so cleanup */ 1293141cc406Sopenharmony_ci if( devlist ) 1294141cc406Sopenharmony_ci free( devlist ); 1295141cc406Sopenharmony_ci 1296141cc406Sopenharmony_ci devlist = malloc((num_devices + 1) * sizeof (devlist[0])); 1297141cc406Sopenharmony_ci if ( NULL == devlist ) 1298141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1299141cc406Sopenharmony_ci 1300141cc406Sopenharmony_ci i = 0; 1301141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 1302141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 1303141cc406Sopenharmony_ci devlist[i++] = 0; 1304141cc406Sopenharmony_ci 1305141cc406Sopenharmony_ci *device_list = devlist; 1306141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1307141cc406Sopenharmony_ci} 1308141cc406Sopenharmony_ci 1309141cc406Sopenharmony_ci/** open the sane device 1310141cc406Sopenharmony_ci */ 1311141cc406Sopenharmony_ciSANE_Status sane_open( SANE_String_Const devicename, SANE_Handle* handle ) 1312141cc406Sopenharmony_ci{ 1313141cc406Sopenharmony_ci SANE_Status status; 1314141cc406Sopenharmony_ci Plustek_Device *dev; 1315141cc406Sopenharmony_ci Plustek_Scanner *s; 1316141cc406Sopenharmony_ci CnfDef config; 1317141cc406Sopenharmony_ci 1318141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_open - %s\n", devicename ); 1319141cc406Sopenharmony_ci 1320141cc406Sopenharmony_ci if( devicename[0] ) { 1321141cc406Sopenharmony_ci for( dev = first_dev; dev; dev = dev->next ) { 1322141cc406Sopenharmony_ci if( strcmp( dev->sane.name, devicename ) == 0 ) 1323141cc406Sopenharmony_ci break; 1324141cc406Sopenharmony_ci } 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci if( !dev ) { 1327141cc406Sopenharmony_ci 1328141cc406Sopenharmony_ci memset( &config, 0, sizeof(CnfDef)); 1329141cc406Sopenharmony_ci 1330141cc406Sopenharmony_ci /* check if a valid parport-device is meant... */ 1331141cc406Sopenharmony_ci status = attach( devicename, &config, &dev ); 1332141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != status ) 1333141cc406Sopenharmony_ci return status; 1334141cc406Sopenharmony_ci } 1335141cc406Sopenharmony_ci } else { 1336141cc406Sopenharmony_ci /* empty devicename -> use first device */ 1337141cc406Sopenharmony_ci dev = first_dev; 1338141cc406Sopenharmony_ci } 1339141cc406Sopenharmony_ci 1340141cc406Sopenharmony_ci if( !dev ) 1341141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1342141cc406Sopenharmony_ci 1343141cc406Sopenharmony_ci s = malloc (sizeof (*s)); 1344141cc406Sopenharmony_ci if( NULL == s ) 1345141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1346141cc406Sopenharmony_ci 1347141cc406Sopenharmony_ci memset(s, 0, sizeof (*s)); 1348141cc406Sopenharmony_ci s->r_pipe = -1; 1349141cc406Sopenharmony_ci s->w_pipe = -1; 1350141cc406Sopenharmony_ci s->hw = dev; 1351141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1352141cc406Sopenharmony_ci 1353141cc406Sopenharmony_ci init_options(s); 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles: */ 1356141cc406Sopenharmony_ci s->next = first_handle; 1357141cc406Sopenharmony_ci first_handle = s; 1358141cc406Sopenharmony_ci 1359141cc406Sopenharmony_ci *handle = s; 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1362141cc406Sopenharmony_ci} 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci/** 1365141cc406Sopenharmony_ci */ 1366141cc406Sopenharmony_civoid sane_close (SANE_Handle handle) 1367141cc406Sopenharmony_ci{ 1368141cc406Sopenharmony_ci Plustek_Scanner *prev, *s; 1369141cc406Sopenharmony_ci 1370141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_close\n" ); 1371141cc406Sopenharmony_ci 1372141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 1373141cc406Sopenharmony_ci prev = 0; 1374141cc406Sopenharmony_ci 1375141cc406Sopenharmony_ci for( s = first_handle; s; s = s->next ) { 1376141cc406Sopenharmony_ci if( s == handle ) 1377141cc406Sopenharmony_ci break; 1378141cc406Sopenharmony_ci prev = s; 1379141cc406Sopenharmony_ci } 1380141cc406Sopenharmony_ci 1381141cc406Sopenharmony_ci if (!s) { 1382141cc406Sopenharmony_ci DBG( _DBG_ERROR, "close: invalid handle %p\n", handle); 1383141cc406Sopenharmony_ci return; 1384141cc406Sopenharmony_ci } 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci close_pipe( s ); 1387141cc406Sopenharmony_ci 1388141cc406Sopenharmony_ci if( NULL != s->buf ) 1389141cc406Sopenharmony_ci free(s->buf); 1390141cc406Sopenharmony_ci 1391141cc406Sopenharmony_ci drvclose( s->hw ); 1392141cc406Sopenharmony_ci 1393141cc406Sopenharmony_ci if (prev) 1394141cc406Sopenharmony_ci prev->next = s->next; 1395141cc406Sopenharmony_ci else 1396141cc406Sopenharmony_ci first_handle = s->next; 1397141cc406Sopenharmony_ci 1398141cc406Sopenharmony_ci free(s); 1399141cc406Sopenharmony_ci} 1400141cc406Sopenharmony_ci 1401141cc406Sopenharmony_ci/** goes through a string list and returns the start-address of the string 1402141cc406Sopenharmony_ci * that has been found, or NULL on error 1403141cc406Sopenharmony_ci */ 1404141cc406Sopenharmony_cistatic const SANE_String_Const *search_string_list( 1405141cc406Sopenharmony_ci const SANE_String_Const *list, SANE_String value ) 1406141cc406Sopenharmony_ci{ 1407141cc406Sopenharmony_ci while( *list != NULL && strcmp(value, *list) != 0 ) 1408141cc406Sopenharmony_ci ++list; 1409141cc406Sopenharmony_ci 1410141cc406Sopenharmony_ci if( *list == NULL ) 1411141cc406Sopenharmony_ci return NULL; 1412141cc406Sopenharmony_ci 1413141cc406Sopenharmony_ci return list; 1414141cc406Sopenharmony_ci} 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci/** return or set the parameter values, also do some checks 1417141cc406Sopenharmony_ci */ 1418141cc406Sopenharmony_ciSANE_Status sane_control_option( SANE_Handle handle, SANE_Int option, 1419141cc406Sopenharmony_ci SANE_Action action, void *value, 1420141cc406Sopenharmony_ci SANE_Int * info) 1421141cc406Sopenharmony_ci{ 1422141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner *)handle; 1423141cc406Sopenharmony_ci SANE_Status status; 1424141cc406Sopenharmony_ci const SANE_String_Const *optval; 1425141cc406Sopenharmony_ci pModeParam mp; 1426141cc406Sopenharmony_ci int scanmode; 1427141cc406Sopenharmony_ci 1428141cc406Sopenharmony_ci if ( s->scanning ) 1429141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1430141cc406Sopenharmony_ci 1431141cc406Sopenharmony_ci if((option < 0) || (option >= NUM_OPTIONS)) 1432141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1433141cc406Sopenharmony_ci 1434141cc406Sopenharmony_ci if( NULL != info ) 1435141cc406Sopenharmony_ci *info = 0; 1436141cc406Sopenharmony_ci 1437141cc406Sopenharmony_ci switch( action ) { 1438141cc406Sopenharmony_ci 1439141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 1440141cc406Sopenharmony_ci switch (option) { 1441141cc406Sopenharmony_ci case OPT_PREVIEW: 1442141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1443141cc406Sopenharmony_ci case OPT_RESOLUTION: 1444141cc406Sopenharmony_ci case OPT_TL_X: 1445141cc406Sopenharmony_ci case OPT_TL_Y: 1446141cc406Sopenharmony_ci case OPT_BR_X: 1447141cc406Sopenharmony_ci case OPT_BR_Y: 1448141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1449141cc406Sopenharmony_ci *(SANE_Word *)value = s->val[option].w; 1450141cc406Sopenharmony_ci break; 1451141cc406Sopenharmony_ci 1452141cc406Sopenharmony_ci case OPT_CONTRAST: 1453141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1454141cc406Sopenharmony_ci *(SANE_Word *)value = 1455141cc406Sopenharmony_ci (s->val[option].w << SANE_FIXED_SCALE_SHIFT); 1456141cc406Sopenharmony_ci break; 1457141cc406Sopenharmony_ci 1458141cc406Sopenharmony_ci case OPT_MODE: 1459141cc406Sopenharmony_ci case OPT_EXT_MODE: 1460141cc406Sopenharmony_ci case OPT_HALFTONE: 1461141cc406Sopenharmony_ci strcpy ((char *) value, 1462141cc406Sopenharmony_ci s->opt[option].constraint.string_list[s->val[option].w]); 1463141cc406Sopenharmony_ci break; 1464141cc406Sopenharmony_ci 1465141cc406Sopenharmony_ci /* word array options: */ 1466141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1467141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1468141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1469141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1470141cc406Sopenharmony_ci memcpy( value, s->val[option].wa, s->opt[option].size ); 1471141cc406Sopenharmony_ci break; 1472141cc406Sopenharmony_ci 1473141cc406Sopenharmony_ci default: 1474141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1475141cc406Sopenharmony_ci } 1476141cc406Sopenharmony_ci break; 1477141cc406Sopenharmony_ci 1478141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 1479141cc406Sopenharmony_ci status = sanei_constrain_value( s->opt + option, value, info ); 1480141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != status ) 1481141cc406Sopenharmony_ci return status; 1482141cc406Sopenharmony_ci 1483141cc406Sopenharmony_ci optval = NULL; 1484141cc406Sopenharmony_ci if( SANE_CONSTRAINT_STRING_LIST == s->opt[option].constraint_type ) { 1485141cc406Sopenharmony_ci 1486141cc406Sopenharmony_ci optval = search_string_list( s->opt[option].constraint.string_list, 1487141cc406Sopenharmony_ci (char *) value); 1488141cc406Sopenharmony_ci if( NULL == optval ) 1489141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1490141cc406Sopenharmony_ci } 1491141cc406Sopenharmony_ci 1492141cc406Sopenharmony_ci switch (option) { 1493141cc406Sopenharmony_ci 1494141cc406Sopenharmony_ci case OPT_RESOLUTION: { 1495141cc406Sopenharmony_ci int n; 1496141cc406Sopenharmony_ci int min_d = s->hw->res_list[s->hw->res_list_size - 1]; 1497141cc406Sopenharmony_ci int v = *(SANE_Word *)value; 1498141cc406Sopenharmony_ci int best = v; 1499141cc406Sopenharmony_ci 1500141cc406Sopenharmony_ci for( n = 0; n < s->hw->res_list_size; n++ ) { 1501141cc406Sopenharmony_ci int d = abs(v - s->hw->res_list[n]); 1502141cc406Sopenharmony_ci 1503141cc406Sopenharmony_ci if( d < min_d ) { 1504141cc406Sopenharmony_ci min_d = d; 1505141cc406Sopenharmony_ci best = s->hw->res_list[n]; 1506141cc406Sopenharmony_ci } 1507141cc406Sopenharmony_ci } 1508141cc406Sopenharmony_ci 1509141cc406Sopenharmony_ci s->val[option].w = (SANE_Word)best; 1510141cc406Sopenharmony_ci 1511141cc406Sopenharmony_ci if( v != best ) 1512141cc406Sopenharmony_ci *(SANE_Word *)value = best; 1513141cc406Sopenharmony_ci 1514141cc406Sopenharmony_ci if( NULL != info ) { 1515141cc406Sopenharmony_ci if( v != best ) 1516141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1517141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1518141cc406Sopenharmony_ci } 1519141cc406Sopenharmony_ci break; 1520141cc406Sopenharmony_ci 1521141cc406Sopenharmony_ci } 1522141cc406Sopenharmony_ci 1523141cc406Sopenharmony_ci case OPT_PREVIEW: 1524141cc406Sopenharmony_ci case OPT_TL_X: 1525141cc406Sopenharmony_ci case OPT_TL_Y: 1526141cc406Sopenharmony_ci case OPT_BR_X: 1527141cc406Sopenharmony_ci case OPT_BR_Y: 1528141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *)value; 1529141cc406Sopenharmony_ci if( NULL != info ) 1530141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1531141cc406Sopenharmony_ci break; 1532141cc406Sopenharmony_ci 1533141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1534141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *)value; 1535141cc406Sopenharmony_ci if( NULL != info ) 1536141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 1537141cc406Sopenharmony_ci 1538141cc406Sopenharmony_ci mp = getModeList( s ); 1539141cc406Sopenharmony_ci scanmode = mp[s->val[OPT_MODE].w].scanmode; 1540141cc406Sopenharmony_ci 1541141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1542141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1543141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1544141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1545141cc406Sopenharmony_ci 1546141cc406Sopenharmony_ci if( SANE_TRUE == s->val[option].w ) { 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci if((scanmode == COLOR_256GRAY) || 1549141cc406Sopenharmony_ci (scanmode == COLOR_GRAY16)) { 1550141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1551141cc406Sopenharmony_ci } else { 1552141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1553141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1554141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1555141cc406Sopenharmony_ci } 1556141cc406Sopenharmony_ci 1557141cc406Sopenharmony_ci } else { 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci initGammaSettings( s ); 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci if((scanmode == COLOR_256GRAY) || 1562141cc406Sopenharmony_ci (scanmode == COLOR_GRAY16)) { 1563141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1564141cc406Sopenharmony_ci } else { 1565141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1566141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1567141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1568141cc406Sopenharmony_ci } 1569141cc406Sopenharmony_ci } 1570141cc406Sopenharmony_ci break; 1571141cc406Sopenharmony_ci 1572141cc406Sopenharmony_ci case OPT_CONTRAST: 1573141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1574141cc406Sopenharmony_ci s->val[option].w = 1575141cc406Sopenharmony_ci ((*(SANE_Word *)value) >> SANE_FIXED_SCALE_SHIFT); 1576141cc406Sopenharmony_ci break; 1577141cc406Sopenharmony_ci 1578141cc406Sopenharmony_ci case OPT_MODE: { 1579141cc406Sopenharmony_ci 1580141cc406Sopenharmony_ci int idx = (optval - mode_list); 1581141cc406Sopenharmony_ci 1582141cc406Sopenharmony_ci if((_ASIC_IS_98001 == s->hw->caps.AsicID) || 1583141cc406Sopenharmony_ci (_ASIC_IS_98003 == s->hw->caps.AsicID)) { 1584141cc406Sopenharmony_ci idx = optval - mode_9800x_list; 1585141cc406Sopenharmony_ci } 1586141cc406Sopenharmony_ci 1587141cc406Sopenharmony_ci mp = getModeList( s ); 1588141cc406Sopenharmony_ci 1589141cc406Sopenharmony_ci if( mp[idx].scanmode != COLOR_HALFTONE ){ 1590141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 1591141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1592141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1593141cc406Sopenharmony_ci } else { 1594141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; 1595141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 1596141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1597141cc406Sopenharmony_ci } 1598141cc406Sopenharmony_ci 1599141cc406Sopenharmony_ci if( mp[idx].scanmode == COLOR_BW ) { 1600141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 1601141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1602141cc406Sopenharmony_ci } 1603141cc406Sopenharmony_ci 1604141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1605141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1606141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1607141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1608141cc406Sopenharmony_ci 1609141cc406Sopenharmony_ci if( s->val[OPT_CUSTOM_GAMMA].w && 1610141cc406Sopenharmony_ci !(s->opt[OPT_CUSTOM_GAMMA].cap & SANE_CAP_INACTIVE)) { 1611141cc406Sopenharmony_ci 1612141cc406Sopenharmony_ci if((mp[idx].scanmode == COLOR_256GRAY) || 1613141cc406Sopenharmony_ci (mp[idx].scanmode == COLOR_GRAY16)) { 1614141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1615141cc406Sopenharmony_ci } else { 1616141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1617141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1618141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1619141cc406Sopenharmony_ci } 1620141cc406Sopenharmony_ci } 1621141cc406Sopenharmony_ci 1622141cc406Sopenharmony_ci if( NULL != info ) 1623141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1624141cc406Sopenharmony_ci } 1625141cc406Sopenharmony_ci 1626141cc406Sopenharmony_ci // fall through 1627141cc406Sopenharmony_ci case OPT_HALFTONE: 1628141cc406Sopenharmony_ci s->val[option].w = optval - s->opt[option].constraint.string_list; 1629141cc406Sopenharmony_ci break; 1630141cc406Sopenharmony_ci 1631141cc406Sopenharmony_ci case OPT_EXT_MODE: { 1632141cc406Sopenharmony_ci s->val[option].w = optval - s->opt[option].constraint.string_list; 1633141cc406Sopenharmony_ci 1634141cc406Sopenharmony_ci /* 1635141cc406Sopenharmony_ci * change the area and mode_list when changing the source 1636141cc406Sopenharmony_ci */ 1637141cc406Sopenharmony_ci if( s->val[option].w == 0 ) { 1638141cc406Sopenharmony_ci 1639141cc406Sopenharmony_ci s->hw->dpi_range.min = _DEF_DPI; 1640141cc406Sopenharmony_ci 1641141cc406Sopenharmony_ci s->hw->x_range.max = SANE_FIX(s->hw->max_x); 1642141cc406Sopenharmony_ci s->hw->y_range.max = SANE_FIX(s->hw->max_y); 1643141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); 1644141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); 1645141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); 1646141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); 1647141cc406Sopenharmony_ci s->val[OPT_MODE].w = 3; /* COLOR_TRUE24 */ 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci if((_ASIC_IS_98001 == s->hw->caps.AsicID) || 1650141cc406Sopenharmony_ci (_ASIC_IS_98003 == s->hw->caps.AsicID)) { 1651141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_9800x_list; 1652141cc406Sopenharmony_ci } else { 1653141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_list; 1654141cc406Sopenharmony_ci } 1655141cc406Sopenharmony_ci 1656141cc406Sopenharmony_ci } else { 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci s->hw->dpi_range.min = _TPAMinDpi; 1659141cc406Sopenharmony_ci 1660141cc406Sopenharmony_ci if( s->val[option].w == 1 ) { 1661141cc406Sopenharmony_ci s->hw->x_range.max = SANE_FIX(_TP_X); 1662141cc406Sopenharmony_ci s->hw->y_range.max = SANE_FIX(_TP_Y); 1663141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TP_TLX); 1664141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TP_TLY); 1665141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_TP_BRX); 1666141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_TP_BRY); 1667141cc406Sopenharmony_ci 1668141cc406Sopenharmony_ci } else { 1669141cc406Sopenharmony_ci s->hw->x_range.max = SANE_FIX(_NEG_X); 1670141cc406Sopenharmony_ci s->hw->y_range.max = SANE_FIX(_NEG_Y); 1671141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_NEG_TLX); 1672141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_NEG_TLY); 1673141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_NEG_BRX); 1674141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_NEG_BRY); 1675141cc406Sopenharmony_ci } 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci if( s->hw->caps.dwFlag & SFLAG_TPA ) { 1678141cc406Sopenharmony_ci 1679141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = 1680141cc406Sopenharmony_ci &mode_9800x_list[_TPAModeSupportMin]; 1681141cc406Sopenharmony_ci } else { 1682141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = 1683141cc406Sopenharmony_ci &mode_list[_TPAModeSupportMin]; 1684141cc406Sopenharmony_ci } 1685141cc406Sopenharmony_ci s->val[OPT_MODE].w = 0; /* COLOR_24 is the default */ 1686141cc406Sopenharmony_ci } 1687141cc406Sopenharmony_ci 1688141cc406Sopenharmony_ci s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 1689141cc406Sopenharmony_ci s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 1690141cc406Sopenharmony_ci 1691141cc406Sopenharmony_ci if( NULL != info ) 1692141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1693141cc406Sopenharmony_ci break; 1694141cc406Sopenharmony_ci } 1695141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1696141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1697141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1698141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1699141cc406Sopenharmony_ci memcpy( s->val[option].wa, value, s->opt[option].size ); 1700141cc406Sopenharmony_ci checkGammaSettings(s); 1701141cc406Sopenharmony_ci if( NULL != info ) 1702141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1703141cc406Sopenharmony_ci break; 1704141cc406Sopenharmony_ci 1705141cc406Sopenharmony_ci default: 1706141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1707141cc406Sopenharmony_ci } 1708141cc406Sopenharmony_ci break; 1709141cc406Sopenharmony_ci 1710141cc406Sopenharmony_ci 1711141cc406Sopenharmony_ci default: 1712141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1713141cc406Sopenharmony_ci } 1714141cc406Sopenharmony_ci 1715141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1716141cc406Sopenharmony_ci} 1717141cc406Sopenharmony_ci 1718141cc406Sopenharmony_ci/** according to the option number, return a pointer to a descriptor 1719141cc406Sopenharmony_ci */ 1720141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1721141cc406Sopenharmony_ci sane_get_option_descriptor( SANE_Handle handle, SANE_Int option ) 1722141cc406Sopenharmony_ci{ 1723141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner *)handle; 1724141cc406Sopenharmony_ci 1725141cc406Sopenharmony_ci if((option < 0) || (option >= NUM_OPTIONS)) 1726141cc406Sopenharmony_ci return NULL; 1727141cc406Sopenharmony_ci 1728141cc406Sopenharmony_ci return &(s->opt[option]); 1729141cc406Sopenharmony_ci} 1730141cc406Sopenharmony_ci 1731141cc406Sopenharmony_ci/** return the current parameter settings 1732141cc406Sopenharmony_ci */ 1733141cc406Sopenharmony_ciSANE_Status sane_get_parameters( SANE_Handle handle, SANE_Parameters *params ) 1734141cc406Sopenharmony_ci{ 1735141cc406Sopenharmony_ci int ndpi; 1736141cc406Sopenharmony_ci pModeParam mp; 1737141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner *)handle; 1738141cc406Sopenharmony_ci 1739141cc406Sopenharmony_ci /* if we're calling from within, calc best guess 1740141cc406Sopenharmony_ci * do the same, if sane_get_parameters() is called 1741141cc406Sopenharmony_ci * by a frontend before sane_start() is called 1742141cc406Sopenharmony_ci */ 1743141cc406Sopenharmony_ci if((NULL == params) || (s->scanning != SANE_TRUE)) { 1744141cc406Sopenharmony_ci 1745141cc406Sopenharmony_ci mp = getModeList( s ); 1746141cc406Sopenharmony_ci 1747141cc406Sopenharmony_ci memset( &s->params, 0, sizeof (SANE_Parameters)); 1748141cc406Sopenharmony_ci 1749141cc406Sopenharmony_ci ndpi = s->val[OPT_RESOLUTION].w; 1750141cc406Sopenharmony_ci 1751141cc406Sopenharmony_ci s->params.pixels_per_line = SANE_UNFIX(s->val[OPT_BR_X].w - 1752141cc406Sopenharmony_ci s->val[OPT_TL_X].w) / MM_PER_INCH * ndpi; 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci s->params.lines = SANE_UNFIX( s->val[OPT_BR_Y].w - 1755141cc406Sopenharmony_ci s->val[OPT_TL_Y].w) / MM_PER_INCH * ndpi; 1756141cc406Sopenharmony_ci 1757141cc406Sopenharmony_ci /* pixels_per_line seems to be 8 * n. */ 1758141cc406Sopenharmony_ci /* s->params.pixels_per_line = s->params.pixels_per_line & ~7; debug only */ 1759141cc406Sopenharmony_ci 1760141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 1761141cc406Sopenharmony_ci s->params.depth = mp[s->val[OPT_MODE].w].depth; 1762141cc406Sopenharmony_ci 1763141cc406Sopenharmony_ci if( mp[s->val[OPT_MODE].w].color ) { 1764141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RGB; 1765141cc406Sopenharmony_ci s->params.bytes_per_line = 3 * s->params.pixels_per_line; 1766141cc406Sopenharmony_ci } else { 1767141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 1768141cc406Sopenharmony_ci if (s->params.depth == 1) 1769141cc406Sopenharmony_ci s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; 1770141cc406Sopenharmony_ci else 1771141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line * 1772141cc406Sopenharmony_ci s->params.depth / 8; 1773141cc406Sopenharmony_ci } 1774141cc406Sopenharmony_ci 1775141cc406Sopenharmony_ci /* if sane_get_parameters() was called before sane_start() */ 1776141cc406Sopenharmony_ci /* pass new values to the caller */ 1777141cc406Sopenharmony_ci if ((NULL != params) && (s->scanning != SANE_TRUE)) 1778141cc406Sopenharmony_ci *params = s->params; 1779141cc406Sopenharmony_ci } else 1780141cc406Sopenharmony_ci *params = s->params; 1781141cc406Sopenharmony_ci 1782141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1783141cc406Sopenharmony_ci} 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci/** initiate the scan process 1786141cc406Sopenharmony_ci */ 1787141cc406Sopenharmony_ciSANE_Status sane_start( SANE_Handle handle ) 1788141cc406Sopenharmony_ci{ 1789141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner *) handle; 1790141cc406Sopenharmony_ci pModeParam mp; 1791141cc406Sopenharmony_ci 1792141cc406Sopenharmony_ci int result; 1793141cc406Sopenharmony_ci int ndpi; 1794141cc406Sopenharmony_ci int left, top; 1795141cc406Sopenharmony_ci int width, height; 1796141cc406Sopenharmony_ci int scanmode; 1797141cc406Sopenharmony_ci int fds[2]; 1798141cc406Sopenharmony_ci StartScan start; 1799141cc406Sopenharmony_ci CropInfo crop; 1800141cc406Sopenharmony_ci ScanInfo sinfo; 1801141cc406Sopenharmony_ci SANE_Status status; 1802141cc406Sopenharmony_ci SANE_Word tmp; 1803141cc406Sopenharmony_ci 1804141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_start\n" ); 1805141cc406Sopenharmony_ci 1806141cc406Sopenharmony_ci if( s->scanning ) { 1807141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1808141cc406Sopenharmony_ci } 1809141cc406Sopenharmony_ci 1810141cc406Sopenharmony_ci status = sane_get_parameters (handle, NULL); 1811141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 1812141cc406Sopenharmony_ci DBG( _DBG_ERROR, "sane_get_parameters failed\n" ); 1813141cc406Sopenharmony_ci return status; 1814141cc406Sopenharmony_ci } 1815141cc406Sopenharmony_ci 1816141cc406Sopenharmony_ci /* 1817141cc406Sopenharmony_ci * open the driver and get some information about the scanner 1818141cc406Sopenharmony_ci */ 1819141cc406Sopenharmony_ci s->hw->fd = drvopen( s->hw ); 1820141cc406Sopenharmony_ci if( s->hw->fd < 0 ) { 1821141cc406Sopenharmony_ci DBG( _DBG_ERROR,"sane_start: open failed: %d\n", errno ); 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_ci if( errno == EBUSY ) 1824141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1825141cc406Sopenharmony_ci 1826141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1827141cc406Sopenharmony_ci } 1828141cc406Sopenharmony_ci 1829141cc406Sopenharmony_ci result = s->hw->getCaps( s->hw ); 1830141cc406Sopenharmony_ci if( result < 0 ) { 1831141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->getCaps() failed(%d)\n", result); 1832141cc406Sopenharmony_ci s->hw->close( s->hw ); 1833141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1834141cc406Sopenharmony_ci } 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci result = s->hw->getLensInfo( s->hw, &lens ); 1837141cc406Sopenharmony_ci if( result < 0 ) { 1838141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->getLensInfo() failed(%d)\n", result ); 1839141cc406Sopenharmony_ci s->hw->close( s->hw ); 1840141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1841141cc406Sopenharmony_ci } 1842141cc406Sopenharmony_ci 1843141cc406Sopenharmony_ci /* did we fail on connection? */ 1844141cc406Sopenharmony_ci if ( s->hw->caps.wIOBase == _NO_BASE ) { 1845141cc406Sopenharmony_ci DBG( _DBG_ERROR, "failed to find Plustek scanner\n" ); 1846141cc406Sopenharmony_ci s->hw->close( s->hw ); 1847141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1848141cc406Sopenharmony_ci } 1849141cc406Sopenharmony_ci 1850141cc406Sopenharmony_ci /* All ready to go. Set image def and see what the scanner 1851141cc406Sopenharmony_ci * says for crop info. 1852141cc406Sopenharmony_ci */ 1853141cc406Sopenharmony_ci ndpi = s->val[OPT_RESOLUTION].w; 1854141cc406Sopenharmony_ci 1855141cc406Sopenharmony_ci /* exchange the values as we can't deal with negative heights and so on...*/ 1856141cc406Sopenharmony_ci tmp = s->val[OPT_TL_X].w; 1857141cc406Sopenharmony_ci if( tmp > s->val[OPT_BR_X].w ) { 1858141cc406Sopenharmony_ci DBG( _DBG_INFO, "exchanging BR-X - TL-X\n" ); 1859141cc406Sopenharmony_ci s->val[OPT_TL_X].w = s->val[OPT_BR_X].w; 1860141cc406Sopenharmony_ci s->val[OPT_BR_X].w = tmp; 1861141cc406Sopenharmony_ci } 1862141cc406Sopenharmony_ci 1863141cc406Sopenharmony_ci tmp = s->val[OPT_TL_Y].w; 1864141cc406Sopenharmony_ci if( tmp > s->val[OPT_BR_Y].w ) { 1865141cc406Sopenharmony_ci DBG( _DBG_INFO, "exchanging BR-Y - TL-Y\n" ); 1866141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = s->val[OPT_BR_Y].w; 1867141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = tmp; 1868141cc406Sopenharmony_ci } 1869141cc406Sopenharmony_ci 1870141cc406Sopenharmony_ci /* position and extent are always relative to 300 dpi */ 1871141cc406Sopenharmony_ci left = (int)(SANE_UNFIX (s->val[OPT_TL_X].w)*(double)lens.rDpiX.wPhyMax/ 1872141cc406Sopenharmony_ci (MM_PER_INCH*((double)lens.rDpiX.wPhyMax/300.0))); 1873141cc406Sopenharmony_ci top = (int)(SANE_UNFIX (s->val[OPT_TL_Y].w)*(double)lens.rDpiY.wPhyMax/ 1874141cc406Sopenharmony_ci (MM_PER_INCH*((double)lens.rDpiY.wPhyMax/300.0))); 1875141cc406Sopenharmony_ci width = (int)(SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * 1876141cc406Sopenharmony_ci (double)lens.rDpiX.wPhyMax / 1877141cc406Sopenharmony_ci (MM_PER_INCH *((double)lens.rDpiX.wPhyMax/300.0))); 1878141cc406Sopenharmony_ci height = (int)(SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * 1879141cc406Sopenharmony_ci (double)lens.rDpiY.wPhyMax / 1880141cc406Sopenharmony_ci (MM_PER_INCH *((double)lens.rDpiY.wPhyMax/300.0))); 1881141cc406Sopenharmony_ci 1882141cc406Sopenharmony_ci /* 1883141cc406Sopenharmony_ci * adjust mode list according to the model we use and the 1884141cc406Sopenharmony_ci * source we have 1885141cc406Sopenharmony_ci */ 1886141cc406Sopenharmony_ci mp = getModeList( s ); 1887141cc406Sopenharmony_ci 1888141cc406Sopenharmony_ci scanmode = mp[s->val[OPT_MODE].w].scanmode; 1889141cc406Sopenharmony_ci DBG( _DBG_INFO, "scanmode = %u\n", scanmode ); 1890141cc406Sopenharmony_ci 1891141cc406Sopenharmony_ci /* clear it out just in case */ 1892141cc406Sopenharmony_ci memset (&sinfo, 0, sizeof(sinfo)); 1893141cc406Sopenharmony_ci sinfo.ImgDef.xyDpi.x = ndpi; 1894141cc406Sopenharmony_ci sinfo.ImgDef.xyDpi.y = ndpi; 1895141cc406Sopenharmony_ci sinfo.ImgDef.crArea.x = left; /* offset from left edge to area you want to scan */ 1896141cc406Sopenharmony_ci sinfo.ImgDef.crArea.y = top; /* offset from top edge to area you want to scan */ 1897141cc406Sopenharmony_ci sinfo.ImgDef.crArea.cx = width; /* always relative to 300 dpi */ 1898141cc406Sopenharmony_ci sinfo.ImgDef.crArea.cy = height; 1899141cc406Sopenharmony_ci sinfo.ImgDef.wDataType = scanmode; 1900141cc406Sopenharmony_ci 1901141cc406Sopenharmony_ci/* 1902141cc406Sopenharmony_ci * CHECK: what about the 10 bit mode? 1903141cc406Sopenharmony_ci */ 1904141cc406Sopenharmony_ci#if 0 1905141cc406Sopenharmony_ci if( COLOR_TRUE48 == scanmode ) 1906141cc406Sopenharmony_ci sinfo.ImgDef.wBits = OUTPUT_12Bits; 1907141cc406Sopenharmony_ci else if( COLOR_TRUE32 == scanmode ) 1908141cc406Sopenharmony_ci sinfo.ImgDef.wBits = OUTPUT_10Bits; 1909141cc406Sopenharmony_ci else 1910141cc406Sopenharmony_ci sinfo.ImgDef.wBits = OUTPUT_8Bits; 1911141cc406Sopenharmony_ci#endif 1912141cc406Sopenharmony_ci sinfo.ImgDef.dwFlag = SCANDEF_QualityScan; 1913141cc406Sopenharmony_ci 1914141cc406Sopenharmony_ci switch( s->val[OPT_EXT_MODE].w ) { 1915141cc406Sopenharmony_ci case 1: sinfo.ImgDef.dwFlag |= SCANDEF_Transparency; break; 1916141cc406Sopenharmony_ci case 2: sinfo.ImgDef.dwFlag |= SCANDEF_Negative; break; 1917141cc406Sopenharmony_ci default: break; 1918141cc406Sopenharmony_ci } 1919141cc406Sopenharmony_ci 1920141cc406Sopenharmony_ci /* only for parallel-port devices */ 1921141cc406Sopenharmony_ci if( s->hw->putImgInfo ) { 1922141cc406Sopenharmony_ci result = s->hw->putImgInfo( s->hw, &sinfo.ImgDef ); 1923141cc406Sopenharmony_ci if( result < 0 ) { 1924141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->putImgInfo failed(%d)\n", result ); 1925141cc406Sopenharmony_ci s->hw->close( s->hw ); 1926141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1927141cc406Sopenharmony_ci } 1928141cc406Sopenharmony_ci } else { 1929141cc406Sopenharmony_ci 1930141cc406Sopenharmony_ci memcpy( &(crop.ImgDef), &sinfo.ImgDef, sizeof(ImgDef)); 1931141cc406Sopenharmony_ci 1932141cc406Sopenharmony_ci } 1933141cc406Sopenharmony_ci 1934141cc406Sopenharmony_ci result = s->hw->getCropInfo( s->hw, &crop ); 1935141cc406Sopenharmony_ci if( result < 0 ) { 1936141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->getCropInfo() failed(%d)\n", result ); 1937141cc406Sopenharmony_ci s->hw->close( s->hw ); 1938141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1939141cc406Sopenharmony_ci } 1940141cc406Sopenharmony_ci 1941141cc406Sopenharmony_ci /* DataInf.dwAppPixelsPerLine = crop.dwPixelsPerLine; */ 1942141cc406Sopenharmony_ci s->params.pixels_per_line = crop.dwPixelsPerLine; 1943141cc406Sopenharmony_ci s->params.bytes_per_line = crop.dwBytesPerLine; 1944141cc406Sopenharmony_ci s->params.lines = crop.dwLinesPerArea; 1945141cc406Sopenharmony_ci 1946141cc406Sopenharmony_ci /* build a SCANINFO block and get ready to scan it */ 1947141cc406Sopenharmony_ci sinfo.ImgDef.dwFlag |= (SCANDEF_BuildBwMap | SCANDEF_QualityScan); 1948141cc406Sopenharmony_ci 1949141cc406Sopenharmony_ci /* set adjustments for brightness and contrast */ 1950141cc406Sopenharmony_ci sinfo.siBrightness = s->val[OPT_BRIGHTNESS].w; 1951141cc406Sopenharmony_ci sinfo.siContrast = s->val[OPT_CONTRAST].w; 1952141cc406Sopenharmony_ci sinfo.wDither = s->val[OPT_HALFTONE].w; 1953141cc406Sopenharmony_ci 1954141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "bright %i contrast %i\n", sinfo.siBrightness, 1955141cc406Sopenharmony_ci sinfo.siContrast); 1956141cc406Sopenharmony_ci 1957141cc406Sopenharmony_ci result = s->hw->setScanEnv( s->hw, &sinfo ); 1958141cc406Sopenharmony_ci if( result < 0 ) { 1959141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->setEnv() failed(%d)\n", result ); 1960141cc406Sopenharmony_ci s->hw->close( s->hw ); 1961141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1962141cc406Sopenharmony_ci } 1963141cc406Sopenharmony_ci 1964141cc406Sopenharmony_ci /* download gamma correction tables... */ 1965141cc406Sopenharmony_ci if( scanmode <= COLOR_256GRAY || scanmode == COLOR_GRAY16 ) { 1966141cc406Sopenharmony_ci s->hw->setMap( s->hw, s->gamma_table[0], s->gamma_length, _MAP_MASTER); 1967141cc406Sopenharmony_ci } else { 1968141cc406Sopenharmony_ci s->hw->setMap( s->hw, s->gamma_table[1], s->gamma_length, _MAP_RED ); 1969141cc406Sopenharmony_ci s->hw->setMap( s->hw, s->gamma_table[2], s->gamma_length, _MAP_GREEN ); 1970141cc406Sopenharmony_ci s->hw->setMap( s->hw, s->gamma_table[3], s->gamma_length, _MAP_BLUE ); 1971141cc406Sopenharmony_ci } 1972141cc406Sopenharmony_ci /* work-around for USB... */ 1973141cc406Sopenharmony_ci start.dwLinesPerScan = s->params.lines; 1974141cc406Sopenharmony_ci 1975141cc406Sopenharmony_ci result = s->hw->startScan( s->hw, &start ); 1976141cc406Sopenharmony_ci if( result < 0 ) { 1977141cc406Sopenharmony_ci DBG( _DBG_ERROR, "dev->startScan() failed(%d)\n", result ); 1978141cc406Sopenharmony_ci s->hw->close( s->hw ); 1979141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1980141cc406Sopenharmony_ci } 1981141cc406Sopenharmony_ci 1982141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "dwflag = 0x%lx dwBytesPerLine = %ld, " 1983141cc406Sopenharmony_ci "dwLinesPerScan = %ld\n", 1984141cc406Sopenharmony_ci start.dwFlag, start.dwBytesPerLine, start.dwLinesPerScan); 1985141cc406Sopenharmony_ci 1986141cc406Sopenharmony_ci s->buf = realloc( s->buf, (s->params.lines) * s->params.bytes_per_line ); 1987141cc406Sopenharmony_ci if( NULL == s->buf ) { 1988141cc406Sopenharmony_ci DBG( _DBG_ERROR, "realloc failed\n" ); 1989141cc406Sopenharmony_ci s->hw->close( s->hw ); 1990141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1991141cc406Sopenharmony_ci } 1992141cc406Sopenharmony_ci 1993141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 1994141cc406Sopenharmony_ci 1995141cc406Sopenharmony_ci tsecs = (unsigned long)time(NULL); 1996141cc406Sopenharmony_ci DBG( _DBG_INFO, "TIME START\n" ); 1997141cc406Sopenharmony_ci 1998141cc406Sopenharmony_ci /* 1999141cc406Sopenharmony_ci * everything prepared, so start the child process and a pipe to communicate 2000141cc406Sopenharmony_ci * pipe --> fds[0]=read-fd, fds[1]=write-fd 2001141cc406Sopenharmony_ci */ 2002141cc406Sopenharmony_ci if( pipe(fds) < 0 ) { 2003141cc406Sopenharmony_ci DBG( _DBG_ERROR, "ERROR: could not create pipe\n" ); 2004141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 2005141cc406Sopenharmony_ci s->hw->close( s->hw ); 2006141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2007141cc406Sopenharmony_ci } 2008141cc406Sopenharmony_ci 2009141cc406Sopenharmony_ci /* create reader routine as new process */ 2010141cc406Sopenharmony_ci s->bytes_read = 0; 2011141cc406Sopenharmony_ci s->r_pipe = fds[0]; 2012141cc406Sopenharmony_ci s->w_pipe = fds[1]; 2013141cc406Sopenharmony_ci s->reader_pid = sanei_thread_begin( reader_process, s ); 2014141cc406Sopenharmony_ci 2015141cc406Sopenharmony_ci if(!sanei_thread_is_valid( s->reader_pid )) { 2016141cc406Sopenharmony_ci DBG( _DBG_ERROR, "ERROR: could not create child process\n" ); 2017141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 2018141cc406Sopenharmony_ci s->hw->close( s->hw ); 2019141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2020141cc406Sopenharmony_ci } 2021141cc406Sopenharmony_ci 2022141cc406Sopenharmony_ci /* reader_pid = 0 ===> child process */ 2023141cc406Sopenharmony_ci#if 0 2024141cc406Sopenharmony_ci if( 0 == s->reader_pid ) { 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci sigset_t ignore_set; 2027141cc406Sopenharmony_ci struct SIGACTION act; 2028141cc406Sopenharmony_ci 2029141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "reader process...\n" ); 2030141cc406Sopenharmony_ci 2031141cc406Sopenharmony_ci close(fds[0]); 2032141cc406Sopenharmony_ci 2033141cc406Sopenharmony_ci sigfillset ( &ignore_set ); 2034141cc406Sopenharmony_ci sigdelset ( &ignore_set, SIGTERM ); 2035141cc406Sopenharmony_ci sigprocmask( SIG_SETMASK, &ignore_set, 0 ); 2036141cc406Sopenharmony_ci 2037141cc406Sopenharmony_ci memset ( &act, 0, sizeof (act)); 2038141cc406Sopenharmony_ci sigaction( SIGTERM, &act, 0 ); 2039141cc406Sopenharmony_ci 2040141cc406Sopenharmony_ci status = reader_process( s, fds[1] ); 2041141cc406Sopenharmony_ci 2042141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "reader process done, status = %i\n", status ); 2043141cc406Sopenharmony_ci 2044141cc406Sopenharmony_ci /* don't use exit() since that would run the atexit() handlers */ 2045141cc406Sopenharmony_ci _exit( status ); 2046141cc406Sopenharmony_ci } 2047141cc406Sopenharmony_ci#endif 2048141cc406Sopenharmony_ci signal( SIGCHLD, sig_chldhandler ); 2049141cc406Sopenharmony_ci 2050141cc406Sopenharmony_ci if( sanei_thread_is_forked()) { 2051141cc406Sopenharmony_ci close( s->w_pipe ); 2052141cc406Sopenharmony_ci s->w_pipe = -1; 2053141cc406Sopenharmony_ci } 2054141cc406Sopenharmony_ci 2055141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_start done\n" ); 2056141cc406Sopenharmony_ci 2057141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2058141cc406Sopenharmony_ci} 2059141cc406Sopenharmony_ci 2060141cc406Sopenharmony_ci/** function to read the data from our child process 2061141cc406Sopenharmony_ci */ 2062141cc406Sopenharmony_ciSANE_Status sane_read( SANE_Handle handle, SANE_Byte *data, 2063141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int *length ) 2064141cc406Sopenharmony_ci{ 2065141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner*)handle; 2066141cc406Sopenharmony_ci ssize_t nread; 2067141cc406Sopenharmony_ci 2068141cc406Sopenharmony_ci *length = 0; 2069141cc406Sopenharmony_ci 2070141cc406Sopenharmony_ci /* here we read all data from the driver... */ 2071141cc406Sopenharmony_ci nread = read( s->r_pipe, data, max_length ); 2072141cc406Sopenharmony_ci DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread ); 2073141cc406Sopenharmony_ci if (!(s->scanning)) { 2074141cc406Sopenharmony_ci return do_cancel( s, SANE_TRUE ); 2075141cc406Sopenharmony_ci } 2076141cc406Sopenharmony_ci 2077141cc406Sopenharmony_ci if( nread < 0 ) { 2078141cc406Sopenharmony_ci 2079141cc406Sopenharmony_ci if( EAGAIN == errno ) { 2080141cc406Sopenharmony_ci 2081141cc406Sopenharmony_ci /* if we had already red the picture, so it's okay and stop */ 2082141cc406Sopenharmony_ci if( s->bytes_read == 2083141cc406Sopenharmony_ci (unsigned long)(s->params.lines * s->params.bytes_per_line)) { 2084141cc406Sopenharmony_ci sanei_thread_waitpid( s->reader_pid, 0 ); 2085141cc406Sopenharmony_ci sanei_thread_invalidate( s->reader_pid ); 2086141cc406Sopenharmony_ci drvclose( s->hw ); 2087141cc406Sopenharmony_ci return close_pipe(s); 2088141cc406Sopenharmony_ci } 2089141cc406Sopenharmony_ci 2090141cc406Sopenharmony_ci /* else force the frontend to try again*/ 2091141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2092141cc406Sopenharmony_ci 2093141cc406Sopenharmony_ci } else { 2094141cc406Sopenharmony_ci DBG( _DBG_ERROR, "ERROR: errno=%d\n", errno ); 2095141cc406Sopenharmony_ci do_cancel( s, SANE_TRUE ); 2096141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2097141cc406Sopenharmony_ci } 2098141cc406Sopenharmony_ci } 2099141cc406Sopenharmony_ci 2100141cc406Sopenharmony_ci *length = nread; 2101141cc406Sopenharmony_ci s->bytes_read += nread; 2102141cc406Sopenharmony_ci 2103141cc406Sopenharmony_ci /* nothing red means that we're finished OR we had a problem...*/ 2104141cc406Sopenharmony_ci if( 0 == nread ) { 2105141cc406Sopenharmony_ci 2106141cc406Sopenharmony_ci drvclose( s->hw ); 2107141cc406Sopenharmony_ci s->exit_code = sanei_thread_get_status( s->reader_pid ); 2108141cc406Sopenharmony_ci 2109141cc406Sopenharmony_ci if( SANE_STATUS_GOOD != s->exit_code ) { 2110141cc406Sopenharmony_ci close_pipe(s); 2111141cc406Sopenharmony_ci return s->exit_code; 2112141cc406Sopenharmony_ci } 2113141cc406Sopenharmony_ci sanei_thread_invalidate( s->reader_pid ); 2114141cc406Sopenharmony_ci return close_pipe(s); 2115141cc406Sopenharmony_ci } 2116141cc406Sopenharmony_ci 2117141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2118141cc406Sopenharmony_ci} 2119141cc406Sopenharmony_ci 2120141cc406Sopenharmony_ci/** cancel the scanning process 2121141cc406Sopenharmony_ci */ 2122141cc406Sopenharmony_civoid sane_cancel (SANE_Handle handle) 2123141cc406Sopenharmony_ci{ 2124141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner *)handle; 2125141cc406Sopenharmony_ci 2126141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_cancel\n" ); 2127141cc406Sopenharmony_ci 2128141cc406Sopenharmony_ci if( s->scanning ) 2129141cc406Sopenharmony_ci do_cancel( s, SANE_FALSE ); 2130141cc406Sopenharmony_ci} 2131141cc406Sopenharmony_ci 2132141cc406Sopenharmony_ci/** set the pipe to blocking/non blocking mode 2133141cc406Sopenharmony_ci */ 2134141cc406Sopenharmony_ciSANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 2135141cc406Sopenharmony_ci{ 2136141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner *)handle; 2137141cc406Sopenharmony_ci 2138141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_set_io_mode: non_blocking=%d\n",non_blocking ); 2139141cc406Sopenharmony_ci 2140141cc406Sopenharmony_ci if ( !s->scanning ) { 2141141cc406Sopenharmony_ci DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); 2142141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2143141cc406Sopenharmony_ci } 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_ci if( -1 == s->r_pipe ) { 2146141cc406Sopenharmony_ci DBG( _DBG_ERROR, "ERROR: not supported !\n" ); 2147141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2148141cc406Sopenharmony_ci } 2149141cc406Sopenharmony_ci 2150141cc406Sopenharmony_ci if( fcntl (s->r_pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { 2151141cc406Sopenharmony_ci DBG( _DBG_ERROR, "ERROR: can´t set to non-blocking mode !\n" ); 2152141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2153141cc406Sopenharmony_ci } 2154141cc406Sopenharmony_ci 2155141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_set_io_mode done\n" ); 2156141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2157141cc406Sopenharmony_ci} 2158141cc406Sopenharmony_ci 2159141cc406Sopenharmony_ci/** return the descriptor if available 2160141cc406Sopenharmony_ci */ 2161141cc406Sopenharmony_ciSANE_Status sane_get_select_fd( SANE_Handle handle, SANE_Int * fd ) 2162141cc406Sopenharmony_ci{ 2163141cc406Sopenharmony_ci Plustek_Scanner *s = (Plustek_Scanner *)handle; 2164141cc406Sopenharmony_ci 2165141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_get_select_fd\n" ); 2166141cc406Sopenharmony_ci 2167141cc406Sopenharmony_ci if( !s->scanning ) { 2168141cc406Sopenharmony_ci DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); 2169141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2170141cc406Sopenharmony_ci } 2171141cc406Sopenharmony_ci 2172141cc406Sopenharmony_ci *fd = s->r_pipe; 2173141cc406Sopenharmony_ci 2174141cc406Sopenharmony_ci DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" ); 2175141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2176141cc406Sopenharmony_ci} 2177141cc406Sopenharmony_ci 2178141cc406Sopenharmony_ci/* END PLUSTEK_PP.C .........................................................*/ 2179