1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 2000-2003 Jochen Eisinger <jochen.eisinger@gmx.net> 3141cc406Sopenharmony_ci This file is part of the SANE package. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 19141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 22141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 23141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 24141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 25141cc406Sopenharmony_ci account of linking the SANE library code into it. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 28141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 29141cc406Sopenharmony_ci License. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 32141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 33141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 36141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 37141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci This file implements a SANE backend for Mustek PP flatbed scanners. */ 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci#include "../include/sane/config.h" 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci#if defined(HAVE_STDLIB_H) 44141cc406Sopenharmony_ci# include <stdlib.h> 45141cc406Sopenharmony_ci#endif 46141cc406Sopenharmony_ci#include <stdio.h> 47141cc406Sopenharmony_ci#include <ctype.h> 48141cc406Sopenharmony_ci#include <errno.h> 49141cc406Sopenharmony_ci#include <limits.h> 50141cc406Sopenharmony_ci#include <signal.h> 51141cc406Sopenharmony_ci#if defined(HAVE_STRING_H) 52141cc406Sopenharmony_ci# include <string.h> 53141cc406Sopenharmony_ci#elif defined(HAVE_STRINGS_H) 54141cc406Sopenharmony_ci# include <strings.h> 55141cc406Sopenharmony_ci#endif 56141cc406Sopenharmony_ci#if defined(HAVE_UNISTD_H) 57141cc406Sopenharmony_ci# include <unistd.h> 58141cc406Sopenharmony_ci#endif 59141cc406Sopenharmony_ci#include <math.h> 60141cc406Sopenharmony_ci#include <fcntl.h> 61141cc406Sopenharmony_ci#include <time.h> 62141cc406Sopenharmony_ci#if defined(HAVE_SYS_TIME_H) 63141cc406Sopenharmony_ci# include <sys/time.h> 64141cc406Sopenharmony_ci#endif 65141cc406Sopenharmony_ci#if defined(HAVE_SYS_TYPES_H) 66141cc406Sopenharmony_ci# include <sys/types.h> 67141cc406Sopenharmony_ci#endif 68141cc406Sopenharmony_ci#include <sys/wait.h> 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci#define BACKEND_NAME mustek_pp 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci#include "../include/sane/sane.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 74141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 79141cc406Sopenharmony_ci#define MUSTEK_PP_CONFIG_FILE "mustek_pp.conf" 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci#include "../include/sane/sanei_pa4s2.h" 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_ci#include "mustek_pp.h" 84141cc406Sopenharmony_ci#include "mustek_pp_drivers.h" 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci#define MIN(a,b) ((a) < (b) ? (a) : (b)) 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci/* converts millimeter to pixels at a given resolution */ 89141cc406Sopenharmony_ci#define MM_TO_PIXEL(mm, dpi) (((float )mm * 5.0 / 127.0) * (float)dpi) 90141cc406Sopenharmony_ci /* and back */ 91141cc406Sopenharmony_ci#define PIXEL_TO_MM(pixel, dpi) (((float )pixel / (float )dpi) * 127.0 / 5.0) 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci/* if you change the source, please set MUSTEK_PP_STATE to "devel". Do *not* 94141cc406Sopenharmony_ci * change the MUSTEK_PP_BUILD. */ 95141cc406Sopenharmony_ci#define MUSTEK_PP_BUILD 13 96141cc406Sopenharmony_ci#define MUSTEK_PP_STATE "beta" 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci/* auth callback... since basic user authentication is done by saned, this 100141cc406Sopenharmony_ci * callback mechanism isn't used */ 101141cc406Sopenharmony_ciSANE_Auth_Callback sane_auth; 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ci/* count of present devices */ 104141cc406Sopenharmony_cistatic int num_devices = 0; 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci/* list of present devices */ 107141cc406Sopenharmony_cistatic Mustek_pp_Device *devlist = NULL; 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci/* temporary array of configuration options used during device attachment */ 110141cc406Sopenharmony_cistatic Mustek_pp_config_option *cfgoptions = NULL; 111141cc406Sopenharmony_cistatic int numcfgoptions = 0; 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci/* list of pointers to the SANE_Device structures of the Mustek_pp_Devices */ 114141cc406Sopenharmony_cistatic SANE_Device **devarray = NULL; 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci/* currently active Handles */ 117141cc406Sopenharmony_cistatic Mustek_pp_Handle *first_hndl = NULL; 118141cc406Sopenharmony_ci 119141cc406Sopenharmony_cistatic SANE_String_Const mustek_pp_modes[4] = {SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL}; 120141cc406Sopenharmony_cistatic SANE_Word mustek_pp_modes_size = 10; 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_cistatic SANE_String_Const mustek_pp_speeds[6] = {"Slowest", "Slower", "Normal", "Faster", "Fastest", NULL}; 123141cc406Sopenharmony_cistatic SANE_Word mustek_pp_speeds_size = 8; 124141cc406Sopenharmony_cistatic SANE_Word mustek_pp_depths[5] = {4, 8, 10, 12, 16}; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci/* prototypes */ 127141cc406Sopenharmony_cistatic void free_cfg_options(int *numoptions, Mustek_pp_config_option** options); 128141cc406Sopenharmony_cistatic SANE_Status do_eof(Mustek_pp_Handle *hndl); 129141cc406Sopenharmony_cistatic SANE_Status do_stop(Mustek_pp_Handle *hndl); 130141cc406Sopenharmony_cistatic int reader_process (Mustek_pp_Handle * hndl, int pipe); 131141cc406Sopenharmony_cistatic SANE_Status sane_attach(SANE_String_Const port, SANE_String_Const name, 132141cc406Sopenharmony_ci SANE_Int driver, SANE_Int info); 133141cc406Sopenharmony_cistatic void init_options(Mustek_pp_Handle *hndl); 134141cc406Sopenharmony_cistatic void attach_device(SANE_String *driver, SANE_String *name, 135141cc406Sopenharmony_ci SANE_String *port, SANE_String *option_ta); 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci/* 139141cc406Sopenharmony_ci * Auxiliary function for freeing arrays of configuration options, 140141cc406Sopenharmony_ci */ 141141cc406Sopenharmony_cistatic void 142141cc406Sopenharmony_cifree_cfg_options(int *numoptions, Mustek_pp_config_option** options) 143141cc406Sopenharmony_ci{ 144141cc406Sopenharmony_ci int i; 145141cc406Sopenharmony_ci if (*numoptions) 146141cc406Sopenharmony_ci { 147141cc406Sopenharmony_ci for (i=0; i<*numoptions; ++i) 148141cc406Sopenharmony_ci { 149141cc406Sopenharmony_ci free ((*options)[i].name); 150141cc406Sopenharmony_ci free ((*options)[i].value); 151141cc406Sopenharmony_ci } 152141cc406Sopenharmony_ci free (*options); 153141cc406Sopenharmony_ci } 154141cc406Sopenharmony_ci *options = NULL; 155141cc406Sopenharmony_ci *numoptions = 0; 156141cc406Sopenharmony_ci} 157141cc406Sopenharmony_ci 158141cc406Sopenharmony_ci/* do_eof: 159141cc406Sopenharmony_ci * closes the pipeline 160141cc406Sopenharmony_ci * 161141cc406Sopenharmony_ci * Description: 162141cc406Sopenharmony_ci * closes the pipe (read-only end) 163141cc406Sopenharmony_ci */ 164141cc406Sopenharmony_cistatic SANE_Status 165141cc406Sopenharmony_cido_eof (Mustek_pp_Handle *hndl) 166141cc406Sopenharmony_ci{ 167141cc406Sopenharmony_ci if (hndl->pipe >= 0) { 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci close (hndl->pipe); 170141cc406Sopenharmony_ci hndl->pipe = -1; 171141cc406Sopenharmony_ci } 172141cc406Sopenharmony_ci 173141cc406Sopenharmony_ci return SANE_STATUS_EOF; 174141cc406Sopenharmony_ci} 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci/* do_stop: 177141cc406Sopenharmony_ci * ends the reader_process and stops the scanner 178141cc406Sopenharmony_ci * 179141cc406Sopenharmony_ci * Description: 180141cc406Sopenharmony_ci * kills the reader process with a SIGTERM and cancels the scanner 181141cc406Sopenharmony_ci */ 182141cc406Sopenharmony_cistatic SANE_Status 183141cc406Sopenharmony_cido_stop(Mustek_pp_Handle *hndl) 184141cc406Sopenharmony_ci{ 185141cc406Sopenharmony_ci 186141cc406Sopenharmony_ci int exit_status; 187141cc406Sopenharmony_ci 188141cc406Sopenharmony_ci do_eof (hndl); 189141cc406Sopenharmony_ci 190141cc406Sopenharmony_ci if (hndl->reader > 0) { 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci DBG (3, "do_stop: terminating reader process\n"); 193141cc406Sopenharmony_ci kill (hndl->reader, SIGTERM); 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ci while (wait (&exit_status) != hndl->reader); 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_ci DBG ((exit_status == SANE_STATUS_GOOD ? 3 : 1), 198141cc406Sopenharmony_ci "do_stop: reader_process terminated with status ``%s''\n", 199141cc406Sopenharmony_ci sane_strstatus(exit_status)); 200141cc406Sopenharmony_ci hndl->reader = 0; 201141cc406Sopenharmony_ci hndl->dev->func->stop (hndl); 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci return exit_status; 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci } 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci hndl->dev->func->stop (hndl); 208141cc406Sopenharmony_ci 209141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 210141cc406Sopenharmony_ci} 211141cc406Sopenharmony_ci 212141cc406Sopenharmony_ci/* sigterm_handler: 213141cc406Sopenharmony_ci * cancel scanner when receiving a SIGTERM 214141cc406Sopenharmony_ci * 215141cc406Sopenharmony_ci * Description: 216141cc406Sopenharmony_ci * just exit... reader_process takes care that nothing bad will happen 217141cc406Sopenharmony_ci * 218141cc406Sopenharmony_ci * EDG - Jan 14, 2004: 219141cc406Sopenharmony_ci * Make sure that the parport is released again by the child process 220141cc406Sopenharmony_ci * under all circumstances, because otherwise the parent process may no 221141cc406Sopenharmony_ci * longer be able to claim it (they share the same file descriptor, and 222141cc406Sopenharmony_ci * the kernel doesn't release the child's claim because the file 223141cc406Sopenharmony_ci * descriptor isn't cleaned up). If that would happen, the lamp may stay 224141cc406Sopenharmony_ci * on and may not return to its home position, unless the scanner 225141cc406Sopenharmony_ci * frontend is restarted. 226141cc406Sopenharmony_ci * (This happens only when sanei_pa4s2 uses libieee1284 AND 227141cc406Sopenharmony_ci * libieee1284 goes via /dev/parportX). 228141cc406Sopenharmony_ci * 229141cc406Sopenharmony_ci */ 230141cc406Sopenharmony_cistatic int fd_to_release = 0; 231141cc406Sopenharmony_ci/*ARGSUSED*/ 232141cc406Sopenharmony_cistatic void 233141cc406Sopenharmony_cisigterm_handler (int signal __UNUSED__) 234141cc406Sopenharmony_ci{ 235141cc406Sopenharmony_ci sanei_pa4s2_enable(fd_to_release, SANE_FALSE); 236141cc406Sopenharmony_ci _exit (SANE_STATUS_GOOD); 237141cc406Sopenharmony_ci} 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci/* reader_process: 240141cc406Sopenharmony_ci * receives data from the scanner and stuff it into the pipeline 241141cc406Sopenharmony_ci * 242141cc406Sopenharmony_ci * Description: 243141cc406Sopenharmony_ci * The signal handle for SIGTERM is initialized. 244141cc406Sopenharmony_ci * 245141cc406Sopenharmony_ci */ 246141cc406Sopenharmony_cistatic int 247141cc406Sopenharmony_cireader_process (Mustek_pp_Handle * hndl, int pipe) 248141cc406Sopenharmony_ci{ 249141cc406Sopenharmony_ci sigset_t sigterm_set; 250141cc406Sopenharmony_ci struct SIGACTION act; 251141cc406Sopenharmony_ci FILE *fp; 252141cc406Sopenharmony_ci SANE_Status status; 253141cc406Sopenharmony_ci int line; 254141cc406Sopenharmony_ci int size, elem; 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_ci SANE_Byte *buffer; 257141cc406Sopenharmony_ci 258141cc406Sopenharmony_ci sigemptyset (&sigterm_set); 259141cc406Sopenharmony_ci sigaddset (&sigterm_set, SIGTERM); 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci if (!(buffer = malloc (hndl->params.bytes_per_line))) 262141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 263141cc406Sopenharmony_ci 264141cc406Sopenharmony_ci if (!(fp = fdopen(pipe, "w"))) 265141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci fd_to_release = hndl->fd; 268141cc406Sopenharmony_ci memset (&act, 0, sizeof(act)); 269141cc406Sopenharmony_ci act.sa_handler = sigterm_handler; 270141cc406Sopenharmony_ci sigaction (SIGTERM, &act, NULL); 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_ci if ((status = hndl->dev->func->start (hndl)) != SANE_STATUS_GOOD) 273141cc406Sopenharmony_ci return status; 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci size = hndl->params.bytes_per_line; 276141cc406Sopenharmony_ci elem = 1; 277141cc406Sopenharmony_ci 278141cc406Sopenharmony_ci for (line=0; line<hndl->params.lines ; line++) { 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci sigprocmask (SIG_BLOCK, &sigterm_set, NULL); 281141cc406Sopenharmony_ci 282141cc406Sopenharmony_ci hndl->dev->func->read (hndl, buffer); 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci if (getppid() == 1) { 285141cc406Sopenharmony_ci /* The parent process has died. Stop the scan (to make 286141cc406Sopenharmony_ci sure that the lamp is off and returns home). This is 287141cc406Sopenharmony_ci a safety measure to make sure that we don't break 288141cc406Sopenharmony_ci the scanner in case the frontend crashes. */ 289141cc406Sopenharmony_ci DBG (1, "reader_process: front-end died; aborting.\n"); 290141cc406Sopenharmony_ci hndl->dev->func->stop (hndl); 291141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 292141cc406Sopenharmony_ci } 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci sigprocmask (SIG_UNBLOCK, &sigterm_set, NULL); 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci fwrite (buffer, size, elem, fp); 297141cc406Sopenharmony_ci } 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci fclose (fp); 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci free (buffer); 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 304141cc406Sopenharmony_ci} 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci/* sane_attach: 309141cc406Sopenharmony_ci * adds a new entry to the Mustek_pp_Device *devlist list 310141cc406Sopenharmony_ci * 311141cc406Sopenharmony_ci * Description: 312141cc406Sopenharmony_ci * After memory for a new device entry is allocated, the 313141cc406Sopenharmony_ci * parameters for the device are determined by a call to 314141cc406Sopenharmony_ci * capabilities(). 315141cc406Sopenharmony_ci * 316141cc406Sopenharmony_ci * Afterwards the new device entry is inserted into the 317141cc406Sopenharmony_ci * devlist 318141cc406Sopenharmony_ci * 319141cc406Sopenharmony_ci */ 320141cc406Sopenharmony_cistatic SANE_Status 321141cc406Sopenharmony_cisane_attach (SANE_String_Const port, SANE_String_Const name, SANE_Int driver, SANE_Int info) 322141cc406Sopenharmony_ci{ 323141cc406Sopenharmony_ci Mustek_pp_Device *dev; 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci DBG (3, "sane_attach: attaching device ``%s'' to port %s (driver %s v%s by %s)\n", 326141cc406Sopenharmony_ci name, port, Mustek_pp_Drivers[driver].driver, 327141cc406Sopenharmony_ci Mustek_pp_Drivers[driver].version, 328141cc406Sopenharmony_ci Mustek_pp_Drivers[driver].author); 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci if ((dev = malloc (sizeof (Mustek_pp_Device))) == NULL) { 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci DBG (1, "sane_attach: not enough free memory\n"); 333141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_ci } 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_ci memset (dev, 0, sizeof (Mustek_pp_Device)); 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci memset (&dev->sane, 0, sizeof (SANE_Device)); 340141cc406Sopenharmony_ci 341141cc406Sopenharmony_ci dev->func = &Mustek_pp_Drivers[driver]; 342141cc406Sopenharmony_ci 343141cc406Sopenharmony_ci dev->sane.name = dev->name = strdup (name); 344141cc406Sopenharmony_ci dev->port = strdup (port); 345141cc406Sopenharmony_ci dev->info = info; /* Modified by EDG */ 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci /* Transfer the options parsed from the configuration file */ 348141cc406Sopenharmony_ci dev->numcfgoptions = numcfgoptions; 349141cc406Sopenharmony_ci dev->cfgoptions = cfgoptions; 350141cc406Sopenharmony_ci numcfgoptions = 0; 351141cc406Sopenharmony_ci cfgoptions = NULL; 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci dev->func->capabilities (info, &dev->model, &dev->vendor, &dev->type, 354141cc406Sopenharmony_ci &dev->maxres, &dev->minres, &dev->maxhsize, &dev->maxvsize, 355141cc406Sopenharmony_ci &dev->caps); 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci dev->sane.model = dev->model; 358141cc406Sopenharmony_ci dev->sane.vendor = dev->vendor; 359141cc406Sopenharmony_ci dev->sane.type = dev->type; 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci dev->next = devlist; 362141cc406Sopenharmony_ci devlist = dev; 363141cc406Sopenharmony_ci 364141cc406Sopenharmony_ci num_devices++; 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 367141cc406Sopenharmony_ci} 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci 370141cc406Sopenharmony_ci/* init_options: 371141cc406Sopenharmony_ci * Sets up the option descriptors for a device 372141cc406Sopenharmony_ci * 373141cc406Sopenharmony_ci * Description: 374141cc406Sopenharmony_ci */ 375141cc406Sopenharmony_cistatic void 376141cc406Sopenharmony_ciinit_options(Mustek_pp_Handle *hndl) 377141cc406Sopenharmony_ci{ 378141cc406Sopenharmony_ci int i; 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci memset (hndl->opt, 0, sizeof (hndl->opt)); 381141cc406Sopenharmony_ci memset (hndl->val, 0, sizeof (hndl->val)); 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 384141cc406Sopenharmony_ci { 385141cc406Sopenharmony_ci hndl->opt[i].size = sizeof (SANE_Word); 386141cc406Sopenharmony_ci hndl->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 387141cc406Sopenharmony_ci } 388141cc406Sopenharmony_ci 389141cc406Sopenharmony_ci hndl->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 390141cc406Sopenharmony_ci hndl->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 391141cc406Sopenharmony_ci hndl->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 392141cc406Sopenharmony_ci hndl->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 393141cc406Sopenharmony_ci hndl->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 394141cc406Sopenharmony_ci hndl->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci /* "Mode" group: */ 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci hndl->opt[OPT_MODE_GROUP].title = "Scan Mode"; 399141cc406Sopenharmony_ci hndl->opt[OPT_MODE_GROUP].desc = ""; 400141cc406Sopenharmony_ci hndl->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 401141cc406Sopenharmony_ci hndl->opt[OPT_MODE_GROUP].cap = 0; 402141cc406Sopenharmony_ci hndl->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 403141cc406Sopenharmony_ci hndl->opt[OPT_MODE_GROUP].size = 0; 404141cc406Sopenharmony_ci 405141cc406Sopenharmony_ci /* scan mode */ 406141cc406Sopenharmony_ci hndl->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 407141cc406Sopenharmony_ci hndl->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 408141cc406Sopenharmony_ci hndl->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 409141cc406Sopenharmony_ci hndl->opt[OPT_MODE].type = SANE_TYPE_STRING; 410141cc406Sopenharmony_ci hndl->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 411141cc406Sopenharmony_ci hndl->opt[OPT_MODE].size = mustek_pp_modes_size; 412141cc406Sopenharmony_ci hndl->opt[OPT_MODE].constraint.string_list = mustek_pp_modes; 413141cc406Sopenharmony_ci hndl->val[OPT_MODE].s = strdup (mustek_pp_modes[2]); 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci /* resolution */ 416141cc406Sopenharmony_ci hndl->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 417141cc406Sopenharmony_ci hndl->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 418141cc406Sopenharmony_ci hndl->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 419141cc406Sopenharmony_ci hndl->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; 420141cc406Sopenharmony_ci hndl->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 421141cc406Sopenharmony_ci hndl->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 422141cc406Sopenharmony_ci hndl->opt[OPT_RESOLUTION].constraint.range = &hndl->dpi_range; 423141cc406Sopenharmony_ci hndl->val[OPT_RESOLUTION].w = SANE_FIX (hndl->dev->minres); 424141cc406Sopenharmony_ci hndl->dpi_range.min = SANE_FIX (hndl->dev->minres); 425141cc406Sopenharmony_ci hndl->dpi_range.max = SANE_FIX (hndl->dev->maxres); 426141cc406Sopenharmony_ci hndl->dpi_range.quant = SANE_FIX (1); 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci /* speed */ 429141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; 430141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; 431141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; 432141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].type = SANE_TYPE_STRING; 433141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].size = mustek_pp_speeds_size; 434141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST; 435141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].constraint.string_list = mustek_pp_speeds; 436141cc406Sopenharmony_ci hndl->val[OPT_SPEED].s = strdup (mustek_pp_speeds[2]); 437141cc406Sopenharmony_ci 438141cc406Sopenharmony_ci if (! (hndl->dev->caps & CAP_SPEED_SELECT)) 439141cc406Sopenharmony_ci hndl->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE; 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci /* preview */ 442141cc406Sopenharmony_ci hndl->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 443141cc406Sopenharmony_ci hndl->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 444141cc406Sopenharmony_ci hndl->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 445141cc406Sopenharmony_ci hndl->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 446141cc406Sopenharmony_ci hndl->val[OPT_PREVIEW].w = SANE_FALSE; 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci /* gray preview */ 449141cc406Sopenharmony_ci hndl->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; 450141cc406Sopenharmony_ci hndl->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; 451141cc406Sopenharmony_ci hndl->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; 452141cc406Sopenharmony_ci hndl->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; 453141cc406Sopenharmony_ci hndl->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci /* color dept */ 456141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; 457141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH; 458141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].desc = 459141cc406Sopenharmony_ci "Number of bits per sample for color scans, typical values are 8 for truecolor (24bpp)" 460141cc406Sopenharmony_ci "up to 16 for far-to-many-color (48bpp)."; 461141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].type = SANE_TYPE_INT; 462141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; 463141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].constraint.word_list = mustek_pp_depths; 464141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; 465141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].size = sizeof(SANE_Word); 466141cc406Sopenharmony_ci hndl->val[OPT_DEPTH].w = 8; 467141cc406Sopenharmony_ci 468141cc406Sopenharmony_ci if ( !(hndl->dev->caps & CAP_DEPTH)) 469141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci /* "Geometry" group: */ 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci hndl->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; 475141cc406Sopenharmony_ci hndl->opt[OPT_GEOMETRY_GROUP].desc = ""; 476141cc406Sopenharmony_ci hndl->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 477141cc406Sopenharmony_ci hndl->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 478141cc406Sopenharmony_ci hndl->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 479141cc406Sopenharmony_ci hndl->opt[OPT_GEOMETRY_GROUP].size = 0; 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci /* top-left x */ 482141cc406Sopenharmony_ci hndl->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 483141cc406Sopenharmony_ci hndl->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 484141cc406Sopenharmony_ci hndl->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 485141cc406Sopenharmony_ci hndl->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 486141cc406Sopenharmony_ci hndl->opt[OPT_TL_X].unit = SANE_UNIT_MM; 487141cc406Sopenharmony_ci hndl->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 488141cc406Sopenharmony_ci hndl->opt[OPT_TL_X].constraint.range = &hndl->x_range; 489141cc406Sopenharmony_ci hndl->x_range.min = SANE_FIX (0); 490141cc406Sopenharmony_ci hndl->x_range.max = SANE_FIX (PIXEL_TO_MM(hndl->dev->maxhsize,hndl->dev->maxres)); 491141cc406Sopenharmony_ci hndl->x_range.quant = 0; 492141cc406Sopenharmony_ci hndl->val[OPT_TL_X].w = hndl->x_range.min; 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci /* top-left y */ 495141cc406Sopenharmony_ci hndl->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 496141cc406Sopenharmony_ci hndl->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 497141cc406Sopenharmony_ci hndl->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 498141cc406Sopenharmony_ci hndl->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 499141cc406Sopenharmony_ci hndl->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 500141cc406Sopenharmony_ci hndl->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 501141cc406Sopenharmony_ci hndl->opt[OPT_TL_Y].constraint.range = &hndl->y_range; 502141cc406Sopenharmony_ci hndl->y_range.min = SANE_FIX(0); 503141cc406Sopenharmony_ci hndl->y_range.max = SANE_FIX(PIXEL_TO_MM(hndl->dev->maxvsize,hndl->dev->maxres)); 504141cc406Sopenharmony_ci hndl->y_range.quant = 0; 505141cc406Sopenharmony_ci hndl->val[OPT_TL_Y].w = hndl->y_range.min; 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci /* bottom-right x */ 508141cc406Sopenharmony_ci hndl->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 509141cc406Sopenharmony_ci hndl->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 510141cc406Sopenharmony_ci hndl->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 511141cc406Sopenharmony_ci hndl->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 512141cc406Sopenharmony_ci hndl->opt[OPT_BR_X].unit = SANE_UNIT_MM; 513141cc406Sopenharmony_ci hndl->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 514141cc406Sopenharmony_ci hndl->opt[OPT_BR_X].constraint.range = &hndl->x_range; 515141cc406Sopenharmony_ci hndl->val[OPT_BR_X].w = hndl->x_range.max; 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci /* bottom-right y */ 518141cc406Sopenharmony_ci hndl->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 519141cc406Sopenharmony_ci hndl->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 520141cc406Sopenharmony_ci hndl->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 521141cc406Sopenharmony_ci hndl->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 522141cc406Sopenharmony_ci hndl->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 523141cc406Sopenharmony_ci hndl->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 524141cc406Sopenharmony_ci hndl->opt[OPT_BR_Y].constraint.range = &hndl->y_range; 525141cc406Sopenharmony_ci hndl->val[OPT_BR_Y].w = hndl->y_range.max; 526141cc406Sopenharmony_ci 527141cc406Sopenharmony_ci /* "Enhancement" group: */ 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci hndl->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; 530141cc406Sopenharmony_ci hndl->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 531141cc406Sopenharmony_ci hndl->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 532141cc406Sopenharmony_ci hndl->opt[OPT_ENHANCEMENT_GROUP].cap = 0; 533141cc406Sopenharmony_ci hndl->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 534141cc406Sopenharmony_ci hndl->opt[OPT_ENHANCEMENT_GROUP].size = 0; 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci /* custom-gamma table */ 538141cc406Sopenharmony_ci hndl->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 539141cc406Sopenharmony_ci hndl->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 540141cc406Sopenharmony_ci hndl->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 541141cc406Sopenharmony_ci hndl->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 542141cc406Sopenharmony_ci hndl->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 543141cc406Sopenharmony_ci 544141cc406Sopenharmony_ci if ( !(hndl->dev->caps & CAP_GAMMA_CORRECT)) 545141cc406Sopenharmony_ci hndl->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 546141cc406Sopenharmony_ci 547141cc406Sopenharmony_ci /* grayscale gamma vector */ 548141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 549141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 550141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 551141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 552141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 553141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 554141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); 555141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 556141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].constraint.range = &hndl->gamma_range; 557141cc406Sopenharmony_ci hndl->val[OPT_GAMMA_VECTOR].wa = &hndl->gamma_table[0][0]; 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci /* red gamma vector */ 560141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 561141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 562141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 563141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 564141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 565141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 566141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); 567141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 568141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].constraint.range = &hndl->gamma_range; 569141cc406Sopenharmony_ci hndl->val[OPT_GAMMA_VECTOR_R].wa = &hndl->gamma_table[1][0]; 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci /* green gamma vector */ 572141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 573141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 574141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 575141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 576141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 577141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 578141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); 579141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 580141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].constraint.range = &hndl->gamma_range; 581141cc406Sopenharmony_ci hndl->val[OPT_GAMMA_VECTOR_G].wa = &hndl->gamma_table[2][0]; 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci /* blue gamma vector */ 584141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 585141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 586141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 587141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 588141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 589141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 590141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); 591141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 592141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].constraint.range = &hndl->gamma_range; 593141cc406Sopenharmony_ci hndl->val[OPT_GAMMA_VECTOR_B].wa = &hndl->gamma_table[3][0]; 594141cc406Sopenharmony_ci 595141cc406Sopenharmony_ci hndl->gamma_range.min = 0; 596141cc406Sopenharmony_ci hndl->gamma_range.max = 255; 597141cc406Sopenharmony_ci hndl->gamma_range.quant = 1; 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci hndl->opt[OPT_INVERT].name = SANE_NAME_NEGATIVE; 600141cc406Sopenharmony_ci hndl->opt[OPT_INVERT].title = SANE_TITLE_NEGATIVE; 601141cc406Sopenharmony_ci hndl->opt[OPT_INVERT].desc = SANE_DESC_NEGATIVE; 602141cc406Sopenharmony_ci hndl->opt[OPT_INVERT].type = SANE_TYPE_BOOL; 603141cc406Sopenharmony_ci hndl->val[OPT_INVERT].w = SANE_FALSE; 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci if (! (hndl->dev->caps & CAP_INVERT)) 606141cc406Sopenharmony_ci hndl->opt[OPT_INVERT].cap |= SANE_CAP_INACTIVE; 607141cc406Sopenharmony_ci 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci} 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci/* attach_device: 612141cc406Sopenharmony_ci * Attempts to attach a device to the list after parsing of a section 613141cc406Sopenharmony_ci * of the configuration file. 614141cc406Sopenharmony_ci * 615141cc406Sopenharmony_ci * Description: 616141cc406Sopenharmony_ci * After parsing a scanner section of the config file, this function 617141cc406Sopenharmony_ci * is called to look for a driver with a matching name. When found, 618141cc406Sopenharmony_ci * this driver is called to initialize the device. 619141cc406Sopenharmony_ci */ 620141cc406Sopenharmony_cistatic void 621141cc406Sopenharmony_ciattach_device(SANE_String *driver, SANE_String *name, 622141cc406Sopenharmony_ci SANE_String *port, SANE_String *option_ta) 623141cc406Sopenharmony_ci{ 624141cc406Sopenharmony_ci int found = 0, driver_no, port_no; 625141cc406Sopenharmony_ci const char **ports; 626141cc406Sopenharmony_ci 627141cc406Sopenharmony_ci if (!strcmp (*port, "*")) 628141cc406Sopenharmony_ci { 629141cc406Sopenharmony_ci ports = sanei_pa4s2_devices(); 630141cc406Sopenharmony_ci DBG (3, "sanei_init: auto probing port\n"); 631141cc406Sopenharmony_ci } 632141cc406Sopenharmony_ci else 633141cc406Sopenharmony_ci { 634141cc406Sopenharmony_ci ports = malloc (sizeof(char *) * 2); 635141cc406Sopenharmony_ci ports[0] = *port; 636141cc406Sopenharmony_ci ports[1] = NULL; 637141cc406Sopenharmony_ci } 638141cc406Sopenharmony_ci 639141cc406Sopenharmony_ci for (port_no=0; ports[port_no] != NULL; port_no++) 640141cc406Sopenharmony_ci { 641141cc406Sopenharmony_ci for (driver_no=0 ; driver_no<MUSTEK_PP_NUM_DRIVERS ; driver_no++) 642141cc406Sopenharmony_ci { 643141cc406Sopenharmony_ci if (strcasecmp (Mustek_pp_Drivers[driver_no].driver, *driver) == 0) 644141cc406Sopenharmony_ci { 645141cc406Sopenharmony_ci Mustek_pp_Drivers[driver_no].init ( 646141cc406Sopenharmony_ci (*option_ta == 0 ? CAP_NOTHING : CAP_TA), 647141cc406Sopenharmony_ci ports[port_no], *name, sane_attach); 648141cc406Sopenharmony_ci found = 1; 649141cc406Sopenharmony_ci break; 650141cc406Sopenharmony_ci } 651141cc406Sopenharmony_ci } 652141cc406Sopenharmony_ci } 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci free (ports); 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci if (found == 0) 657141cc406Sopenharmony_ci { 658141cc406Sopenharmony_ci DBG (1, "sane_init: no scanner detected\n"); 659141cc406Sopenharmony_ci DBG (3, "sane_init: either the driver name ``%s'' is invalid, or no scanner was detected\n", *driver); 660141cc406Sopenharmony_ci } 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_ci free (*name); 663141cc406Sopenharmony_ci free (*port); 664141cc406Sopenharmony_ci free (*driver); 665141cc406Sopenharmony_ci if (*option_ta) 666141cc406Sopenharmony_ci free (*option_ta); 667141cc406Sopenharmony_ci *name = *port = *driver = *option_ta = 0; 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci /* In case of a successful initialization, the configuration options 670141cc406Sopenharmony_ci should have been transferred to the device, but this function can 671141cc406Sopenharmony_ci deal with that. */ 672141cc406Sopenharmony_ci free_cfg_options(&numcfgoptions, &cfgoptions); 673141cc406Sopenharmony_ci} 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ci/* sane_init: 676141cc406Sopenharmony_ci * Reads configuration file and registers hardware driver 677141cc406Sopenharmony_ci * 678141cc406Sopenharmony_ci * Description: 679141cc406Sopenharmony_ci * in *version_code the SANE version this backend was compiled with and the 680141cc406Sopenharmony_ci * version of the backend is returned. The value of authorize is stored in 681141cc406Sopenharmony_ci * the global variable sane_auth. 682141cc406Sopenharmony_ci * 683141cc406Sopenharmony_ci * Next the configuration file is read. If it isn't present, all drivers 684141cc406Sopenharmony_ci * are auto-probed with default values (port 0x378, with and without TA). 685141cc406Sopenharmony_ci * 686141cc406Sopenharmony_ci * The configuration file is expected to contain lines of the form 687141cc406Sopenharmony_ci * 688141cc406Sopenharmony_ci * scanner <name> <port> <driver> [<option_ta>] 689141cc406Sopenharmony_ci * 690141cc406Sopenharmony_ci * where <name> is a arbitrary name to identify this entry 691141cc406Sopenharmony_ci * <port> is the port where the scanner is attached to 692141cc406Sopenharmony_ci * <driver> is the name of the driver to use 693141cc406Sopenharmony_ci * 694141cc406Sopenharmony_ci * if the optional argument "option_ta" is present the driver uses special 695141cc406Sopenharmony_ci * parameters fitting for a transparency adapter. 696141cc406Sopenharmony_ci */ 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ciSANE_Status 699141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 700141cc406Sopenharmony_ci{ 701141cc406Sopenharmony_ci FILE *fp; 702141cc406Sopenharmony_ci char config_line[1024]; 703141cc406Sopenharmony_ci const char *config_line_ptr; 704141cc406Sopenharmony_ci int line=0, driver_no; 705141cc406Sopenharmony_ci char *driver = 0, *port = 0, *name = 0, *option_ta = 0; 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci DBG_INIT (); 708141cc406Sopenharmony_ci DBG (3, "sane-mustek_pp, version 0.%d-%s. build for SANE %s\n", 709141cc406Sopenharmony_ci MUSTEK_PP_BUILD, MUSTEK_PP_STATE, VERSION); 710141cc406Sopenharmony_ci DBG (3, "backend by Jochen Eisinger <jochen.eisinger@gmx.net>\n"); 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci if (version_code != NULL) 713141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, MUSTEK_PP_BUILD); 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci sane_auth = authorize; 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci fp = sanei_config_open (MUSTEK_PP_CONFIG_FILE); 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci if (fp == NULL) 721141cc406Sopenharmony_ci { 722141cc406Sopenharmony_ci char driver_name[64]; 723141cc406Sopenharmony_ci const char **devices = sanei_pa4s2_devices(); 724141cc406Sopenharmony_ci int device_no; 725141cc406Sopenharmony_ci 726141cc406Sopenharmony_ci DBG (2, "sane_init: could not open configuration file\n"); 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci for (device_no = 0; devices[device_no] != NULL; device_no++) 729141cc406Sopenharmony_ci { 730141cc406Sopenharmony_ci DBG (3, "sane_init: trying ``%s''\n", devices[device_no]); 731141cc406Sopenharmony_ci for (driver_no=0 ; driver_no<MUSTEK_PP_NUM_DRIVERS ; driver_no++) 732141cc406Sopenharmony_ci { 733141cc406Sopenharmony_ci Mustek_pp_Drivers[driver_no].init(CAP_NOTHING, devices[device_no], 734141cc406Sopenharmony_ci Mustek_pp_Drivers[driver_no].driver, sane_attach); 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci snprintf (driver_name, 64, "%s-ta", 737141cc406Sopenharmony_ci Mustek_pp_Drivers[driver_no].driver); 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci Mustek_pp_Drivers[driver_no].init(CAP_TA, devices[device_no], 740141cc406Sopenharmony_ci driver_name, sane_attach); 741141cc406Sopenharmony_ci } 742141cc406Sopenharmony_ci } 743141cc406Sopenharmony_ci 744141cc406Sopenharmony_ci free (devices); 745141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 746141cc406Sopenharmony_ci } 747141cc406Sopenharmony_ci 748141cc406Sopenharmony_ci while (sanei_config_read (config_line, 1023, fp)) 749141cc406Sopenharmony_ci { 750141cc406Sopenharmony_ci line++; 751141cc406Sopenharmony_ci if ((!*config_line) || (*config_line == '#')) 752141cc406Sopenharmony_ci continue; 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci config_line_ptr = config_line; 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_ci if (strncmp(config_line_ptr, "scanner", 7) == 0) 757141cc406Sopenharmony_ci { 758141cc406Sopenharmony_ci config_line_ptr += 7; 759141cc406Sopenharmony_ci 760141cc406Sopenharmony_ci if (name) 761141cc406Sopenharmony_ci { 762141cc406Sopenharmony_ci /* Parsing of previous scanner + options is finished. Attach 763141cc406Sopenharmony_ci the device before we parse the next section. */ 764141cc406Sopenharmony_ci attach_device(&driver, &name, &port, &option_ta); 765141cc406Sopenharmony_ci } 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); 768141cc406Sopenharmony_ci if (!*config_line_ptr) 769141cc406Sopenharmony_ci { 770141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after ``scanner''\n", 771141cc406Sopenharmony_ci line); 772141cc406Sopenharmony_ci continue; 773141cc406Sopenharmony_ci } 774141cc406Sopenharmony_ci 775141cc406Sopenharmony_ci config_line_ptr = sanei_config_get_string (config_line_ptr, &name); 776141cc406Sopenharmony_ci if ((name == NULL) || (!*name)) 777141cc406Sopenharmony_ci { 778141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after ``scanner''\n", 779141cc406Sopenharmony_ci line); 780141cc406Sopenharmony_ci if (name != NULL) 781141cc406Sopenharmony_ci free (name); 782141cc406Sopenharmony_ci name = 0; 783141cc406Sopenharmony_ci continue; 784141cc406Sopenharmony_ci } 785141cc406Sopenharmony_ci 786141cc406Sopenharmony_ci config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); 787141cc406Sopenharmony_ci if (!*config_line_ptr) 788141cc406Sopenharmony_ci { 789141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after " 790141cc406Sopenharmony_ci "``scanner %s''\n", line, name); 791141cc406Sopenharmony_ci free (name); 792141cc406Sopenharmony_ci name = 0; 793141cc406Sopenharmony_ci continue; 794141cc406Sopenharmony_ci } 795141cc406Sopenharmony_ci 796141cc406Sopenharmony_ci config_line_ptr = sanei_config_get_string (config_line_ptr, &port); 797141cc406Sopenharmony_ci if ((port == NULL) || (!*port)) 798141cc406Sopenharmony_ci { 799141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after " 800141cc406Sopenharmony_ci "``scanner %s''\n", line, name); 801141cc406Sopenharmony_ci free (name); 802141cc406Sopenharmony_ci name = 0; 803141cc406Sopenharmony_ci if (port != NULL) 804141cc406Sopenharmony_ci free (port); 805141cc406Sopenharmony_ci port = 0; 806141cc406Sopenharmony_ci continue; 807141cc406Sopenharmony_ci } 808141cc406Sopenharmony_ci 809141cc406Sopenharmony_ci config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); 810141cc406Sopenharmony_ci if (!*config_line_ptr) 811141cc406Sopenharmony_ci { 812141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after " 813141cc406Sopenharmony_ci "``scanner %s %s''\n", line, name, port); 814141cc406Sopenharmony_ci free (name); 815141cc406Sopenharmony_ci free (port); 816141cc406Sopenharmony_ci name = 0; 817141cc406Sopenharmony_ci port = 0; 818141cc406Sopenharmony_ci continue; 819141cc406Sopenharmony_ci } 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci config_line_ptr = sanei_config_get_string (config_line_ptr, &driver); 822141cc406Sopenharmony_ci if ((driver == NULL) || (!*driver)) 823141cc406Sopenharmony_ci { 824141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after " 825141cc406Sopenharmony_ci "``scanner %s %s''\n", line, name, port); 826141cc406Sopenharmony_ci free (name); 827141cc406Sopenharmony_ci name = 0; 828141cc406Sopenharmony_ci free (port); 829141cc406Sopenharmony_ci port = 0; 830141cc406Sopenharmony_ci if (driver != NULL) 831141cc406Sopenharmony_ci free (driver); 832141cc406Sopenharmony_ci driver = 0; 833141cc406Sopenharmony_ci continue; 834141cc406Sopenharmony_ci } 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci if (*config_line_ptr) 839141cc406Sopenharmony_ci { 840141cc406Sopenharmony_ci config_line_ptr = sanei_config_get_string (config_line_ptr, 841141cc406Sopenharmony_ci &option_ta); 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci if ((option_ta == NULL) || (!*option_ta) || 844141cc406Sopenharmony_ci (strcasecmp (option_ta, "use_ta") != 0)) 845141cc406Sopenharmony_ci { 846141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after " 847141cc406Sopenharmony_ci "``scanner %s %s %s''\n", line, name, port, driver); 848141cc406Sopenharmony_ci free (name); 849141cc406Sopenharmony_ci free (port); 850141cc406Sopenharmony_ci free (driver); 851141cc406Sopenharmony_ci if (option_ta) 852141cc406Sopenharmony_ci free (option_ta); 853141cc406Sopenharmony_ci name = port = driver = option_ta = 0; 854141cc406Sopenharmony_ci continue; 855141cc406Sopenharmony_ci } 856141cc406Sopenharmony_ci } 857141cc406Sopenharmony_ci 858141cc406Sopenharmony_ci if (*config_line_ptr) 859141cc406Sopenharmony_ci { 860141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after " 861141cc406Sopenharmony_ci "``scanner %s %s %s %s\n", line, name, port, driver, 862141cc406Sopenharmony_ci (option_ta == 0 ? "" : option_ta)); 863141cc406Sopenharmony_ci free (name); 864141cc406Sopenharmony_ci free (port); 865141cc406Sopenharmony_ci free (driver); 866141cc406Sopenharmony_ci if (option_ta) 867141cc406Sopenharmony_ci free (option_ta); 868141cc406Sopenharmony_ci name = port = driver = option_ta = 0; 869141cc406Sopenharmony_ci continue; 870141cc406Sopenharmony_ci } 871141cc406Sopenharmony_ci } 872141cc406Sopenharmony_ci else if (strncmp(config_line_ptr, "option", 6) == 0) 873141cc406Sopenharmony_ci { 874141cc406Sopenharmony_ci /* Format for options: option <name> [<value>] 875141cc406Sopenharmony_ci Note that the value is optional. */ 876141cc406Sopenharmony_ci char *optname, *optval = 0; 877141cc406Sopenharmony_ci Mustek_pp_config_option *tmpoptions; 878141cc406Sopenharmony_ci 879141cc406Sopenharmony_ci config_line_ptr += 6; 880141cc406Sopenharmony_ci config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); 881141cc406Sopenharmony_ci if (!*config_line_ptr) 882141cc406Sopenharmony_ci { 883141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after ``option''\n", 884141cc406Sopenharmony_ci line); 885141cc406Sopenharmony_ci continue; 886141cc406Sopenharmony_ci } 887141cc406Sopenharmony_ci 888141cc406Sopenharmony_ci config_line_ptr = sanei_config_get_string (config_line_ptr, &optname); 889141cc406Sopenharmony_ci if ((optname == NULL) || (!*optname)) 890141cc406Sopenharmony_ci { 891141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after ``option''\n", 892141cc406Sopenharmony_ci line); 893141cc406Sopenharmony_ci if (optname != NULL) 894141cc406Sopenharmony_ci free (optname); 895141cc406Sopenharmony_ci continue; 896141cc406Sopenharmony_ci } 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); 899141cc406Sopenharmony_ci if (*config_line_ptr) 900141cc406Sopenharmony_ci { 901141cc406Sopenharmony_ci /* The option has a value. 902141cc406Sopenharmony_ci No need to check the value; that's up to the backend */ 903141cc406Sopenharmony_ci config_line_ptr = sanei_config_get_string (config_line_ptr, 904141cc406Sopenharmony_ci &optval); 905141cc406Sopenharmony_ci 906141cc406Sopenharmony_ci config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); 907141cc406Sopenharmony_ci } 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci if (*config_line_ptr) 910141cc406Sopenharmony_ci { 911141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d after " 912141cc406Sopenharmony_ci "``option %s %s''\n", line, optname, 913141cc406Sopenharmony_ci (optval == 0 ? "" : optval)); 914141cc406Sopenharmony_ci free (optname); 915141cc406Sopenharmony_ci if (optval) 916141cc406Sopenharmony_ci free (optval); 917141cc406Sopenharmony_ci continue; 918141cc406Sopenharmony_ci } 919141cc406Sopenharmony_ci 920141cc406Sopenharmony_ci if (!strcmp (optname, "no_epp")) 921141cc406Sopenharmony_ci { 922141cc406Sopenharmony_ci u_int pa4s2_options; 923141cc406Sopenharmony_ci if (name) 924141cc406Sopenharmony_ci DBG (2, "sane_init: global option found in local scope, " 925141cc406Sopenharmony_ci "executing anyway\n"); 926141cc406Sopenharmony_ci free (optname); 927141cc406Sopenharmony_ci if (optval) 928141cc406Sopenharmony_ci { 929141cc406Sopenharmony_ci DBG (1, "sane_init: unexpected value for option no_epp\n"); 930141cc406Sopenharmony_ci free (optval); 931141cc406Sopenharmony_ci continue; 932141cc406Sopenharmony_ci } 933141cc406Sopenharmony_ci DBG (3, "sane_init: disabling mode EPP\n"); 934141cc406Sopenharmony_ci sanei_pa4s2_options (&pa4s2_options, SANE_FALSE); 935141cc406Sopenharmony_ci pa4s2_options |= SANEI_PA4S2_OPT_NO_EPP; 936141cc406Sopenharmony_ci sanei_pa4s2_options (&pa4s2_options, SANE_TRUE); 937141cc406Sopenharmony_ci continue; 938141cc406Sopenharmony_ci } 939141cc406Sopenharmony_ci else if (!name) 940141cc406Sopenharmony_ci { 941141cc406Sopenharmony_ci DBG (1, "sane_init: parse error in line %d: unexpected " 942141cc406Sopenharmony_ci " ``option''\n", line); 943141cc406Sopenharmony_ci free (optname); 944141cc406Sopenharmony_ci if (optval) 945141cc406Sopenharmony_ci free (optval); 946141cc406Sopenharmony_ci continue; 947141cc406Sopenharmony_ci } 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci /* Extend the (global) array of options */ 951141cc406Sopenharmony_ci tmpoptions = realloc(cfgoptions, 952141cc406Sopenharmony_ci (numcfgoptions+1)*sizeof(cfgoptions[0])); 953141cc406Sopenharmony_ci if (!tmpoptions) 954141cc406Sopenharmony_ci { 955141cc406Sopenharmony_ci DBG (1, "sane_init: not enough memory for device options\n"); 956141cc406Sopenharmony_ci free_cfg_options(&numcfgoptions, &cfgoptions); 957141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 958141cc406Sopenharmony_ci } 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci cfgoptions = tmpoptions; 961141cc406Sopenharmony_ci cfgoptions[numcfgoptions].name = optname; 962141cc406Sopenharmony_ci cfgoptions[numcfgoptions].value = optval; 963141cc406Sopenharmony_ci ++numcfgoptions; 964141cc406Sopenharmony_ci } 965141cc406Sopenharmony_ci else 966141cc406Sopenharmony_ci { 967141cc406Sopenharmony_ci DBG (1, "sane_init: parse error at beginning of line %d\n", line); 968141cc406Sopenharmony_ci continue; 969141cc406Sopenharmony_ci } 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci } 972141cc406Sopenharmony_ci 973141cc406Sopenharmony_ci /* If we hit the end of the file, we still may have to process the 974141cc406Sopenharmony_ci last driver */ 975141cc406Sopenharmony_ci if (name) 976141cc406Sopenharmony_ci attach_device(&driver, &name, &port, &option_ta); 977141cc406Sopenharmony_ci 978141cc406Sopenharmony_ci fclose(fp); 979141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 980141cc406Sopenharmony_ci 981141cc406Sopenharmony_ci} 982141cc406Sopenharmony_ci 983141cc406Sopenharmony_ci/* sane_exit: 984141cc406Sopenharmony_ci * Unloads all drivers and frees allocated memory 985141cc406Sopenharmony_ci * 986141cc406Sopenharmony_ci * Description: 987141cc406Sopenharmony_ci * All open devices are closed first. Then all registered devices 988141cc406Sopenharmony_ci * are removed. 989141cc406Sopenharmony_ci * 990141cc406Sopenharmony_ci */ 991141cc406Sopenharmony_ci 992141cc406Sopenharmony_civoid 993141cc406Sopenharmony_cisane_exit (void) 994141cc406Sopenharmony_ci{ 995141cc406Sopenharmony_ci Mustek_pp_Handle *hndl; 996141cc406Sopenharmony_ci Mustek_pp_Device *dev; 997141cc406Sopenharmony_ci 998141cc406Sopenharmony_ci if (first_hndl) 999141cc406Sopenharmony_ci DBG (3, "sane_exit: closing open devices\n"); 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci while (first_hndl) 1002141cc406Sopenharmony_ci { 1003141cc406Sopenharmony_ci hndl = first_hndl; 1004141cc406Sopenharmony_ci sane_close (hndl); 1005141cc406Sopenharmony_ci } 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci dev = devlist; 1008141cc406Sopenharmony_ci num_devices = 0; 1009141cc406Sopenharmony_ci devlist = NULL; 1010141cc406Sopenharmony_ci 1011141cc406Sopenharmony_ci while (dev) { 1012141cc406Sopenharmony_ci 1013141cc406Sopenharmony_ci free (dev->port); 1014141cc406Sopenharmony_ci free (dev->name); 1015141cc406Sopenharmony_ci free (dev->vendor); 1016141cc406Sopenharmony_ci free (dev->model); 1017141cc406Sopenharmony_ci free (dev->type); 1018141cc406Sopenharmony_ci free_cfg_options (&dev->numcfgoptions, &dev->cfgoptions); 1019141cc406Sopenharmony_ci dev = dev->next; 1020141cc406Sopenharmony_ci 1021141cc406Sopenharmony_ci } 1022141cc406Sopenharmony_ci 1023141cc406Sopenharmony_ci if (devarray != NULL) 1024141cc406Sopenharmony_ci free (devarray); 1025141cc406Sopenharmony_ci devarray = NULL; 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci DBG (3, "sane_exit: all drivers unloaded\n"); 1028141cc406Sopenharmony_ci 1029141cc406Sopenharmony_ci} 1030141cc406Sopenharmony_ci 1031141cc406Sopenharmony_ci/* sane_get_devices: 1032141cc406Sopenharmony_ci * Returns a list of registered devices 1033141cc406Sopenharmony_ci * 1034141cc406Sopenharmony_ci * Description: 1035141cc406Sopenharmony_ci * A possible present old device_list is removed first. A new 1036141cc406Sopenharmony_ci * devarray is allocated and filled with pointers to the 1037141cc406Sopenharmony_ci * SANE_Device structures of the Mustek_pp_Devices 1038141cc406Sopenharmony_ci */ 1039141cc406Sopenharmony_ci/*ARGSUSED*/ 1040141cc406Sopenharmony_ciSANE_Status 1041141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, 1042141cc406Sopenharmony_ci SANE_Bool local_only __UNUSED__) 1043141cc406Sopenharmony_ci{ 1044141cc406Sopenharmony_ci int ctr; 1045141cc406Sopenharmony_ci Mustek_pp_Device *dev; 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci if (devarray != NULL) 1048141cc406Sopenharmony_ci free (devarray); 1049141cc406Sopenharmony_ci 1050141cc406Sopenharmony_ci devarray = malloc ((num_devices + 1) * sizeof (devarray[0])); 1051141cc406Sopenharmony_ci 1052141cc406Sopenharmony_ci if (devarray == NULL) 1053141cc406Sopenharmony_ci { 1054141cc406Sopenharmony_ci DBG (1, "sane_get_devices: not enough memory for device list\n"); 1055141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1056141cc406Sopenharmony_ci } 1057141cc406Sopenharmony_ci 1058141cc406Sopenharmony_ci dev = devlist; 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci for (ctr=0 ; ctr<num_devices ; ctr++) { 1061141cc406Sopenharmony_ci devarray[ctr] = &dev->sane; 1062141cc406Sopenharmony_ci dev = dev->next; 1063141cc406Sopenharmony_ci } 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci devarray[num_devices] = NULL; 1066141cc406Sopenharmony_ci *device_list = (const SANE_Device **)devarray; 1067141cc406Sopenharmony_ci 1068141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1069141cc406Sopenharmony_ci} 1070141cc406Sopenharmony_ci 1071141cc406Sopenharmony_ci/* sane_open: 1072141cc406Sopenharmony_ci * opens a device and prepares it for operation 1073141cc406Sopenharmony_ci * 1074141cc406Sopenharmony_ci * Description: 1075141cc406Sopenharmony_ci * The device identified by ``devicename'' is looked 1076141cc406Sopenharmony_ci * up in the list, or if devicename is zero, the 1077141cc406Sopenharmony_ci * first device from the list is taken. 1078141cc406Sopenharmony_ci * 1079141cc406Sopenharmony_ci * open is called for the selected device. 1080141cc406Sopenharmony_ci * 1081141cc406Sopenharmony_ci * The handle is set up with default values, and the 1082141cc406Sopenharmony_ci * option descriptors are initialized 1083141cc406Sopenharmony_ci */ 1084141cc406Sopenharmony_ci 1085141cc406Sopenharmony_ciSANE_Status 1086141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 1087141cc406Sopenharmony_ci{ 1088141cc406Sopenharmony_ci 1089141cc406Sopenharmony_ci Mustek_pp_Handle *hndl; 1090141cc406Sopenharmony_ci Mustek_pp_Device *dev; 1091141cc406Sopenharmony_ci SANE_Status status; 1092141cc406Sopenharmony_ci int fd, i; 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci if (devicename[0]) { 1095141cc406Sopenharmony_ci 1096141cc406Sopenharmony_ci dev = devlist; 1097141cc406Sopenharmony_ci 1098141cc406Sopenharmony_ci while (dev) { 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci if (strcmp (dev->name, devicename) == 0) 1101141cc406Sopenharmony_ci break; 1102141cc406Sopenharmony_ci 1103141cc406Sopenharmony_ci dev = dev->next; 1104141cc406Sopenharmony_ci 1105141cc406Sopenharmony_ci } 1106141cc406Sopenharmony_ci 1107141cc406Sopenharmony_ci if (!dev) { 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci DBG (1, "sane_open: unknown devicename ``%s''\n", devicename); 1110141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1111141cc406Sopenharmony_ci 1112141cc406Sopenharmony_ci } 1113141cc406Sopenharmony_ci } else 1114141cc406Sopenharmony_ci dev = devlist; 1115141cc406Sopenharmony_ci 1116141cc406Sopenharmony_ci if (!dev) { 1117141cc406Sopenharmony_ci DBG (1, "sane_open: no devices present...\n"); 1118141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1119141cc406Sopenharmony_ci } 1120141cc406Sopenharmony_ci 1121141cc406Sopenharmony_ci DBG (3, "sane_open: Using device ``%s'' (driver %s v%s by %s)\n", 1122141cc406Sopenharmony_ci dev->name, dev->func->driver, dev->func->version, dev->func->author); 1123141cc406Sopenharmony_ci 1124141cc406Sopenharmony_ci if ((hndl = malloc (sizeof (Mustek_pp_Handle))) == NULL) { 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci DBG (1, "sane_open: not enough free memory for the handle\n"); 1127141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1128141cc406Sopenharmony_ci 1129141cc406Sopenharmony_ci } 1130141cc406Sopenharmony_ci 1131141cc406Sopenharmony_ci if ((status = dev->func->open (dev->port, dev->caps, &fd)) != SANE_STATUS_GOOD) { 1132141cc406Sopenharmony_ci 1133141cc406Sopenharmony_ci DBG (1, "sane_open: could not open device (%s)\n", 1134141cc406Sopenharmony_ci sane_strstatus (status)); 1135141cc406Sopenharmony_ci return status; 1136141cc406Sopenharmony_ci 1137141cc406Sopenharmony_ci } 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci hndl->next = first_hndl; 1140141cc406Sopenharmony_ci hndl->dev = dev; 1141141cc406Sopenharmony_ci hndl->fd = fd; 1142141cc406Sopenharmony_ci hndl->state = STATE_IDLE; 1143141cc406Sopenharmony_ci hndl->pipe = -1; 1144141cc406Sopenharmony_ci 1145141cc406Sopenharmony_ci init_options (hndl); 1146141cc406Sopenharmony_ci 1147141cc406Sopenharmony_ci dev->func->setup (hndl); 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci /* Initialize driver-specific configuration options. This must be 1150141cc406Sopenharmony_ci done after calling the setup() function because only then the 1151141cc406Sopenharmony_ci driver is guaranteed to be fully initialized */ 1152141cc406Sopenharmony_ci for (i = 0; i<dev->numcfgoptions; ++i) 1153141cc406Sopenharmony_ci { 1154141cc406Sopenharmony_ci status = dev->func->config (hndl, 1155141cc406Sopenharmony_ci dev->cfgoptions[i].name, 1156141cc406Sopenharmony_ci dev->cfgoptions[i].value); 1157141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1158141cc406Sopenharmony_ci { 1159141cc406Sopenharmony_ci DBG (1, "sane_open: could not set option %s for device (%s)\n", 1160141cc406Sopenharmony_ci dev->cfgoptions[i].name, sane_strstatus (status)); 1161141cc406Sopenharmony_ci 1162141cc406Sopenharmony_ci /* Question: should the initialization be aborted when an 1163141cc406Sopenharmony_ci option cannot be handled ? 1164141cc406Sopenharmony_ci The driver should have reasonable built-in defaults, so 1165141cc406Sopenharmony_ci an illegal option value or an unknown option should not 1166141cc406Sopenharmony_ci be fatal. Therefore, it's probably ok to ignore the error. */ 1167141cc406Sopenharmony_ci } 1168141cc406Sopenharmony_ci } 1169141cc406Sopenharmony_ci 1170141cc406Sopenharmony_ci first_hndl = hndl; 1171141cc406Sopenharmony_ci 1172141cc406Sopenharmony_ci *handle = hndl; 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1175141cc406Sopenharmony_ci} 1176141cc406Sopenharmony_ci 1177141cc406Sopenharmony_ci/* sane_close: 1178141cc406Sopenharmony_ci * closes a given device and frees all resources 1179141cc406Sopenharmony_ci * 1180141cc406Sopenharmony_ci * Description: 1181141cc406Sopenharmony_ci * The handle is searched in the list of active handles. 1182141cc406Sopenharmony_ci * If it's found, the handle is removed. 1183141cc406Sopenharmony_ci * 1184141cc406Sopenharmony_ci * If the associated device is still scanning, the process 1185141cc406Sopenharmony_ci * is cancelled. 1186141cc406Sopenharmony_ci * 1187141cc406Sopenharmony_ci * Then the backend makes sure, the lamp was at least 1188141cc406Sopenharmony_ci * 2 seconds on. 1189141cc406Sopenharmony_ci * 1190141cc406Sopenharmony_ci * Afterwards the selected handle is closed 1191141cc406Sopenharmony_ci */ 1192141cc406Sopenharmony_civoid 1193141cc406Sopenharmony_cisane_close (SANE_Handle handle) 1194141cc406Sopenharmony_ci{ 1195141cc406Sopenharmony_ci Mustek_pp_Handle *prev, *hndl; 1196141cc406Sopenharmony_ci 1197141cc406Sopenharmony_ci prev = NULL; 1198141cc406Sopenharmony_ci 1199141cc406Sopenharmony_ci for (hndl = first_hndl; hndl; hndl = hndl->next) 1200141cc406Sopenharmony_ci { 1201141cc406Sopenharmony_ci if (hndl == handle) 1202141cc406Sopenharmony_ci break; 1203141cc406Sopenharmony_ci prev = hndl; 1204141cc406Sopenharmony_ci } 1205141cc406Sopenharmony_ci 1206141cc406Sopenharmony_ci if (hndl == NULL) 1207141cc406Sopenharmony_ci { 1208141cc406Sopenharmony_ci DBG (2, "sane_close: unknown device handle\n"); 1209141cc406Sopenharmony_ci return; 1210141cc406Sopenharmony_ci } 1211141cc406Sopenharmony_ci 1212141cc406Sopenharmony_ci if (hndl->state == STATE_SCANNING) { 1213141cc406Sopenharmony_ci sane_cancel (handle); 1214141cc406Sopenharmony_ci do_eof (handle); 1215141cc406Sopenharmony_ci } 1216141cc406Sopenharmony_ci 1217141cc406Sopenharmony_ci if (prev != NULL) 1218141cc406Sopenharmony_ci prev->next = hndl->next; 1219141cc406Sopenharmony_ci else 1220141cc406Sopenharmony_ci first_hndl = hndl->next; 1221141cc406Sopenharmony_ci 1222141cc406Sopenharmony_ci DBG (3, "sane_close: maybe waiting for lamp...\n"); 1223141cc406Sopenharmony_ci if (hndl->lamp_on) 1224141cc406Sopenharmony_ci while (time (NULL) - hndl->lamp_on < 2) 1225141cc406Sopenharmony_ci sleep (1); 1226141cc406Sopenharmony_ci 1227141cc406Sopenharmony_ci hndl->dev->func->close (hndl); 1228141cc406Sopenharmony_ci 1229141cc406Sopenharmony_ci DBG (3, "sane_close: device closed\n"); 1230141cc406Sopenharmony_ci 1231141cc406Sopenharmony_ci free (handle); 1232141cc406Sopenharmony_ci 1233141cc406Sopenharmony_ci} 1234141cc406Sopenharmony_ci 1235141cc406Sopenharmony_ci/* sane_get_option_descriptor: 1236141cc406Sopenharmony_ci * does what it says 1237141cc406Sopenharmony_ci * 1238141cc406Sopenharmony_ci * Description: 1239141cc406Sopenharmony_ci * 1240141cc406Sopenharmony_ci */ 1241141cc406Sopenharmony_ci 1242141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1243141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1244141cc406Sopenharmony_ci{ 1245141cc406Sopenharmony_ci Mustek_pp_Handle *hndl = handle; 1246141cc406Sopenharmony_ci 1247141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 1248141cc406Sopenharmony_ci { 1249141cc406Sopenharmony_ci DBG (2, "sane_get_option_descriptor: option %d doesn't exist\n", option); 1250141cc406Sopenharmony_ci return NULL; 1251141cc406Sopenharmony_ci } 1252141cc406Sopenharmony_ci 1253141cc406Sopenharmony_ci return hndl->opt + option; 1254141cc406Sopenharmony_ci} 1255141cc406Sopenharmony_ci 1256141cc406Sopenharmony_ci 1257141cc406Sopenharmony_ci/* sane_control_option: 1258141cc406Sopenharmony_ci * Reads or writes an option 1259141cc406Sopenharmony_ci * 1260141cc406Sopenharmony_ci * Description: 1261141cc406Sopenharmony_ci * If a pointer to info is given, the value is initialized to zero 1262141cc406Sopenharmony_ci * while scanning options cannot be read or written. next a basic 1263141cc406Sopenharmony_ci * check whether the request is valid is done. 1264141cc406Sopenharmony_ci * 1265141cc406Sopenharmony_ci * Depending on ``action'' the value of the option is either read 1266141cc406Sopenharmony_ci * (in the first block) or written (in the second block). auto 1267141cc406Sopenharmony_ci * values aren't supported. 1268141cc406Sopenharmony_ci * 1269141cc406Sopenharmony_ci * before a value is written, some checks are performed. Depending 1270141cc406Sopenharmony_ci * on the option, that is written, other options also change 1271141cc406Sopenharmony_ci * 1272141cc406Sopenharmony_ci */ 1273141cc406Sopenharmony_ciSANE_Status 1274141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1275141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 1276141cc406Sopenharmony_ci{ 1277141cc406Sopenharmony_ci Mustek_pp_Handle *hndl = handle; 1278141cc406Sopenharmony_ci SANE_Status status; 1279141cc406Sopenharmony_ci SANE_Word w, cap; 1280141cc406Sopenharmony_ci 1281141cc406Sopenharmony_ci if (info) 1282141cc406Sopenharmony_ci *info = 0; 1283141cc406Sopenharmony_ci 1284141cc406Sopenharmony_ci if (hndl->state == STATE_SCANNING) 1285141cc406Sopenharmony_ci { 1286141cc406Sopenharmony_ci DBG (2, "sane_control_option: device is scanning\n"); 1287141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1288141cc406Sopenharmony_ci } 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci if ((unsigned int) option >= NUM_OPTIONS) 1291141cc406Sopenharmony_ci { 1292141cc406Sopenharmony_ci DBG (2, "sane_control_option: option %d doesn't exist\n", option); 1293141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1294141cc406Sopenharmony_ci } 1295141cc406Sopenharmony_ci 1296141cc406Sopenharmony_ci cap = hndl->opt[option].cap; 1297141cc406Sopenharmony_ci 1298141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 1299141cc406Sopenharmony_ci { 1300141cc406Sopenharmony_ci DBG (2, "sane_control_option: option %d isn't active\n", option); 1301141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1302141cc406Sopenharmony_ci } 1303141cc406Sopenharmony_ci 1304141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 1305141cc406Sopenharmony_ci { 1306141cc406Sopenharmony_ci 1307141cc406Sopenharmony_ci switch (option) 1308141cc406Sopenharmony_ci { 1309141cc406Sopenharmony_ci /* word options: */ 1310141cc406Sopenharmony_ci case OPT_PREVIEW: 1311141cc406Sopenharmony_ci case OPT_GRAY_PREVIEW: 1312141cc406Sopenharmony_ci case OPT_RESOLUTION: 1313141cc406Sopenharmony_ci case OPT_TL_X: 1314141cc406Sopenharmony_ci case OPT_TL_Y: 1315141cc406Sopenharmony_ci case OPT_BR_X: 1316141cc406Sopenharmony_ci case OPT_BR_Y: 1317141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1318141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1319141cc406Sopenharmony_ci case OPT_INVERT: 1320141cc406Sopenharmony_ci case OPT_DEPTH: 1321141cc406Sopenharmony_ci 1322141cc406Sopenharmony_ci *(SANE_Word *) val = hndl->val[option].w; 1323141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1324141cc406Sopenharmony_ci 1325141cc406Sopenharmony_ci /* word-array options: */ 1326141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1327141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1328141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1329141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1330141cc406Sopenharmony_ci 1331141cc406Sopenharmony_ci memcpy (val, hndl->val[option].wa, hndl->opt[option].size); 1332141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1333141cc406Sopenharmony_ci 1334141cc406Sopenharmony_ci /* string options: */ 1335141cc406Sopenharmony_ci case OPT_MODE: 1336141cc406Sopenharmony_ci case OPT_SPEED: 1337141cc406Sopenharmony_ci 1338141cc406Sopenharmony_ci strcpy (val, hndl->val[option].s); 1339141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1340141cc406Sopenharmony_ci } 1341141cc406Sopenharmony_ci } 1342141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 1343141cc406Sopenharmony_ci { 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 1346141cc406Sopenharmony_ci { 1347141cc406Sopenharmony_ci DBG (2, "sane_control_option: option can't be set (%s)\n", 1348141cc406Sopenharmony_ci hndl->opt[option].name); 1349141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1350141cc406Sopenharmony_ci } 1351141cc406Sopenharmony_ci 1352141cc406Sopenharmony_ci status = sanei_constrain_value (hndl->opt + option, val, info); 1353141cc406Sopenharmony_ci 1354141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1355141cc406Sopenharmony_ci { 1356141cc406Sopenharmony_ci DBG (2, "sane_control_option: constrain_value failed (%s)\n", 1357141cc406Sopenharmony_ci sane_strstatus (status)); 1358141cc406Sopenharmony_ci return status; 1359141cc406Sopenharmony_ci } 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci switch (option) 1362141cc406Sopenharmony_ci { 1363141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 1364141cc406Sopenharmony_ci case OPT_RESOLUTION: 1365141cc406Sopenharmony_ci case OPT_TL_X: 1366141cc406Sopenharmony_ci case OPT_BR_X: 1367141cc406Sopenharmony_ci case OPT_TL_Y: 1368141cc406Sopenharmony_ci case OPT_BR_Y: 1369141cc406Sopenharmony_ci case OPT_PREVIEW: 1370141cc406Sopenharmony_ci case OPT_GRAY_PREVIEW: 1371141cc406Sopenharmony_ci case OPT_INVERT: 1372141cc406Sopenharmony_ci case OPT_DEPTH: 1373141cc406Sopenharmony_ci 1374141cc406Sopenharmony_ci if (info) 1375141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_ci hndl->val[option].w = *(SANE_Word *) val; 1378141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1379141cc406Sopenharmony_ci 1380141cc406Sopenharmony_ci /* side-effect-free word-array options: */ 1381141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1382141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1383141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1384141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci memcpy (hndl->val[option].wa, val, hndl->opt[option].size); 1387141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1388141cc406Sopenharmony_ci 1389141cc406Sopenharmony_ci /* side-effect-free string options: */ 1390141cc406Sopenharmony_ci case OPT_SPEED: 1391141cc406Sopenharmony_ci 1392141cc406Sopenharmony_ci if (hndl->val[option].s) 1393141cc406Sopenharmony_ci free (hndl->val[option].s); 1394141cc406Sopenharmony_ci 1395141cc406Sopenharmony_ci hndl->val[option].s = strdup (val); 1396141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1397141cc406Sopenharmony_ci 1398141cc406Sopenharmony_ci 1399141cc406Sopenharmony_ci /* options with side-effects: */ 1400141cc406Sopenharmony_ci 1401141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1402141cc406Sopenharmony_ci w = *(SANE_Word *) val; 1403141cc406Sopenharmony_ci 1404141cc406Sopenharmony_ci if (w == hndl->val[OPT_CUSTOM_GAMMA].w) 1405141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 1406141cc406Sopenharmony_ci 1407141cc406Sopenharmony_ci if (info) 1408141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 1409141cc406Sopenharmony_ci 1410141cc406Sopenharmony_ci hndl->val[OPT_CUSTOM_GAMMA].w = w; 1411141cc406Sopenharmony_ci 1412141cc406Sopenharmony_ci if (w == SANE_TRUE) 1413141cc406Sopenharmony_ci { 1414141cc406Sopenharmony_ci const char *mode = hndl->val[OPT_MODE].s; 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1417141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1418141cc406Sopenharmony_ci else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1419141cc406Sopenharmony_ci { 1420141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1421141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1422141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1423141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1424141cc406Sopenharmony_ci } 1425141cc406Sopenharmony_ci } 1426141cc406Sopenharmony_ci else 1427141cc406Sopenharmony_ci { 1428141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1429141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1430141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1431141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1432141cc406Sopenharmony_ci } 1433141cc406Sopenharmony_ci 1434141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1435141cc406Sopenharmony_ci 1436141cc406Sopenharmony_ci case OPT_MODE: 1437141cc406Sopenharmony_ci { 1438141cc406Sopenharmony_ci char *old_val = hndl->val[option].s; 1439141cc406Sopenharmony_ci 1440141cc406Sopenharmony_ci if (old_val) 1441141cc406Sopenharmony_ci { 1442141cc406Sopenharmony_ci if (strcmp (old_val, val) == 0) 1443141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 1444141cc406Sopenharmony_ci 1445141cc406Sopenharmony_ci free (old_val); 1446141cc406Sopenharmony_ci } 1447141cc406Sopenharmony_ci 1448141cc406Sopenharmony_ci if (info) 1449141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1450141cc406Sopenharmony_ci 1451141cc406Sopenharmony_ci hndl->val[option].s = strdup (val); 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci hndl->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1454141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1455141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1456141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1457141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1458141cc406Sopenharmony_ci 1459141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci if ((hndl->dev->caps & CAP_DEPTH) && (strcmp(val, SANE_VALUE_SCAN_MODE_COLOR) == 0)) 1462141cc406Sopenharmony_ci hndl->opt[OPT_DEPTH].cap &= ~SANE_CAP_INACTIVE; 1463141cc406Sopenharmony_ci 1464141cc406Sopenharmony_ci if (!(hndl->dev->caps & CAP_GAMMA_CORRECT)) 1465141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1466141cc406Sopenharmony_ci 1467141cc406Sopenharmony_ci if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) != 0) 1468141cc406Sopenharmony_ci hndl->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci if (hndl->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) 1471141cc406Sopenharmony_ci { 1472141cc406Sopenharmony_ci if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1473141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1474141cc406Sopenharmony_ci else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1475141cc406Sopenharmony_ci { 1476141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1477141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1478141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1479141cc406Sopenharmony_ci hndl->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1480141cc406Sopenharmony_ci } 1481141cc406Sopenharmony_ci } 1482141cc406Sopenharmony_ci 1483141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1484141cc406Sopenharmony_ci } 1485141cc406Sopenharmony_ci } 1486141cc406Sopenharmony_ci } 1487141cc406Sopenharmony_ci 1488141cc406Sopenharmony_ci DBG (2, "sane_control_option: unknown action\n"); 1489141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1490141cc406Sopenharmony_ci} 1491141cc406Sopenharmony_ci 1492141cc406Sopenharmony_ci 1493141cc406Sopenharmony_ci/* sane_get_parameters: 1494141cc406Sopenharmony_ci * returns the set of parameters, that is used for the next scan 1495141cc406Sopenharmony_ci * 1496141cc406Sopenharmony_ci * Description: 1497141cc406Sopenharmony_ci * 1498141cc406Sopenharmony_ci * First of all it is impossible to change the parameter set 1499141cc406Sopenharmony_ci * while scanning. 1500141cc406Sopenharmony_ci * 1501141cc406Sopenharmony_ci * sane_get_parameters not only returns the parameters for 1502141cc406Sopenharmony_ci * the next scan, it also sets them, i.e. converts the 1503141cc406Sopenharmony_ci * options in actually parameters. 1504141cc406Sopenharmony_ci * 1505141cc406Sopenharmony_ci * The following parameters are set: 1506141cc406Sopenharmony_ci * 1507141cc406Sopenharmony_ci * scanmode: according to the option SCANMODE, but 1508141cc406Sopenharmony_ci * 24bit color, if PREVIEW is selected and 1509141cc406Sopenharmony_ci * grayscale if GRAY_PREVIEW is selected 1510141cc406Sopenharmony_ci * depth: the bit depth for color modes (if 1511141cc406Sopenharmony_ci * supported) or 24bit by default 1512141cc406Sopenharmony_ci * (ignored in bw/grayscale or if not 1513141cc406Sopenharmony_ci * supported) 1514141cc406Sopenharmony_ci * dpi: resolution 1515141cc406Sopenharmony_ci * invert: if supported else defaults to false 1516141cc406Sopenharmony_ci * gamma: if supported and selected 1517141cc406Sopenharmony_ci * ta: if supported by the device 1518141cc406Sopenharmony_ci * speed: selected speed (or fastest if not 1519141cc406Sopenharmony_ci * supported) 1520141cc406Sopenharmony_ci * scanarea: the scanarea is calculated from the 1521141cc406Sopenharmony_ci * selections the user has mode. note 1522141cc406Sopenharmony_ci * that the area may slightly differ from 1523141cc406Sopenharmony_ci * the scanarea selected due to rounding 1524141cc406Sopenharmony_ci * note also, that a scanarea of 1525141cc406Sopenharmony_ci * (0,0)-(100,100) will include all pixels 1526141cc406Sopenharmony_ci * where 0 <= x < 100 and 0 <= y < 100 1527141cc406Sopenharmony_ci * afterwards, all values are copied into the SANE_Parameters 1528141cc406Sopenharmony_ci * structure. 1529141cc406Sopenharmony_ci */ 1530141cc406Sopenharmony_ciSANE_Status 1531141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1532141cc406Sopenharmony_ci{ 1533141cc406Sopenharmony_ci Mustek_pp_Handle *hndl = handle; 1534141cc406Sopenharmony_ci char *mode; 1535141cc406Sopenharmony_ci int dpi, ctr; 1536141cc406Sopenharmony_ci 1537141cc406Sopenharmony_ci if (hndl->state != STATE_SCANNING) 1538141cc406Sopenharmony_ci { 1539141cc406Sopenharmony_ci 1540141cc406Sopenharmony_ci 1541141cc406Sopenharmony_ci memset (&hndl->params, 0, sizeof (hndl->params)); 1542141cc406Sopenharmony_ci 1543141cc406Sopenharmony_ci 1544141cc406Sopenharmony_ci if ((hndl->dev->caps & CAP_DEPTH) && (hndl->mode == MODE_COLOR)) 1545141cc406Sopenharmony_ci hndl->depth = hndl->val[OPT_DEPTH].w; 1546141cc406Sopenharmony_ci else 1547141cc406Sopenharmony_ci hndl->depth = 8; 1548141cc406Sopenharmony_ci 1549141cc406Sopenharmony_ci dpi = (int) (SANE_UNFIX (hndl->val[OPT_RESOLUTION].w) + 0.5); 1550141cc406Sopenharmony_ci 1551141cc406Sopenharmony_ci hndl->res = dpi; 1552141cc406Sopenharmony_ci 1553141cc406Sopenharmony_ci if (hndl->dev->caps & CAP_INVERT) 1554141cc406Sopenharmony_ci hndl->invert = hndl->val[OPT_INVERT].w; 1555141cc406Sopenharmony_ci else 1556141cc406Sopenharmony_ci hndl->invert = SANE_FALSE; 1557141cc406Sopenharmony_ci 1558141cc406Sopenharmony_ci if (hndl->dev->caps & CAP_TA) 1559141cc406Sopenharmony_ci hndl->use_ta = SANE_TRUE; 1560141cc406Sopenharmony_ci else 1561141cc406Sopenharmony_ci hndl->use_ta = SANE_FALSE; 1562141cc406Sopenharmony_ci 1563141cc406Sopenharmony_ci if ((hndl->dev->caps & CAP_GAMMA_CORRECT) && (hndl->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE)) 1564141cc406Sopenharmony_ci hndl->do_gamma = SANE_TRUE; 1565141cc406Sopenharmony_ci else 1566141cc406Sopenharmony_ci hndl->do_gamma = SANE_FALSE; 1567141cc406Sopenharmony_ci 1568141cc406Sopenharmony_ci if (hndl->dev->caps & CAP_SPEED_SELECT) { 1569141cc406Sopenharmony_ci 1570141cc406Sopenharmony_ci for (ctr=SPEED_SLOWEST; ctr<=SPEED_FASTEST; ctr++) 1571141cc406Sopenharmony_ci if (strcmp(mustek_pp_speeds[ctr], hndl->val[OPT_SPEED].s) == 0) 1572141cc406Sopenharmony_ci hndl->speed = ctr; 1573141cc406Sopenharmony_ci 1574141cc406Sopenharmony_ci 1575141cc406Sopenharmony_ci 1576141cc406Sopenharmony_ci } else 1577141cc406Sopenharmony_ci hndl->speed = SPEED_NORMAL; 1578141cc406Sopenharmony_ci 1579141cc406Sopenharmony_ci mode = hndl->val[OPT_MODE].s; 1580141cc406Sopenharmony_ci 1581141cc406Sopenharmony_ci if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) 1582141cc406Sopenharmony_ci hndl->mode = MODE_BW; 1583141cc406Sopenharmony_ci else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1584141cc406Sopenharmony_ci hndl->mode = MODE_GRAYSCALE; 1585141cc406Sopenharmony_ci else 1586141cc406Sopenharmony_ci hndl->mode = MODE_COLOR; 1587141cc406Sopenharmony_ci 1588141cc406Sopenharmony_ci if (hndl->val[OPT_PREVIEW].w == SANE_TRUE) 1589141cc406Sopenharmony_ci { 1590141cc406Sopenharmony_ci 1591141cc406Sopenharmony_ci hndl->speed = SPEED_FASTEST; 1592141cc406Sopenharmony_ci hndl->depth = 8; 1593141cc406Sopenharmony_ci if (! hndl->use_ta) 1594141cc406Sopenharmony_ci hndl->invert = SANE_FALSE; 1595141cc406Sopenharmony_ci hndl->do_gamma = SANE_FALSE; 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_ci if (hndl->val[OPT_GRAY_PREVIEW].w == SANE_TRUE) 1598141cc406Sopenharmony_ci hndl->mode = MODE_GRAYSCALE; 1599141cc406Sopenharmony_ci else { 1600141cc406Sopenharmony_ci hndl->mode = MODE_COLOR; 1601141cc406Sopenharmony_ci } 1602141cc406Sopenharmony_ci 1603141cc406Sopenharmony_ci } 1604141cc406Sopenharmony_ci 1605141cc406Sopenharmony_ci hndl->topX = 1606141cc406Sopenharmony_ci MIN ((int) 1607141cc406Sopenharmony_ci (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_TL_X].w), hndl->dev->maxres) + 1608141cc406Sopenharmony_ci 0.5), hndl->dev->maxhsize); 1609141cc406Sopenharmony_ci hndl->topY = 1610141cc406Sopenharmony_ci MIN ((int) 1611141cc406Sopenharmony_ci (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_TL_Y].w), hndl->dev->maxres) + 1612141cc406Sopenharmony_ci 0.5), hndl->dev->maxvsize); 1613141cc406Sopenharmony_ci 1614141cc406Sopenharmony_ci hndl->bottomX = 1615141cc406Sopenharmony_ci MIN ((int) 1616141cc406Sopenharmony_ci (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_BR_X].w), hndl->dev->maxres) + 1617141cc406Sopenharmony_ci 0.5), hndl->dev->maxhsize); 1618141cc406Sopenharmony_ci hndl->bottomY = 1619141cc406Sopenharmony_ci MIN ((int) 1620141cc406Sopenharmony_ci (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_BR_Y].w), hndl->dev->maxres) + 1621141cc406Sopenharmony_ci 0.5), hndl->dev->maxvsize); 1622141cc406Sopenharmony_ci 1623141cc406Sopenharmony_ci /* If necessary, swap the upper and lower boundaries to avoid negative 1624141cc406Sopenharmony_ci distances. */ 1625141cc406Sopenharmony_ci if (hndl->topX > hndl->bottomX) { 1626141cc406Sopenharmony_ci SANE_Int tmp = hndl->topX; 1627141cc406Sopenharmony_ci hndl->topX = hndl->bottomX; 1628141cc406Sopenharmony_ci hndl->bottomX = tmp; 1629141cc406Sopenharmony_ci } 1630141cc406Sopenharmony_ci if (hndl->topY > hndl->bottomY) { 1631141cc406Sopenharmony_ci SANE_Int tmp = hndl->topY; 1632141cc406Sopenharmony_ci hndl->topY = hndl->bottomY; 1633141cc406Sopenharmony_ci hndl->bottomY = tmp; 1634141cc406Sopenharmony_ci } 1635141cc406Sopenharmony_ci 1636141cc406Sopenharmony_ci hndl->params.pixels_per_line = (hndl->bottomX - hndl->topX) * hndl->res 1637141cc406Sopenharmony_ci / hndl->dev->maxres; 1638141cc406Sopenharmony_ci 1639141cc406Sopenharmony_ci hndl->params.bytes_per_line = hndl->params.pixels_per_line; 1640141cc406Sopenharmony_ci 1641141cc406Sopenharmony_ci switch (hndl->mode) 1642141cc406Sopenharmony_ci { 1643141cc406Sopenharmony_ci 1644141cc406Sopenharmony_ci case MODE_BW: 1645141cc406Sopenharmony_ci hndl->params.bytes_per_line /= 8; 1646141cc406Sopenharmony_ci 1647141cc406Sopenharmony_ci if ((hndl->params.pixels_per_line % 8) != 0) 1648141cc406Sopenharmony_ci hndl->params.bytes_per_line++; 1649141cc406Sopenharmony_ci 1650141cc406Sopenharmony_ci hndl->params.depth = 1; 1651141cc406Sopenharmony_ci break; 1652141cc406Sopenharmony_ci 1653141cc406Sopenharmony_ci case MODE_GRAYSCALE: 1654141cc406Sopenharmony_ci hndl->params.depth = 8; 1655141cc406Sopenharmony_ci hndl->params.format = SANE_FRAME_GRAY; 1656141cc406Sopenharmony_ci break; 1657141cc406Sopenharmony_ci 1658141cc406Sopenharmony_ci case MODE_COLOR: 1659141cc406Sopenharmony_ci hndl->params.depth = hndl->depth; 1660141cc406Sopenharmony_ci hndl->params.bytes_per_line *= 3; 1661141cc406Sopenharmony_ci if (hndl->depth > 8) 1662141cc406Sopenharmony_ci hndl->params.bytes_per_line *= 2; 1663141cc406Sopenharmony_ci hndl->params.format = SANE_FRAME_RGB; 1664141cc406Sopenharmony_ci break; 1665141cc406Sopenharmony_ci 1666141cc406Sopenharmony_ci } 1667141cc406Sopenharmony_ci 1668141cc406Sopenharmony_ci hndl->params.last_frame = SANE_TRUE; 1669141cc406Sopenharmony_ci 1670141cc406Sopenharmony_ci hndl->params.lines = (hndl->bottomY - hndl->topY) * hndl->res / 1671141cc406Sopenharmony_ci hndl->dev->maxres; 1672141cc406Sopenharmony_ci } 1673141cc406Sopenharmony_ci else 1674141cc406Sopenharmony_ci DBG (2, "sane_get_parameters: can't set parameters while scanning\n"); 1675141cc406Sopenharmony_ci 1676141cc406Sopenharmony_ci if (params != NULL) 1677141cc406Sopenharmony_ci *params = hndl->params; 1678141cc406Sopenharmony_ci 1679141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1680141cc406Sopenharmony_ci 1681141cc406Sopenharmony_ci} 1682141cc406Sopenharmony_ci 1683141cc406Sopenharmony_ci 1684141cc406Sopenharmony_ci/* sane_start: 1685141cc406Sopenharmony_ci * starts the scan. data acquisition will start immediately 1686141cc406Sopenharmony_ci * 1687141cc406Sopenharmony_ci * Description: 1688141cc406Sopenharmony_ci * 1689141cc406Sopenharmony_ci */ 1690141cc406Sopenharmony_ciSANE_Status 1691141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1692141cc406Sopenharmony_ci{ 1693141cc406Sopenharmony_ci Mustek_pp_Handle *hndl = handle; 1694141cc406Sopenharmony_ci int pipeline[2]; 1695141cc406Sopenharmony_ci 1696141cc406Sopenharmony_ci if (hndl->state == STATE_SCANNING) { 1697141cc406Sopenharmony_ci DBG (2, "sane_start: device is already scanning\n"); 1698141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1699141cc406Sopenharmony_ci 1700141cc406Sopenharmony_ci } 1701141cc406Sopenharmony_ci 1702141cc406Sopenharmony_ci sane_get_parameters (hndl, NULL); 1703141cc406Sopenharmony_ci 1704141cc406Sopenharmony_ci if (pipe(pipeline) < 0) { 1705141cc406Sopenharmony_ci DBG (1, "sane_start: could not initialize pipe (%s)\n", 1706141cc406Sopenharmony_ci strerror(errno)); 1707141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1708141cc406Sopenharmony_ci } 1709141cc406Sopenharmony_ci 1710141cc406Sopenharmony_ci hndl->reader = fork(); 1711141cc406Sopenharmony_ci 1712141cc406Sopenharmony_ci if (hndl->reader == 0) { 1713141cc406Sopenharmony_ci 1714141cc406Sopenharmony_ci sigset_t ignore_set; 1715141cc406Sopenharmony_ci struct SIGACTION act; 1716141cc406Sopenharmony_ci 1717141cc406Sopenharmony_ci close (pipeline[0]); 1718141cc406Sopenharmony_ci 1719141cc406Sopenharmony_ci sigfillset (&ignore_set); 1720141cc406Sopenharmony_ci sigdelset (&ignore_set, SIGTERM); 1721141cc406Sopenharmony_ci sigprocmask (SIG_SETMASK, &ignore_set, NULL); 1722141cc406Sopenharmony_ci 1723141cc406Sopenharmony_ci memset (&act, 0, sizeof(act)); 1724141cc406Sopenharmony_ci sigaction (SIGTERM, &act, NULL); 1725141cc406Sopenharmony_ci 1726141cc406Sopenharmony_ci _exit (reader_process (hndl, pipeline[1])); 1727141cc406Sopenharmony_ci 1728141cc406Sopenharmony_ci } 1729141cc406Sopenharmony_ci 1730141cc406Sopenharmony_ci close (pipeline[1]); 1731141cc406Sopenharmony_ci 1732141cc406Sopenharmony_ci hndl->pipe = pipeline[0]; 1733141cc406Sopenharmony_ci 1734141cc406Sopenharmony_ci hndl->state = STATE_SCANNING; 1735141cc406Sopenharmony_ci 1736141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1737141cc406Sopenharmony_ci 1738141cc406Sopenharmony_ci} 1739141cc406Sopenharmony_ci 1740141cc406Sopenharmony_ci 1741141cc406Sopenharmony_ci/* sane_read: 1742141cc406Sopenharmony_ci * receives data from pipeline and passes it to the caller 1743141cc406Sopenharmony_ci * 1744141cc406Sopenharmony_ci * Description: 1745141cc406Sopenharmony_ci * ditto 1746141cc406Sopenharmony_ci */ 1747141cc406Sopenharmony_ciSANE_Status 1748141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 1749141cc406Sopenharmony_ci SANE_Int * len) 1750141cc406Sopenharmony_ci{ 1751141cc406Sopenharmony_ci Mustek_pp_Handle *hndl = handle; 1752141cc406Sopenharmony_ci SANE_Int nread; 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci 1755141cc406Sopenharmony_ci if (hndl->state == STATE_CANCELLED) { 1756141cc406Sopenharmony_ci DBG (2, "sane_read: device already cancelled\n"); 1757141cc406Sopenharmony_ci do_eof (hndl); 1758141cc406Sopenharmony_ci hndl->state = STATE_IDLE; 1759141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1760141cc406Sopenharmony_ci } 1761141cc406Sopenharmony_ci 1762141cc406Sopenharmony_ci if (hndl->state != STATE_SCANNING) { 1763141cc406Sopenharmony_ci DBG (1, "sane_read: device isn't scanning\n"); 1764141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1765141cc406Sopenharmony_ci } 1766141cc406Sopenharmony_ci 1767141cc406Sopenharmony_ci 1768141cc406Sopenharmony_ci *len = nread = 0; 1769141cc406Sopenharmony_ci 1770141cc406Sopenharmony_ci while (*len < max_len) { 1771141cc406Sopenharmony_ci 1772141cc406Sopenharmony_ci nread = read(hndl->pipe, buf + *len, max_len - *len); 1773141cc406Sopenharmony_ci 1774141cc406Sopenharmony_ci if (hndl->state == STATE_CANCELLED) { 1775141cc406Sopenharmony_ci 1776141cc406Sopenharmony_ci *len = 0; 1777141cc406Sopenharmony_ci DBG(3, "sane_read: scan was cancelled\n"); 1778141cc406Sopenharmony_ci 1779141cc406Sopenharmony_ci do_eof (hndl); 1780141cc406Sopenharmony_ci hndl->state = STATE_IDLE; 1781141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1782141cc406Sopenharmony_ci 1783141cc406Sopenharmony_ci } 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci if (nread < 0) { 1786141cc406Sopenharmony_ci 1787141cc406Sopenharmony_ci if (errno == EAGAIN) { 1788141cc406Sopenharmony_ci 1789141cc406Sopenharmony_ci if (*len == 0) 1790141cc406Sopenharmony_ci DBG(3, "sane_read: no data at the moment\n"); 1791141cc406Sopenharmony_ci else 1792141cc406Sopenharmony_ci DBG(3, "sane_read: %d bytes read\n", *len); 1793141cc406Sopenharmony_ci 1794141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1795141cc406Sopenharmony_ci 1796141cc406Sopenharmony_ci } else { 1797141cc406Sopenharmony_ci 1798141cc406Sopenharmony_ci DBG(1, "sane_read: IO error (%s)\n", strerror(errno)); 1799141cc406Sopenharmony_ci 1800141cc406Sopenharmony_ci hndl->state = STATE_IDLE; 1801141cc406Sopenharmony_ci do_stop(hndl); 1802141cc406Sopenharmony_ci 1803141cc406Sopenharmony_ci do_eof (hndl); 1804141cc406Sopenharmony_ci 1805141cc406Sopenharmony_ci *len = 0; 1806141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1807141cc406Sopenharmony_ci 1808141cc406Sopenharmony_ci } 1809141cc406Sopenharmony_ci } 1810141cc406Sopenharmony_ci 1811141cc406Sopenharmony_ci *len += nread; 1812141cc406Sopenharmony_ci 1813141cc406Sopenharmony_ci if (nread == 0) { 1814141cc406Sopenharmony_ci 1815141cc406Sopenharmony_ci if (*len == 0) { 1816141cc406Sopenharmony_ci 1817141cc406Sopenharmony_ci DBG (3, "sane_read: read finished\n"); 1818141cc406Sopenharmony_ci do_stop(hndl); 1819141cc406Sopenharmony_ci 1820141cc406Sopenharmony_ci hndl->state = STATE_IDLE; 1821141cc406Sopenharmony_ci 1822141cc406Sopenharmony_ci return do_eof(hndl); 1823141cc406Sopenharmony_ci 1824141cc406Sopenharmony_ci } 1825141cc406Sopenharmony_ci 1826141cc406Sopenharmony_ci DBG(3, "sane_read: read last buffer of %d bytes\n", 1827141cc406Sopenharmony_ci *len); 1828141cc406Sopenharmony_ci 1829141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1830141cc406Sopenharmony_ci 1831141cc406Sopenharmony_ci } 1832141cc406Sopenharmony_ci 1833141cc406Sopenharmony_ci } 1834141cc406Sopenharmony_ci 1835141cc406Sopenharmony_ci DBG(3, "sane_read: read full buffer of %d bytes\n", *len); 1836141cc406Sopenharmony_ci 1837141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1838141cc406Sopenharmony_ci} 1839141cc406Sopenharmony_ci 1840141cc406Sopenharmony_ci 1841141cc406Sopenharmony_ci/* sane_cancel: 1842141cc406Sopenharmony_ci * stops a scan and ends the reader process 1843141cc406Sopenharmony_ci * 1844141cc406Sopenharmony_ci * Description: 1845141cc406Sopenharmony_ci * 1846141cc406Sopenharmony_ci */ 1847141cc406Sopenharmony_civoid 1848141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 1849141cc406Sopenharmony_ci{ 1850141cc406Sopenharmony_ci Mustek_pp_Handle *hndl = handle; 1851141cc406Sopenharmony_ci 1852141cc406Sopenharmony_ci if (hndl->state != STATE_SCANNING) 1853141cc406Sopenharmony_ci return; 1854141cc406Sopenharmony_ci 1855141cc406Sopenharmony_ci hndl->state = STATE_CANCELLED; 1856141cc406Sopenharmony_ci 1857141cc406Sopenharmony_ci do_stop (hndl); 1858141cc406Sopenharmony_ci 1859141cc406Sopenharmony_ci} 1860141cc406Sopenharmony_ci 1861141cc406Sopenharmony_ci 1862141cc406Sopenharmony_ci/* sane_set_io_mode: 1863141cc406Sopenharmony_ci * toggles between blocking and non-blocking reading 1864141cc406Sopenharmony_ci * 1865141cc406Sopenharmony_ci * Description: 1866141cc406Sopenharmony_ci * 1867141cc406Sopenharmony_ci */ 1868141cc406Sopenharmony_ciSANE_Status 1869141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 1870141cc406Sopenharmony_ci{ 1871141cc406Sopenharmony_ci 1872141cc406Sopenharmony_ci Mustek_pp_Handle *hndl=handle; 1873141cc406Sopenharmony_ci 1874141cc406Sopenharmony_ci if (hndl->state != STATE_SCANNING) 1875141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci 1878141cc406Sopenharmony_ci if (fcntl (hndl->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { 1879141cc406Sopenharmony_ci 1880141cc406Sopenharmony_ci DBG(1, "sane_set_io_mode: can't set io mode\n"); 1881141cc406Sopenharmony_ci 1882141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1883141cc406Sopenharmony_ci 1884141cc406Sopenharmony_ci } 1885141cc406Sopenharmony_ci 1886141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1887141cc406Sopenharmony_ci} 1888141cc406Sopenharmony_ci 1889141cc406Sopenharmony_ci 1890141cc406Sopenharmony_ci/* sane_get_select_fd: 1891141cc406Sopenharmony_ci * returns the pipeline fd for direct reading 1892141cc406Sopenharmony_ci * 1893141cc406Sopenharmony_ci * Description: 1894141cc406Sopenharmony_ci * to allow the frontend to receive the data directly it 1895141cc406Sopenharmony_ci * can read from the pipeline itself 1896141cc406Sopenharmony_ci */ 1897141cc406Sopenharmony_ciSANE_Status 1898141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 1899141cc406Sopenharmony_ci{ 1900141cc406Sopenharmony_ci Mustek_pp_Handle *hndl=handle; 1901141cc406Sopenharmony_ci 1902141cc406Sopenharmony_ci if (hndl->state != STATE_SCANNING) 1903141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1904141cc406Sopenharmony_ci 1905141cc406Sopenharmony_ci *fd = hndl->pipe; 1906141cc406Sopenharmony_ci 1907141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1908141cc406Sopenharmony_ci} 1909141cc406Sopenharmony_ci 1910141cc406Sopenharmony_ci/* include drivers */ 1911141cc406Sopenharmony_ci#include "mustek_pp_decl.h" 1912141cc406Sopenharmony_ci#include "mustek_pp_null.c" 1913141cc406Sopenharmony_ci#include "mustek_pp_cis.h" 1914141cc406Sopenharmony_ci#include "mustek_pp_cis.c" 1915141cc406Sopenharmony_ci#include "mustek_pp_ccd300.h" 1916141cc406Sopenharmony_ci#include "mustek_pp_ccd300.c" 1917