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