1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 2001-2012 Stéphane Voltz <stef.dev@free.fr> 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 Umax PP flatbed scanners. */ 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci/* CREDITS: 42141cc406Sopenharmony_ci Started by being a mere copy of mustek_pp 43141cc406Sopenharmony_ci by Jochen Eisinger <jochen.eisinger@gmx.net> 44141cc406Sopenharmony_ci then evolved in its own thing 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci support for the 610P has been made possible thank to an hardware donation 47141cc406Sopenharmony_ci from William Stuart 48141cc406Sopenharmony_ci */ 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci#include "../include/sane/config.h" 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci#include <ctype.h> 54141cc406Sopenharmony_ci#include <errno.h> 55141cc406Sopenharmony_ci#include <limits.h> 56141cc406Sopenharmony_ci#include <stdio.h> 57141cc406Sopenharmony_ci#include <stdlib.h> 58141cc406Sopenharmony_ci#include <string.h> 59141cc406Sopenharmony_ci#ifdef HAVE_UNISTD_H 60141cc406Sopenharmony_ci#include <unistd.h> 61141cc406Sopenharmony_ci#endif 62141cc406Sopenharmony_ci#include <math.h> 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 65141cc406Sopenharmony_ci#include <sys/time.h> 66141cc406Sopenharmony_ci#endif 67141cc406Sopenharmony_ci#ifdef HAVE_SYS_TYPES_H 68141cc406Sopenharmony_ci#include <sys/types.h> 69141cc406Sopenharmony_ci#endif 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci#define DEBUG_NOT_STATIC 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_ci#include "../include/sane/sane.h" 74141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 75141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 76141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci#define BACKEND_NAME umax_pp 79141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci#include "umax_pp_mid.h" 82141cc406Sopenharmony_ci#include "umax_pp.h" 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci#ifdef DMALLOC 85141cc406Sopenharmony_ci#include "dmalloc.h" 86141cc406Sopenharmony_ci#endif 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci#define UMAX_PP_CONFIG_FILE "umax_pp.conf" 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci#define MIN(a,b) ((a) < (b) ? (a) : (b)) 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci/* DEBUG 94141cc406Sopenharmony_ci * for debug output, set SANE_DEBUG_UMAX_PP to 95141cc406Sopenharmony_ci * 0 for nothing 96141cc406Sopenharmony_ci * 1 for errors 97141cc406Sopenharmony_ci * 2 for warnings 98141cc406Sopenharmony_ci * 3 for additional information 99141cc406Sopenharmony_ci * 4 for debug information 100141cc406Sopenharmony_ci * 5 for code flow protocol (there isn't any) 101141cc406Sopenharmony_ci * 129 if you want to know which parameters are unused 102141cc406Sopenharmony_ci */ 103141cc406Sopenharmony_ci 104141cc406Sopenharmony_ci#define UMAX_PP_BUILD 2301 105141cc406Sopenharmony_ci#define UMAX_PP_STATE "release" 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_cistatic int num_devices = 0; 108141cc406Sopenharmony_cistatic Umax_PP_Descriptor *devlist = NULL; 109141cc406Sopenharmony_cistatic const SANE_Device **devarray = NULL; 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_cistatic Umax_PP_Device *first_dev = NULL; 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci/* 2 Meg scan buffer */ 115141cc406Sopenharmony_cistatic SANE_Word buf_size = 2048 * 1024; 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_cistatic SANE_Word red_gain = 0; 118141cc406Sopenharmony_cistatic SANE_Word green_gain = 0; 119141cc406Sopenharmony_cistatic SANE_Word blue_gain = 0; 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_cistatic SANE_Word red_offset = 0; 122141cc406Sopenharmony_cistatic SANE_Word green_offset = 0; 123141cc406Sopenharmony_cistatic SANE_Word blue_offset = 0; 124141cc406Sopenharmony_cistatic SANE_Char scanner_vendor[128]=""; 125141cc406Sopenharmony_cistatic SANE_Char scanner_name[128]=""; 126141cc406Sopenharmony_cistatic SANE_Char scanner_model[128]=""; 127141cc406Sopenharmony_cistatic SANE_Char astra[128]; 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] = { 132141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 133141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 134141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 135141cc406Sopenharmony_ci 0 136141cc406Sopenharmony_ci}; 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_cistatic const SANE_Range u4_range = { 139141cc406Sopenharmony_ci 0, /* minimum */ 140141cc406Sopenharmony_ci 15, /* maximum */ 141141cc406Sopenharmony_ci 0 /* quantization */ 142141cc406Sopenharmony_ci}; 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_cistatic const SANE_Range u8_range = { 145141cc406Sopenharmony_ci 0, /* minimum */ 146141cc406Sopenharmony_ci 255, /* maximum */ 147141cc406Sopenharmony_ci 0 /* quantization */ 148141cc406Sopenharmony_ci}; 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci/* range for int value in [0-15] */ 151141cc406Sopenharmony_cistatic const SANE_Range value16_range = { 152141cc406Sopenharmony_ci 0, /* minimum */ 153141cc406Sopenharmony_ci 15, /* maximum */ 154141cc406Sopenharmony_ci 1 /* quantization */ 155141cc406Sopenharmony_ci}; 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci/* range for buffer size */ 158141cc406Sopenharmony_cistatic const SANE_Range buffer_range = { 159141cc406Sopenharmony_ci 2048, /* minimum */ 160141cc406Sopenharmony_ci 4096 * 4096, /* maximum */ 161141cc406Sopenharmony_ci 1 /* quantization */ 162141cc406Sopenharmony_ci}; 163141cc406Sopenharmony_ci 164141cc406Sopenharmony_ci/* list of astra models */ 165141cc406Sopenharmony_cistatic const SANE_String_Const astra_models[] = 166141cc406Sopenharmony_ci { "610", "1220", "1600", "2000", NULL }; 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci#define UMAX_PP_CHANNEL_RED 0 170141cc406Sopenharmony_ci#define UMAX_PP_CHANNEL_GREEN 1 171141cc406Sopenharmony_ci#define UMAX_PP_CHANNEL_BLUE 2 172141cc406Sopenharmony_ci#define UMAX_PP_CHANNEL_GRAY 1 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci#define UMAX_PP_STATE_SCANNING 2 175141cc406Sopenharmony_ci#define UMAX_PP_STATE_CANCELLED 1 176141cc406Sopenharmony_ci#define UMAX_PP_STATE_IDLE 0 177141cc406Sopenharmony_ci 178141cc406Sopenharmony_ci#define UMAX_PP_MODE_LINEART 0 179141cc406Sopenharmony_ci#define UMAX_PP_MODE_GRAYSCALE 1 180141cc406Sopenharmony_ci#define UMAX_PP_MODE_COLOR 2 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci#define MM_TO_PIXEL(mm, res) (SANE_UNFIX(mm) * (float )res / MM_PER_INCH) 183141cc406Sopenharmony_ci#define PIXEL_TO_MM(px, res) (SANE_FIX((float )(px * MM_PER_INCH / (res / 10)) / 10.0)) 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci#define UMAX_PP_DEFAULT_PORT "/dev/parport0" 186141cc406Sopenharmony_ci 187141cc406Sopenharmony_ci#define UMAX_PP_RESERVE 259200 188141cc406Sopenharmony_ci 189141cc406Sopenharmony_ci/* 190141cc406Sopenharmony_ci * devname may be either an hardware address for direct I/O (0x378 for instance) 191141cc406Sopenharmony_ci * or the device name used by ppdev on linux systems (/dev/parport0 ) 192141cc406Sopenharmony_ci */ 193141cc406Sopenharmony_ci 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_cistatic SANE_Status 196141cc406Sopenharmony_ciumax_pp_attach (SANEI_Config * config, const char *devname) 197141cc406Sopenharmony_ci{ 198141cc406Sopenharmony_ci Umax_PP_Descriptor *dev; 199141cc406Sopenharmony_ci int i; 200141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 201141cc406Sopenharmony_ci int ret, prt = 0, mdl; 202141cc406Sopenharmony_ci char model[32]; 203141cc406Sopenharmony_ci const char *name = NULL; 204141cc406Sopenharmony_ci const char *val; 205141cc406Sopenharmony_ci 206141cc406Sopenharmony_ci if (!devname || (strlen (devname) < 3)) 207141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 208141cc406Sopenharmony_ci 209141cc406Sopenharmony_ci sanei_umax_pp_setastra (atoi((SANE_Char *) config->values[CFG_ASTRA])); 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci /* if the name begins with a slash, it's a device, else it's an addr */ 212141cc406Sopenharmony_ci if ((devname[0] == '/')) 213141cc406Sopenharmony_ci { 214141cc406Sopenharmony_ci name = devname; 215141cc406Sopenharmony_ci } 216141cc406Sopenharmony_ci else 217141cc406Sopenharmony_ci { 218141cc406Sopenharmony_ci if ((devname[0] == '0') 219141cc406Sopenharmony_ci && ((devname[1] == 'x') || (devname[1] == 'X'))) 220141cc406Sopenharmony_ci prt = strtol (devname + 2, NULL, 16); 221141cc406Sopenharmony_ci else 222141cc406Sopenharmony_ci prt = atoi (devname); 223141cc406Sopenharmony_ci } 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci for (i = 0; i < num_devices; i++) 226141cc406Sopenharmony_ci { 227141cc406Sopenharmony_ci if (devname[0] == '/') 228141cc406Sopenharmony_ci { 229141cc406Sopenharmony_ci if (strcmp (devlist[i].ppdevice, devname) == 0) 230141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 231141cc406Sopenharmony_ci } 232141cc406Sopenharmony_ci else 233141cc406Sopenharmony_ci { 234141cc406Sopenharmony_ci if (strcmp (devlist[i].port, devname) == 0) 235141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 236141cc406Sopenharmony_ci } 237141cc406Sopenharmony_ci } 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci ret = sanei_umax_pp_attach (prt, name); 240141cc406Sopenharmony_ci switch (ret) 241141cc406Sopenharmony_ci { 242141cc406Sopenharmony_ci case UMAX1220P_OK: 243141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 244141cc406Sopenharmony_ci break; 245141cc406Sopenharmony_ci case UMAX1220P_BUSY: 246141cc406Sopenharmony_ci status = SANE_STATUS_DEVICE_BUSY; 247141cc406Sopenharmony_ci break; 248141cc406Sopenharmony_ci case UMAX1220P_TRANSPORT_FAILED: 249141cc406Sopenharmony_ci DBG (1, "umax_pp_attach: failed to init transport layer on %s\n", 250141cc406Sopenharmony_ci devname); 251141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 252141cc406Sopenharmony_ci break; 253141cc406Sopenharmony_ci case UMAX1220P_PROBE_FAILED: 254141cc406Sopenharmony_ci DBG (1, "umax_pp_attach: failed to probe scanner on %s\n", devname); 255141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 256141cc406Sopenharmony_ci break; 257141cc406Sopenharmony_ci } 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 260141cc406Sopenharmony_ci { 261141cc406Sopenharmony_ci DBG (2, "umax_pp_attach: couldn't attach to `%s' (%s)\n", devname, 262141cc406Sopenharmony_ci sane_strstatus (status)); 263141cc406Sopenharmony_ci DEBUG (); 264141cc406Sopenharmony_ci return status; 265141cc406Sopenharmony_ci } 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci /* now look for the model */ 269141cc406Sopenharmony_ci do 270141cc406Sopenharmony_ci { 271141cc406Sopenharmony_ci ret = sanei_umax_pp_model (prt, &mdl); 272141cc406Sopenharmony_ci if (ret != UMAX1220P_OK) 273141cc406Sopenharmony_ci { 274141cc406Sopenharmony_ci DBG (1, "umax_pp_attach: waiting for busy scanner on %s\n", 275141cc406Sopenharmony_ci devname); 276141cc406Sopenharmony_ci } 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci while (ret == UMAX1220P_BUSY); 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci if (ret != UMAX1220P_OK) 281141cc406Sopenharmony_ci { 282141cc406Sopenharmony_ci DBG (1, "umax_pp_attach: failed to recognize scanner model on %s\n", 283141cc406Sopenharmony_ci devname); 284141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 285141cc406Sopenharmony_ci } 286141cc406Sopenharmony_ci snprintf (model, sizeof(model), "Astra %dP", mdl); 287141cc406Sopenharmony_ci 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci dev = malloc (sizeof (Umax_PP_Descriptor) * (num_devices + 1)); 290141cc406Sopenharmony_ci 291141cc406Sopenharmony_ci if (dev == NULL) 292141cc406Sopenharmony_ci { 293141cc406Sopenharmony_ci DBG (2, "umax_pp_attach: not enough memory for device descriptor\n"); 294141cc406Sopenharmony_ci DEBUG (); 295141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 296141cc406Sopenharmony_ci } 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci memset (dev, 0, sizeof (Umax_PP_Descriptor) * (num_devices + 1)); 299141cc406Sopenharmony_ci 300141cc406Sopenharmony_ci if (num_devices > 0) 301141cc406Sopenharmony_ci { 302141cc406Sopenharmony_ci memcpy (dev + 1, devlist, sizeof (Umax_PP_Descriptor) * (num_devices)); 303141cc406Sopenharmony_ci free (devlist); 304141cc406Sopenharmony_ci } 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci devlist = dev; 307141cc406Sopenharmony_ci num_devices++; 308141cc406Sopenharmony_ci 309141cc406Sopenharmony_ci /* if there are user provided values, use them */ 310141cc406Sopenharmony_ci val=(const SANE_Char *) config->values[CFG_NAME]; 311141cc406Sopenharmony_ci if(strlen(val)==0) 312141cc406Sopenharmony_ci dev->sane.name = strdup (devname); 313141cc406Sopenharmony_ci else 314141cc406Sopenharmony_ci dev->sane.name = strdup (val); 315141cc406Sopenharmony_ci val=(const SANE_Char *) config->values[CFG_VENDOR]; 316141cc406Sopenharmony_ci if(strlen(val)==0) 317141cc406Sopenharmony_ci dev->sane.vendor = strdup ("UMAX"); 318141cc406Sopenharmony_ci else 319141cc406Sopenharmony_ci dev->sane.vendor = strdup (val); 320141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_ci if (devname[0] == '/') 323141cc406Sopenharmony_ci dev->ppdevice = strdup (devname); 324141cc406Sopenharmony_ci else 325141cc406Sopenharmony_ci dev->port = strdup (devname); 326141cc406Sopenharmony_ci dev->buf_size = buf_size; 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci if (mdl > 610) 329141cc406Sopenharmony_ci { /* Astra 1220, 1600 and 2000 */ 330141cc406Sopenharmony_ci dev->max_res = 1200; 331141cc406Sopenharmony_ci dev->ccd_res = 600; 332141cc406Sopenharmony_ci dev->max_h_size = 5100; 333141cc406Sopenharmony_ci dev->max_v_size = 7000 - 8; /* -8: workaround 'y overflow bug at 600 dpi' */ 334141cc406Sopenharmony_ci } 335141cc406Sopenharmony_ci else 336141cc406Sopenharmony_ci { /* Astra 610 */ 337141cc406Sopenharmony_ci dev->max_res = 600; 338141cc406Sopenharmony_ci dev->ccd_res = 300; 339141cc406Sopenharmony_ci dev->max_h_size = 2550; 340141cc406Sopenharmony_ci dev->max_v_size = 3500; 341141cc406Sopenharmony_ci } 342141cc406Sopenharmony_ci val=(const SANE_Char *) config->values[CFG_MODEL]; 343141cc406Sopenharmony_ci if(strlen(val)==0) 344141cc406Sopenharmony_ci dev->sane.model = strdup (model); 345141cc406Sopenharmony_ci else 346141cc406Sopenharmony_ci dev->sane.model = strdup (val); 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci DBG (3, "umax_pp_attach: device %s attached\n", devname); 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 352141cc406Sopenharmony_ci} 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_ci/* 355141cc406Sopenharmony_ci * walk a port list and try to attach to them 356141cc406Sopenharmony_ci * 357141cc406Sopenharmony_ci */ 358141cc406Sopenharmony_cistatic SANE_Int 359141cc406Sopenharmony_ciumax_pp_try_ports (SANEI_Config * config, char **ports) 360141cc406Sopenharmony_ci{ 361141cc406Sopenharmony_ci int i; 362141cc406Sopenharmony_ci int rc = SANE_STATUS_INVAL; 363141cc406Sopenharmony_ci 364141cc406Sopenharmony_ci if (ports != NULL) 365141cc406Sopenharmony_ci { 366141cc406Sopenharmony_ci i = 0; 367141cc406Sopenharmony_ci rc = SANE_STATUS_INVAL; 368141cc406Sopenharmony_ci while (ports[i] != NULL) 369141cc406Sopenharmony_ci { 370141cc406Sopenharmony_ci if (rc != SANE_STATUS_GOOD) 371141cc406Sopenharmony_ci { 372141cc406Sopenharmony_ci DBG (3, "umax_pp_try_ports: trying port `%s'\n", ports[i]); 373141cc406Sopenharmony_ci rc = umax_pp_attach (config, ports[i]); 374141cc406Sopenharmony_ci if (rc != SANE_STATUS_GOOD) 375141cc406Sopenharmony_ci DBG (3, "umax_pp_try_ports: couldn't attach to port `%s'\n", 376141cc406Sopenharmony_ci ports[i]); 377141cc406Sopenharmony_ci else 378141cc406Sopenharmony_ci DBG (3, 379141cc406Sopenharmony_ci "umax_pp_try_ports: attach to port `%s' successful\n", 380141cc406Sopenharmony_ci ports[i]); 381141cc406Sopenharmony_ci } 382141cc406Sopenharmony_ci free (ports[i]); 383141cc406Sopenharmony_ci i++; 384141cc406Sopenharmony_ci } 385141cc406Sopenharmony_ci free (ports); 386141cc406Sopenharmony_ci } 387141cc406Sopenharmony_ci return rc; 388141cc406Sopenharmony_ci} 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci/* 391141cc406Sopenharmony_ci * attempt to auto detect right parallel port 392141cc406Sopenharmony_ci * if safe set to SANE_TRUE, no direct hardware access 393141cc406Sopenharmony_ci * is tried 394141cc406Sopenharmony_ci */ 395141cc406Sopenharmony_cistatic SANE_Int 396141cc406Sopenharmony_ciumax_pp_auto_attach (SANEI_Config * config, SANE_Int safe) 397141cc406Sopenharmony_ci{ 398141cc406Sopenharmony_ci char **ports; 399141cc406Sopenharmony_ci int rc = SANE_STATUS_INVAL; 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci /* safe tests: user parallel port devices */ 402141cc406Sopenharmony_ci ports = sanei_parport_find_device (); 403141cc406Sopenharmony_ci if (ports != NULL) 404141cc406Sopenharmony_ci rc = umax_pp_try_ports (config, ports); 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci /* try for direct hardware access */ 407141cc406Sopenharmony_ci if ((safe != SANE_TRUE) && (rc != SANE_STATUS_GOOD)) 408141cc406Sopenharmony_ci { 409141cc406Sopenharmony_ci ports = sanei_parport_find_port (); 410141cc406Sopenharmony_ci if (ports != NULL) 411141cc406Sopenharmony_ci rc = umax_pp_try_ports (config, ports); 412141cc406Sopenharmony_ci } 413141cc406Sopenharmony_ci return rc; 414141cc406Sopenharmony_ci} 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci/** callback use by sanei_configure_attach, it is called with the 417141cc406Sopenharmony_ci * device name to use for attach try. 418141cc406Sopenharmony_ci */ 419141cc406Sopenharmony_cistatic SANE_Status 420141cc406Sopenharmony_ciumax_pp_configure_attach (SANEI_Config * config, const char *devname, 421141cc406Sopenharmony_ci void __sane_unused__ *data) 422141cc406Sopenharmony_ci{ 423141cc406Sopenharmony_ci const char *lp; 424141cc406Sopenharmony_ci SANE_Char *token; 425141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_INVAL; 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci /* check for mandatory 'port' token */ 428141cc406Sopenharmony_ci lp = sanei_config_get_string (devname, &token); 429141cc406Sopenharmony_ci if (strncmp (token, "port", 4) != 0) 430141cc406Sopenharmony_ci { 431141cc406Sopenharmony_ci DBG (3, "umax_pp_configure_attach: invalid port line `%s'\n", devname); 432141cc406Sopenharmony_ci free (token); 433141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 434141cc406Sopenharmony_ci } 435141cc406Sopenharmony_ci free (token); 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci /* get argument */ 438141cc406Sopenharmony_ci lp = sanei_config_get_string (lp, &token); 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci /* if "safe-auto" or "auto" devname, use umax_pp_attach_auto */ 441141cc406Sopenharmony_ci if (strncmp (token, "safe-auto", 9) == 0) 442141cc406Sopenharmony_ci { 443141cc406Sopenharmony_ci status = umax_pp_auto_attach (config, SANE_TRUE); 444141cc406Sopenharmony_ci } 445141cc406Sopenharmony_ci else if (strncmp (token, "auto", 4) == 0) 446141cc406Sopenharmony_ci { 447141cc406Sopenharmony_ci status = umax_pp_auto_attach (config, SANE_FALSE); 448141cc406Sopenharmony_ci } 449141cc406Sopenharmony_ci else 450141cc406Sopenharmony_ci { 451141cc406Sopenharmony_ci status = umax_pp_attach (config, token); 452141cc406Sopenharmony_ci } 453141cc406Sopenharmony_ci free (token); 454141cc406Sopenharmony_ci return status; 455141cc406Sopenharmony_ci} 456141cc406Sopenharmony_ci 457141cc406Sopenharmony_cistatic SANE_Int 458141cc406Sopenharmony_ciumax_pp_get_sync (SANE_Int dpi) 459141cc406Sopenharmony_ci{ 460141cc406Sopenharmony_ci /* delta between color frames */ 461141cc406Sopenharmony_ci if (sanei_umax_pp_getastra () > 610) 462141cc406Sopenharmony_ci { 463141cc406Sopenharmony_ci switch (dpi) 464141cc406Sopenharmony_ci { 465141cc406Sopenharmony_ci case 1200: 466141cc406Sopenharmony_ci return 8; 467141cc406Sopenharmony_ci case 600: 468141cc406Sopenharmony_ci return 4; 469141cc406Sopenharmony_ci case 300: 470141cc406Sopenharmony_ci return 2; 471141cc406Sopenharmony_ci case 150: 472141cc406Sopenharmony_ci return 1; 473141cc406Sopenharmony_ci default: 474141cc406Sopenharmony_ci return 0; 475141cc406Sopenharmony_ci } 476141cc406Sopenharmony_ci } 477141cc406Sopenharmony_ci else 478141cc406Sopenharmony_ci { 479141cc406Sopenharmony_ci switch (dpi) 480141cc406Sopenharmony_ci { 481141cc406Sopenharmony_ci case 600: 482141cc406Sopenharmony_ci return 16; 483141cc406Sopenharmony_ci case 300: 484141cc406Sopenharmony_ci return 8; /* 8 double-checked */ 485141cc406Sopenharmony_ci case 150: 486141cc406Sopenharmony_ci /* wrong: 2, 3, 5 487141cc406Sopenharmony_ci * double-checked : 4 488141cc406Sopenharmony_ci */ 489141cc406Sopenharmony_ci return 4; 490141cc406Sopenharmony_ci default: 491141cc406Sopenharmony_ci return 2; /* 2 double-checked */ 492141cc406Sopenharmony_ci } 493141cc406Sopenharmony_ci } 494141cc406Sopenharmony_ci} 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_cistatic SANE_Status 498141cc406Sopenharmony_ciinit_options (Umax_PP_Device * dev) 499141cc406Sopenharmony_ci{ 500141cc406Sopenharmony_ci int i; 501141cc406Sopenharmony_ci 502141cc406Sopenharmony_ci /* sets initial option value to zero */ 503141cc406Sopenharmony_ci memset (dev->opt, 0, sizeof (dev->opt)); 504141cc406Sopenharmony_ci memset (dev->val, 0, sizeof (dev->val)); 505141cc406Sopenharmony_ci 506141cc406Sopenharmony_ci for (i = 0; i < NUM_OPTIONS; ++i) 507141cc406Sopenharmony_ci { 508141cc406Sopenharmony_ci dev->opt[i].size = sizeof (SANE_Word); 509141cc406Sopenharmony_ci dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 510141cc406Sopenharmony_ci } 511141cc406Sopenharmony_ci 512141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 513141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 514141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 515141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 516141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 517141cc406Sopenharmony_ci dev->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci /* "Mode" group: */ 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; 522141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].name = ""; 523141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].desc = ""; 524141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 525141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].size = 0; 526141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 527141cc406Sopenharmony_ci 528141cc406Sopenharmony_ci /* scan mode */ 529141cc406Sopenharmony_ci dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 530141cc406Sopenharmony_ci dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 531141cc406Sopenharmony_ci dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 532141cc406Sopenharmony_ci dev->opt[OPT_MODE].type = SANE_TYPE_STRING; 533141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 534141cc406Sopenharmony_ci dev->opt[OPT_MODE].size = 10; 535141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint.string_list = mode_list; 536141cc406Sopenharmony_ci dev->val[OPT_MODE].s = strdup (mode_list[1]); 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci /* resolution */ 539141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 540141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 541141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 542141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; 543141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 544141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 545141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint.range = &dev->dpi_range; 546141cc406Sopenharmony_ci dev->val[OPT_RESOLUTION].w = dev->dpi_range.min; 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci /* preview */ 550141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 551141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 552141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 553141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 554141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].size = sizeof (SANE_Word); 555141cc406Sopenharmony_ci dev->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; 556141cc406Sopenharmony_ci dev->val[OPT_PREVIEW].w = SANE_FALSE; 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci /* gray preview */ 559141cc406Sopenharmony_ci dev->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; 560141cc406Sopenharmony_ci dev->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; 561141cc406Sopenharmony_ci dev->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; 562141cc406Sopenharmony_ci dev->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; 563141cc406Sopenharmony_ci dev->opt[OPT_GRAY_PREVIEW].size = sizeof (SANE_Word); 564141cc406Sopenharmony_ci dev->opt[OPT_GRAY_PREVIEW].unit = SANE_UNIT_NONE; 565141cc406Sopenharmony_ci dev->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci /* "Geometry" group: */ 568141cc406Sopenharmony_ci 569141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); 570141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].desc = ""; 571141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].name = ""; 572141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 573141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].size = 0; 574141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_ci /* top-left x */ 577141cc406Sopenharmony_ci dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 578141cc406Sopenharmony_ci dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 579141cc406Sopenharmony_ci dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 580141cc406Sopenharmony_ci dev->opt[OPT_TL_X].type = SANE_TYPE_INT; 581141cc406Sopenharmony_ci dev->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; 582141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 583141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint.range = &dev->x_range; 584141cc406Sopenharmony_ci dev->val[OPT_TL_X].w = 0; 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_ci /* top-left y */ 587141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 588141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 589141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 590141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].type = SANE_TYPE_INT; 591141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; 592141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 593141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint.range = &dev->y_range; 594141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = 0; 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci /* bottom-right x */ 597141cc406Sopenharmony_ci dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 598141cc406Sopenharmony_ci dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 599141cc406Sopenharmony_ci dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 600141cc406Sopenharmony_ci dev->opt[OPT_BR_X].type = SANE_TYPE_INT; 601141cc406Sopenharmony_ci dev->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; 602141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 603141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint.range = &dev->x_range; 604141cc406Sopenharmony_ci dev->val[OPT_BR_X].w = dev->x_range.max; 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_ci /* bottom-right y */ 607141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 608141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 609141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 610141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].type = SANE_TYPE_INT; 611141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; 612141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 613141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint.range = &dev->y_range; 614141cc406Sopenharmony_ci dev->val[OPT_BR_Y].w = dev->y_range.max; 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_ci /* "Enhancement" group: */ 617141cc406Sopenharmony_ci 618141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); 619141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 620141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].name = ""; 621141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 622141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; 623141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].cap |= SANE_CAP_ADVANCED; 624141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci /* lamp control */ 627141cc406Sopenharmony_ci dev->opt[OPT_LAMP_CONTROL].name = "lamp-control"; 628141cc406Sopenharmony_ci dev->opt[OPT_LAMP_CONTROL].title = SANE_I18N ("Lamp on"); 629141cc406Sopenharmony_ci dev->opt[OPT_LAMP_CONTROL].desc = SANE_I18N ("Sets lamp on/off"); 630141cc406Sopenharmony_ci dev->opt[OPT_LAMP_CONTROL].type = SANE_TYPE_BOOL; 631141cc406Sopenharmony_ci dev->opt[OPT_LAMP_CONTROL].size = sizeof (SANE_Word); 632141cc406Sopenharmony_ci dev->opt[OPT_LAMP_CONTROL].unit = SANE_UNIT_NONE; 633141cc406Sopenharmony_ci dev->val[OPT_LAMP_CONTROL].w = SANE_TRUE; 634141cc406Sopenharmony_ci dev->opt[OPT_LAMP_CONTROL].cap |= SANE_CAP_ADVANCED; 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_ci /* UTA control */ 637141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].name = "UTA-control"; 638141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].title = SANE_I18N ("UTA on"); 639141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].desc = SANE_I18N ("Sets UTA on/off"); 640141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].type = SANE_TYPE_BOOL; 641141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].size = sizeof (SANE_Word); 642141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].unit = SANE_UNIT_NONE; 643141cc406Sopenharmony_ci dev->val[OPT_UTA_CONTROL].w = SANE_TRUE; 644141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].cap |= SANE_CAP_ADVANCED | SANE_CAP_INACTIVE; 645141cc406Sopenharmony_ci 646141cc406Sopenharmony_ci /* custom-gamma table */ 647141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 648141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 649141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 650141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 651141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_ADVANCED; 652141cc406Sopenharmony_ci dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci /* grayscale gamma vector */ 655141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 656141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 657141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 658141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 659141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 660141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 661141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); 662141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 663141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; 664141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR].wa = &dev->gamma_table[0][0]; 665141cc406Sopenharmony_ci 666141cc406Sopenharmony_ci /* red gamma vector */ 667141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 668141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 669141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 670141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 671141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 672141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 673141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); 674141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 675141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; 676141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_R].wa = &dev->gamma_table[1][0]; 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci /* green gamma vector */ 679141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 680141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 681141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 682141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 683141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 684141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 685141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); 686141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 687141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; 688141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_G].wa = &dev->gamma_table[2][0]; 689141cc406Sopenharmony_ci 690141cc406Sopenharmony_ci /* blue gamma vector */ 691141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 692141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 693141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 694141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 695141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 696141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 697141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); 698141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 699141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; 700141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_B].wa = &dev->gamma_table[3][0]; 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_ci /* gain group */ 703141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].name = "manual-channel-gain"; 704141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].title = SANE_I18N ("Gain"); 705141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].desc = SANE_I18N ("Color channels gain settings"); 706141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].type = SANE_TYPE_BOOL; 707141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].cap |= SANE_CAP_ADVANCED; 708141cc406Sopenharmony_ci dev->val[OPT_MANUAL_GAIN].w = SANE_FALSE; 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci /* gray gain */ 711141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].name = "gray-gain"; 712141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].title = SANE_I18N ("Gray gain"); 713141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].desc = SANE_I18N ("Sets gray channel gain"); 714141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].type = SANE_TYPE_INT; 715141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 716141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].unit = SANE_UNIT_NONE; 717141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].size = sizeof (SANE_Int); 718141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 719141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].constraint.range = &u4_range; 720141cc406Sopenharmony_ci dev->val[OPT_GRAY_GAIN].w = dev->gray_gain; 721141cc406Sopenharmony_ci 722141cc406Sopenharmony_ci /* red gain */ 723141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].name = "red-gain"; 724141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].title = SANE_I18N ("Red gain"); 725141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].desc = SANE_I18N ("Sets red channel gain"); 726141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].type = SANE_TYPE_INT; 727141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 728141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].unit = SANE_UNIT_NONE; 729141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].size = sizeof (SANE_Int); 730141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 731141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].constraint.range = &u4_range; 732141cc406Sopenharmony_ci dev->val[OPT_RED_GAIN].w = dev->red_gain; 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci /* green gain */ 735141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].name = "green-gain"; 736141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].title = SANE_I18N ("Green gain"); 737141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].desc = SANE_I18N ("Sets green channel gain"); 738141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].type = SANE_TYPE_INT; 739141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 740141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].unit = SANE_UNIT_NONE; 741141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].size = sizeof (SANE_Int); 742141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 743141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].constraint.range = &u4_range; 744141cc406Sopenharmony_ci dev->val[OPT_GREEN_GAIN].w = dev->green_gain; 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci /* blue gain */ 747141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].name = "blue-gain"; 748141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].title = SANE_I18N ("Blue gain"); 749141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].desc = SANE_I18N ("Sets blue channel gain"); 750141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].type = SANE_TYPE_INT; 751141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 752141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].unit = SANE_UNIT_NONE; 753141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].size = sizeof (SANE_Int); 754141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 755141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].constraint.range = &u4_range; 756141cc406Sopenharmony_ci dev->val[OPT_BLUE_GAIN].w = dev->blue_gain; 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_ci /* offset group */ 759141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_OFFSET].name = "manual-offset"; 760141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_OFFSET].title = SANE_I18N ("Offset"); 761141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_OFFSET].desc = 762141cc406Sopenharmony_ci SANE_I18N ("Color channels offset settings"); 763141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_OFFSET].type = SANE_TYPE_BOOL; 764141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_OFFSET].cap |= SANE_CAP_ADVANCED; 765141cc406Sopenharmony_ci dev->val[OPT_MANUAL_OFFSET].w = SANE_FALSE; 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci /* gray offset */ 768141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].name = "gray-offset"; 769141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].title = SANE_I18N ("Gray offset"); 770141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].desc = SANE_I18N ("Sets gray channel offset"); 771141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].type = SANE_TYPE_INT; 772141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 773141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].unit = SANE_UNIT_NONE; 774141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].size = sizeof (SANE_Int); 775141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; 776141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].constraint.range = &u4_range; 777141cc406Sopenharmony_ci dev->val[OPT_GRAY_OFFSET].w = dev->gray_offset; 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci /* red offset */ 780141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].name = "red-offset"; 781141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].title = SANE_I18N ("Red offset"); 782141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].desc = SANE_I18N ("Sets red channel offset"); 783141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].type = SANE_TYPE_INT; 784141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 785141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].unit = SANE_UNIT_NONE; 786141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].size = sizeof (SANE_Int); 787141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; 788141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].constraint.range = &u4_range; 789141cc406Sopenharmony_ci dev->val[OPT_RED_OFFSET].w = dev->red_offset; 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_ci /* green offset */ 792141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].name = "green-offset"; 793141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].title = SANE_I18N ("Green offset"); 794141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].desc = SANE_I18N ("Sets green channel offset"); 795141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].type = SANE_TYPE_INT; 796141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 797141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].unit = SANE_UNIT_NONE; 798141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].size = sizeof (SANE_Int); 799141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; 800141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].constraint.range = &u4_range; 801141cc406Sopenharmony_ci dev->val[OPT_GREEN_OFFSET].w = dev->green_offset; 802141cc406Sopenharmony_ci 803141cc406Sopenharmony_ci /* blue offset */ 804141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].name = "blue-offset"; 805141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].title = SANE_I18N ("Blue offset"); 806141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].desc = SANE_I18N ("Sets blue channel offset"); 807141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].type = SANE_TYPE_INT; 808141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; 809141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].unit = SANE_UNIT_NONE; 810141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].size = sizeof (SANE_Int); 811141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; 812141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].constraint.range = &u4_range; 813141cc406Sopenharmony_ci dev->val[OPT_BLUE_OFFSET].w = dev->blue_offset; 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 816141cc406Sopenharmony_ci} 817141cc406Sopenharmony_ci 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ciSANE_Status 820141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 821141cc406Sopenharmony_ci{ 822141cc406Sopenharmony_ci SANE_Status status; 823141cc406Sopenharmony_ci SANEI_Config config; 824141cc406Sopenharmony_ci SANE_Option_Descriptor *options[NUM_CFG_OPTIONS]; 825141cc406Sopenharmony_ci void *values[NUM_CFG_OPTIONS]; 826141cc406Sopenharmony_ci int i = 0; 827141cc406Sopenharmony_ci 828141cc406Sopenharmony_ci DBG_INIT (); 829141cc406Sopenharmony_ci 830141cc406Sopenharmony_ci if (authorize != NULL) 831141cc406Sopenharmony_ci { 832141cc406Sopenharmony_ci DBG (2, "init: SANE_Auth_Callback not supported ...\n"); 833141cc406Sopenharmony_ci } 834141cc406Sopenharmony_ci 835141cc406Sopenharmony_ci if (version_code != NULL) 836141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, UMAX_PP_BUILD); 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci DBG (3, "init: SANE v%s, backend v%d.%d.%d-%s\n", VERSION, SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 839141cc406Sopenharmony_ci UMAX_PP_BUILD, UMAX_PP_STATE); 840141cc406Sopenharmony_ci 841141cc406Sopenharmony_ci /* set up configuration options to parse */ 842141cc406Sopenharmony_ci options[CFG_BUFFER] = 843141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 844141cc406Sopenharmony_ci options[CFG_BUFFER]->name = "buffer"; 845141cc406Sopenharmony_ci options[CFG_BUFFER]->type = SANE_TYPE_INT; 846141cc406Sopenharmony_ci options[CFG_BUFFER]->unit = SANE_UNIT_NONE; 847141cc406Sopenharmony_ci options[CFG_BUFFER]->size = sizeof (SANE_Word); 848141cc406Sopenharmony_ci options[CFG_BUFFER]->cap = SANE_CAP_SOFT_SELECT; 849141cc406Sopenharmony_ci options[CFG_BUFFER]->constraint_type = SANE_CONSTRAINT_RANGE; 850141cc406Sopenharmony_ci options[CFG_BUFFER]->constraint.range = &buffer_range; 851141cc406Sopenharmony_ci values[CFG_BUFFER] = &buf_size; 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ci options[CFG_RED_GAIN] = 854141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 855141cc406Sopenharmony_ci options[CFG_RED_GAIN]->name = "red-gain"; 856141cc406Sopenharmony_ci options[CFG_RED_GAIN]->type = SANE_TYPE_INT; 857141cc406Sopenharmony_ci options[CFG_RED_GAIN]->unit = SANE_UNIT_NONE; 858141cc406Sopenharmony_ci options[CFG_RED_GAIN]->size = sizeof (SANE_Word); 859141cc406Sopenharmony_ci options[CFG_RED_GAIN]->cap = SANE_CAP_SOFT_SELECT; 860141cc406Sopenharmony_ci options[CFG_RED_GAIN]->constraint_type = SANE_CONSTRAINT_RANGE; 861141cc406Sopenharmony_ci options[CFG_RED_GAIN]->constraint.range = &value16_range; 862141cc406Sopenharmony_ci values[CFG_RED_GAIN] = &red_gain; 863141cc406Sopenharmony_ci 864141cc406Sopenharmony_ci options[CFG_GREEN_GAIN] = 865141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 866141cc406Sopenharmony_ci options[CFG_GREEN_GAIN]->name = "green-gain"; 867141cc406Sopenharmony_ci options[CFG_GREEN_GAIN]->type = SANE_TYPE_INT; 868141cc406Sopenharmony_ci options[CFG_GREEN_GAIN]->unit = SANE_UNIT_NONE; 869141cc406Sopenharmony_ci options[CFG_GREEN_GAIN]->size = sizeof (SANE_Word); 870141cc406Sopenharmony_ci options[CFG_GREEN_GAIN]->cap = SANE_CAP_SOFT_SELECT; 871141cc406Sopenharmony_ci options[CFG_GREEN_GAIN]->constraint_type = SANE_CONSTRAINT_RANGE; 872141cc406Sopenharmony_ci options[CFG_GREEN_GAIN]->constraint.range = &value16_range; 873141cc406Sopenharmony_ci values[CFG_GREEN_GAIN] = &green_gain; 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci options[CFG_BLUE_GAIN] = 876141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 877141cc406Sopenharmony_ci options[CFG_BLUE_GAIN]->name = "blue-gain"; 878141cc406Sopenharmony_ci options[CFG_BLUE_GAIN]->type = SANE_TYPE_INT; 879141cc406Sopenharmony_ci options[CFG_BLUE_GAIN]->unit = SANE_UNIT_NONE; 880141cc406Sopenharmony_ci options[CFG_BLUE_GAIN]->size = sizeof (SANE_Word); 881141cc406Sopenharmony_ci options[CFG_BLUE_GAIN]->cap = SANE_CAP_SOFT_SELECT; 882141cc406Sopenharmony_ci options[CFG_BLUE_GAIN]->constraint_type = SANE_CONSTRAINT_RANGE; 883141cc406Sopenharmony_ci options[CFG_BLUE_GAIN]->constraint.range = &value16_range; 884141cc406Sopenharmony_ci values[CFG_BLUE_GAIN] = &blue_gain; 885141cc406Sopenharmony_ci 886141cc406Sopenharmony_ci options[CFG_RED_OFFSET] = 887141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 888141cc406Sopenharmony_ci options[CFG_RED_OFFSET]->name = "red-offset"; 889141cc406Sopenharmony_ci options[CFG_RED_OFFSET]->type = SANE_TYPE_INT; 890141cc406Sopenharmony_ci options[CFG_RED_OFFSET]->unit = SANE_UNIT_NONE; 891141cc406Sopenharmony_ci options[CFG_RED_OFFSET]->size = sizeof (SANE_Word); 892141cc406Sopenharmony_ci options[CFG_RED_OFFSET]->cap = SANE_CAP_SOFT_SELECT; 893141cc406Sopenharmony_ci options[CFG_RED_OFFSET]->constraint_type = SANE_CONSTRAINT_RANGE; 894141cc406Sopenharmony_ci options[CFG_RED_OFFSET]->constraint.range = &value16_range; 895141cc406Sopenharmony_ci values[CFG_RED_OFFSET] = &red_offset; 896141cc406Sopenharmony_ci 897141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET] = 898141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 899141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET]->name = "green-offset"; 900141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET]->type = SANE_TYPE_INT; 901141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET]->unit = SANE_UNIT_NONE; 902141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET]->size = sizeof (SANE_Word); 903141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET]->cap = SANE_CAP_SOFT_SELECT; 904141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET]->constraint_type = SANE_CONSTRAINT_RANGE; 905141cc406Sopenharmony_ci options[CFG_GREEN_OFFSET]->constraint.range = &value16_range; 906141cc406Sopenharmony_ci values[CFG_GREEN_OFFSET] = &green_offset; 907141cc406Sopenharmony_ci 908141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET] = 909141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 910141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET]->name = "blue-offset"; 911141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET]->type = SANE_TYPE_INT; 912141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET]->unit = SANE_UNIT_NONE; 913141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET]->size = sizeof (SANE_Word); 914141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET]->cap = SANE_CAP_SOFT_SELECT; 915141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET]->constraint_type = SANE_CONSTRAINT_RANGE; 916141cc406Sopenharmony_ci options[CFG_BLUE_OFFSET]->constraint.range = &value16_range; 917141cc406Sopenharmony_ci values[CFG_BLUE_OFFSET] = &blue_offset; 918141cc406Sopenharmony_ci 919141cc406Sopenharmony_ci options[CFG_VENDOR] = 920141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 921141cc406Sopenharmony_ci options[CFG_VENDOR]->name = "vendor"; 922141cc406Sopenharmony_ci options[CFG_VENDOR]->type = SANE_TYPE_STRING; 923141cc406Sopenharmony_ci options[CFG_VENDOR]->unit = SANE_UNIT_NONE; 924141cc406Sopenharmony_ci options[CFG_VENDOR]->size = 128; 925141cc406Sopenharmony_ci options[CFG_VENDOR]->cap = SANE_CAP_SOFT_SELECT; 926141cc406Sopenharmony_ci values[CFG_VENDOR] = scanner_vendor; 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci options[CFG_NAME] = 929141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 930141cc406Sopenharmony_ci options[CFG_NAME]->name = "name"; 931141cc406Sopenharmony_ci options[CFG_NAME]->type = SANE_TYPE_STRING; 932141cc406Sopenharmony_ci options[CFG_NAME]->unit = SANE_UNIT_NONE; 933141cc406Sopenharmony_ci options[CFG_NAME]->size = 128; 934141cc406Sopenharmony_ci options[CFG_NAME]->cap = SANE_CAP_SOFT_SELECT; 935141cc406Sopenharmony_ci values[CFG_NAME] = scanner_name; 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci options[CFG_MODEL] = 938141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 939141cc406Sopenharmony_ci options[CFG_MODEL]->name = "model"; 940141cc406Sopenharmony_ci options[CFG_MODEL]->type = SANE_TYPE_STRING; 941141cc406Sopenharmony_ci options[CFG_MODEL]->unit = SANE_UNIT_NONE; 942141cc406Sopenharmony_ci options[CFG_MODEL]->size = 128; 943141cc406Sopenharmony_ci options[CFG_MODEL]->cap = SANE_CAP_SOFT_SELECT; 944141cc406Sopenharmony_ci values[CFG_MODEL] = scanner_model; 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_ci options[CFG_ASTRA] = 947141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 948141cc406Sopenharmony_ci options[CFG_ASTRA]->name = "astra"; 949141cc406Sopenharmony_ci options[CFG_ASTRA]->type = SANE_TYPE_STRING; 950141cc406Sopenharmony_ci options[CFG_ASTRA]->unit = SANE_UNIT_NONE; 951141cc406Sopenharmony_ci options[CFG_ASTRA]->size = 128; 952141cc406Sopenharmony_ci options[CFG_ASTRA]->cap = SANE_CAP_SOFT_SELECT; 953141cc406Sopenharmony_ci options[CFG_ASTRA]->constraint_type = SANE_CONSTRAINT_STRING_LIST; 954141cc406Sopenharmony_ci options[CFG_ASTRA]->constraint.string_list = astra_models; 955141cc406Sopenharmony_ci values[CFG_ASTRA] = astra; 956141cc406Sopenharmony_ci 957141cc406Sopenharmony_ci config.descriptors = options; 958141cc406Sopenharmony_ci config.values = values; 959141cc406Sopenharmony_ci config.count = NUM_CFG_OPTIONS; 960141cc406Sopenharmony_ci 961141cc406Sopenharmony_ci /* generic configure and attach function */ 962141cc406Sopenharmony_ci status = sanei_configure_attach (UMAX_PP_CONFIG_FILE, &config, 963141cc406Sopenharmony_ci umax_pp_configure_attach, NULL); 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci /* free option descriptors */ 966141cc406Sopenharmony_ci for (i = 0; i < NUM_CFG_OPTIONS; i++) 967141cc406Sopenharmony_ci { 968141cc406Sopenharmony_ci free (options[i]); 969141cc406Sopenharmony_ci } 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci return status; 972141cc406Sopenharmony_ci} 973141cc406Sopenharmony_ci 974141cc406Sopenharmony_civoid 975141cc406Sopenharmony_cisane_exit (void) 976141cc406Sopenharmony_ci{ 977141cc406Sopenharmony_ci int i; 978141cc406Sopenharmony_ci Umax_PP_Device *dev; 979141cc406Sopenharmony_ci 980141cc406Sopenharmony_ci DBG (3, "sane_exit: (...)\n"); 981141cc406Sopenharmony_ci if (first_dev) 982141cc406Sopenharmony_ci DBG (3, "exit: closing open devices\n"); 983141cc406Sopenharmony_ci 984141cc406Sopenharmony_ci while (first_dev) 985141cc406Sopenharmony_ci { 986141cc406Sopenharmony_ci dev = first_dev; 987141cc406Sopenharmony_ci sane_close (dev); 988141cc406Sopenharmony_ci } 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci for (i = 0; i < num_devices; i++) 991141cc406Sopenharmony_ci { 992141cc406Sopenharmony_ci free (devlist[i].port); 993141cc406Sopenharmony_ci free ((void *) devlist[i].sane.name); 994141cc406Sopenharmony_ci free ((void *) devlist[i].sane.model); 995141cc406Sopenharmony_ci free ((void *) devlist[i].sane.vendor); 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci 998141cc406Sopenharmony_ci if (devlist != NULL) 999141cc406Sopenharmony_ci { 1000141cc406Sopenharmony_ci free (devlist); 1001141cc406Sopenharmony_ci devlist = NULL; 1002141cc406Sopenharmony_ci } 1003141cc406Sopenharmony_ci 1004141cc406Sopenharmony_ci if (devarray != NULL) 1005141cc406Sopenharmony_ci { 1006141cc406Sopenharmony_ci free (devarray); 1007141cc406Sopenharmony_ci devarray = NULL; 1008141cc406Sopenharmony_ci } 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci /* reset values */ 1011141cc406Sopenharmony_ci num_devices = 0; 1012141cc406Sopenharmony_ci first_dev = NULL; 1013141cc406Sopenharmony_ci 1014141cc406Sopenharmony_ci red_gain = 0; 1015141cc406Sopenharmony_ci green_gain = 0; 1016141cc406Sopenharmony_ci blue_gain = 0; 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci red_offset = 0; 1019141cc406Sopenharmony_ci green_offset = 0; 1020141cc406Sopenharmony_ci blue_offset = 0; 1021141cc406Sopenharmony_ci 1022141cc406Sopenharmony_ci} 1023141cc406Sopenharmony_ci 1024141cc406Sopenharmony_ciSANE_Status 1025141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 1026141cc406Sopenharmony_ci{ 1027141cc406Sopenharmony_ci int i; 1028141cc406Sopenharmony_ci 1029141cc406Sopenharmony_ci DBG (3, "get_devices\n"); 1030141cc406Sopenharmony_ci DBG (129, "unused arg: local_only = %d\n", (int) local_only); 1031141cc406Sopenharmony_ci 1032141cc406Sopenharmony_ci if (devarray != NULL) 1033141cc406Sopenharmony_ci { 1034141cc406Sopenharmony_ci free (devarray); 1035141cc406Sopenharmony_ci devarray = NULL; 1036141cc406Sopenharmony_ci } 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci devarray = malloc ((num_devices + 1) * sizeof (devarray[0])); 1039141cc406Sopenharmony_ci 1040141cc406Sopenharmony_ci if (devarray == NULL) 1041141cc406Sopenharmony_ci { 1042141cc406Sopenharmony_ci DBG (2, "get_devices: not enough memory for device list\n"); 1043141cc406Sopenharmony_ci DEBUG (); 1044141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1045141cc406Sopenharmony_ci } 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci for (i = 0; i < num_devices; i++) 1048141cc406Sopenharmony_ci devarray[i] = &devlist[i].sane; 1049141cc406Sopenharmony_ci 1050141cc406Sopenharmony_ci devarray[num_devices] = NULL; 1051141cc406Sopenharmony_ci *device_list = devarray; 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1054141cc406Sopenharmony_ci} 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_ciSANE_Status 1057141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 1058141cc406Sopenharmony_ci{ 1059141cc406Sopenharmony_ci Umax_PP_Device *dev; 1060141cc406Sopenharmony_ci Umax_PP_Descriptor *desc; 1061141cc406Sopenharmony_ci int i, j; 1062141cc406Sopenharmony_ci int rc, prt = 0; 1063141cc406Sopenharmony_ci char *name = NULL; 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci DBG (3, "open: device `%s'\n", devicename); 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci /* if no device given or 'umax_pp' default value given */ 1068141cc406Sopenharmony_ci if (devicename == NULL || devicename[0] == 0 1069141cc406Sopenharmony_ci || strncmp (devicename, "umax_pp", 7) == 0) 1070141cc406Sopenharmony_ci { 1071141cc406Sopenharmony_ci 1072141cc406Sopenharmony_ci if (num_devices == 0) 1073141cc406Sopenharmony_ci { 1074141cc406Sopenharmony_ci DBG (1, "open: no devices present\n"); 1075141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1076141cc406Sopenharmony_ci } 1077141cc406Sopenharmony_ci 1078141cc406Sopenharmony_ci DBG (3, "open: trying default device %s, port=%s,ppdev=%s\n", 1079141cc406Sopenharmony_ci devlist[0].sane.name, devlist[0].port, devlist[0].ppdevice); 1080141cc406Sopenharmony_ci if (devlist[0].port != NULL) 1081141cc406Sopenharmony_ci { 1082141cc406Sopenharmony_ci if ((devlist[0].port[0] == '0') 1083141cc406Sopenharmony_ci && ((devlist[0].port[1] == 'x') || (devlist[0].port[1] == 'X'))) 1084141cc406Sopenharmony_ci prt = strtol (devlist[0].port + 2, NULL, 16); 1085141cc406Sopenharmony_ci else 1086141cc406Sopenharmony_ci prt = atoi (devlist[0].port); 1087141cc406Sopenharmony_ci rc = sanei_umax_pp_open (prt, NULL); 1088141cc406Sopenharmony_ci } 1089141cc406Sopenharmony_ci else 1090141cc406Sopenharmony_ci { 1091141cc406Sopenharmony_ci rc = sanei_umax_pp_open (0, devlist[0].ppdevice); 1092141cc406Sopenharmony_ci } 1093141cc406Sopenharmony_ci desc = &devlist[0]; 1094141cc406Sopenharmony_ci } 1095141cc406Sopenharmony_ci else /* specific value */ 1096141cc406Sopenharmony_ci { 1097141cc406Sopenharmony_ci for (i = 0; i < num_devices; i++) 1098141cc406Sopenharmony_ci if (strcmp (devlist[i].sane.name, devicename) == 0) 1099141cc406Sopenharmony_ci break; 1100141cc406Sopenharmony_ci 1101141cc406Sopenharmony_ci if (i >= num_devices) 1102141cc406Sopenharmony_ci for (i = 0; i < num_devices; i++) 1103141cc406Sopenharmony_ci if (strcmp (devlist[i].port, devicename) == 0) 1104141cc406Sopenharmony_ci break; 1105141cc406Sopenharmony_ci 1106141cc406Sopenharmony_ci if (i >= num_devices) 1107141cc406Sopenharmony_ci { 1108141cc406Sopenharmony_ci DBG (2, "open: device doesn't exist\n"); 1109141cc406Sopenharmony_ci DEBUG (); 1110141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1111141cc406Sopenharmony_ci } 1112141cc406Sopenharmony_ci 1113141cc406Sopenharmony_ci desc = &devlist[i]; 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci if (devlist[i].ppdevice != NULL) 1116141cc406Sopenharmony_ci { 1117141cc406Sopenharmony_ci if (devlist[i].ppdevice[0] == '/') 1118141cc406Sopenharmony_ci { 1119141cc406Sopenharmony_ci name = devlist[i].ppdevice; 1120141cc406Sopenharmony_ci } 1121141cc406Sopenharmony_ci } 1122141cc406Sopenharmony_ci else 1123141cc406Sopenharmony_ci { 1124141cc406Sopenharmony_ci if ((devlist[i].port[0] == '0') 1125141cc406Sopenharmony_ci && ((devlist[i].port[1] == 'x') || (devlist[i].port[1] == 'X'))) 1126141cc406Sopenharmony_ci prt = strtol (devlist[i].port + 2, NULL, 16); 1127141cc406Sopenharmony_ci else 1128141cc406Sopenharmony_ci prt = atoi (devlist[i].port); 1129141cc406Sopenharmony_ci DBG (64, "open: devlist[i].port='%s' -> port=0x%X\n", 1130141cc406Sopenharmony_ci devlist[i].port, prt); 1131141cc406Sopenharmony_ci } 1132141cc406Sopenharmony_ci rc = sanei_umax_pp_open (prt, name); 1133141cc406Sopenharmony_ci } 1134141cc406Sopenharmony_ci 1135141cc406Sopenharmony_ci /* treat return code from open */ 1136141cc406Sopenharmony_ci switch (rc) 1137141cc406Sopenharmony_ci { 1138141cc406Sopenharmony_ci case UMAX1220P_TRANSPORT_FAILED: 1139141cc406Sopenharmony_ci if (name == NULL) 1140141cc406Sopenharmony_ci { 1141141cc406Sopenharmony_ci DBG (1, "failed to init transport layer on port 0x%03X\n", prt); 1142141cc406Sopenharmony_ci } 1143141cc406Sopenharmony_ci else 1144141cc406Sopenharmony_ci { 1145141cc406Sopenharmony_ci DBG (1, "failed to init transport layer on device %s\n", name); 1146141cc406Sopenharmony_ci } 1147141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci case UMAX1220P_SCANNER_FAILED: 1150141cc406Sopenharmony_ci if (name == NULL) 1151141cc406Sopenharmony_ci { 1152141cc406Sopenharmony_ci DBG (1, "failed to initialize scanner on port 0x%03X\n", prt); 1153141cc406Sopenharmony_ci } 1154141cc406Sopenharmony_ci else 1155141cc406Sopenharmony_ci { 1156141cc406Sopenharmony_ci DBG (1, "failed to initialize scanner on device %s\n", name); 1157141cc406Sopenharmony_ci } 1158141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1159141cc406Sopenharmony_ci case UMAX1220P_BUSY: 1160141cc406Sopenharmony_ci if (name == NULL) 1161141cc406Sopenharmony_ci { 1162141cc406Sopenharmony_ci DBG (1, "busy scanner on port 0x%03X\n", prt); 1163141cc406Sopenharmony_ci } 1164141cc406Sopenharmony_ci else 1165141cc406Sopenharmony_ci { 1166141cc406Sopenharmony_ci DBG (1, "busy scanner on device %s\n", name); 1167141cc406Sopenharmony_ci } 1168141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1169141cc406Sopenharmony_ci } 1170141cc406Sopenharmony_ci 1171141cc406Sopenharmony_ci 1172141cc406Sopenharmony_ci dev = (Umax_PP_Device *) malloc (sizeof (*dev)); 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci if (dev == NULL) 1175141cc406Sopenharmony_ci { 1176141cc406Sopenharmony_ci DBG (2, "open: not enough memory for device descriptor\n"); 1177141cc406Sopenharmony_ci DEBUG (); 1178141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1179141cc406Sopenharmony_ci } 1180141cc406Sopenharmony_ci 1181141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci dev->desc = desc; 1184141cc406Sopenharmony_ci 1185141cc406Sopenharmony_ci for (i = 0; i < 4; ++i) 1186141cc406Sopenharmony_ci for (j = 0; j < 256; ++j) 1187141cc406Sopenharmony_ci dev->gamma_table[i][j] = j; 1188141cc406Sopenharmony_ci 1189141cc406Sopenharmony_ci /* the extra amount of UMAX_PP_RESERVE bytes is to handle */ 1190141cc406Sopenharmony_ci /* the data needed to resync the color frames */ 1191141cc406Sopenharmony_ci dev->buf = malloc (dev->desc->buf_size + UMAX_PP_RESERVE); 1192141cc406Sopenharmony_ci dev->bufsize = dev->desc->buf_size; 1193141cc406Sopenharmony_ci 1194141cc406Sopenharmony_ci dev->dpi_range.min = SANE_FIX (75); 1195141cc406Sopenharmony_ci dev->dpi_range.max = SANE_FIX (dev->desc->max_res); 1196141cc406Sopenharmony_ci dev->dpi_range.quant = 0; 1197141cc406Sopenharmony_ci 1198141cc406Sopenharmony_ci dev->x_range.min = 0; 1199141cc406Sopenharmony_ci dev->x_range.max = dev->desc->max_h_size; 1200141cc406Sopenharmony_ci dev->x_range.quant = 0; 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci dev->y_range.min = 0; 1203141cc406Sopenharmony_ci dev->y_range.max = dev->desc->max_v_size; 1204141cc406Sopenharmony_ci dev->y_range.quant = 0; 1205141cc406Sopenharmony_ci 1206141cc406Sopenharmony_ci dev->gray_gain = 0; 1207141cc406Sopenharmony_ci 1208141cc406Sopenharmony_ci /* use pre defined settings read from umax_pp.conf */ 1209141cc406Sopenharmony_ci dev->red_gain = red_gain; 1210141cc406Sopenharmony_ci dev->green_gain = green_gain; 1211141cc406Sopenharmony_ci dev->blue_gain = blue_gain; 1212141cc406Sopenharmony_ci dev->red_offset = red_offset; 1213141cc406Sopenharmony_ci dev->green_offset = green_offset; 1214141cc406Sopenharmony_ci dev->blue_offset = blue_offset; 1215141cc406Sopenharmony_ci 1216141cc406Sopenharmony_ci 1217141cc406Sopenharmony_ci if (dev->buf == NULL) 1218141cc406Sopenharmony_ci { 1219141cc406Sopenharmony_ci DBG (2, "open: not enough memory for scan buffer (%lu bytes)\n", 1220141cc406Sopenharmony_ci (long int) dev->desc->buf_size); 1221141cc406Sopenharmony_ci DEBUG (); 1222141cc406Sopenharmony_ci free (dev); 1223141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1224141cc406Sopenharmony_ci } 1225141cc406Sopenharmony_ci 1226141cc406Sopenharmony_ci init_options (dev); 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci dev->next = first_dev; 1229141cc406Sopenharmony_ci first_dev = dev; 1230141cc406Sopenharmony_ci 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci if (sanei_umax_pp_UTA () == 1) 1233141cc406Sopenharmony_ci dev->opt[OPT_UTA_CONTROL].cap &= ~SANE_CAP_INACTIVE; 1234141cc406Sopenharmony_ci 1235141cc406Sopenharmony_ci *handle = dev; 1236141cc406Sopenharmony_ci 1237141cc406Sopenharmony_ci DBG (3, "open: success\n"); 1238141cc406Sopenharmony_ci 1239141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1240141cc406Sopenharmony_ci} 1241141cc406Sopenharmony_ci 1242141cc406Sopenharmony_civoid 1243141cc406Sopenharmony_cisane_close (SANE_Handle handle) 1244141cc406Sopenharmony_ci{ 1245141cc406Sopenharmony_ci Umax_PP_Device *prev, *dev; 1246141cc406Sopenharmony_ci int rc; 1247141cc406Sopenharmony_ci 1248141cc406Sopenharmony_ci DBG (3, "sane_close: ...\n"); 1249141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 1250141cc406Sopenharmony_ci prev = NULL; 1251141cc406Sopenharmony_ci 1252141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1253141cc406Sopenharmony_ci { 1254141cc406Sopenharmony_ci if (dev == handle) 1255141cc406Sopenharmony_ci break; 1256141cc406Sopenharmony_ci prev = dev; 1257141cc406Sopenharmony_ci } 1258141cc406Sopenharmony_ci 1259141cc406Sopenharmony_ci if (dev == NULL) 1260141cc406Sopenharmony_ci { 1261141cc406Sopenharmony_ci DBG (2, "close: unknown device\n"); 1262141cc406Sopenharmony_ci DEBUG (); 1263141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 1264141cc406Sopenharmony_ci } 1265141cc406Sopenharmony_ci 1266141cc406Sopenharmony_ci if (dev->state == UMAX_PP_STATE_SCANNING) 1267141cc406Sopenharmony_ci sane_cancel (handle); /* remember: sane_cancel is a macro and 1268141cc406Sopenharmony_ci expands to sane_umax_pp_cancel ()... */ 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci 1271141cc406Sopenharmony_ci /* if the scanner is parking head, we wait it to finish */ 1272141cc406Sopenharmony_ci while (dev->state == UMAX_PP_STATE_CANCELLED) 1273141cc406Sopenharmony_ci { 1274141cc406Sopenharmony_ci DBG (2, "close: waiting scanner to park head\n"); 1275141cc406Sopenharmony_ci rc = sanei_umax_pp_status (); 1276141cc406Sopenharmony_ci 1277141cc406Sopenharmony_ci /* check if scanner busy parking */ 1278141cc406Sopenharmony_ci if (rc != UMAX1220P_BUSY) 1279141cc406Sopenharmony_ci { 1280141cc406Sopenharmony_ci DBG (2, "close: scanner head parked\n"); 1281141cc406Sopenharmony_ci dev->state = UMAX_PP_STATE_IDLE; 1282141cc406Sopenharmony_ci } 1283141cc406Sopenharmony_ci } 1284141cc406Sopenharmony_ci 1285141cc406Sopenharmony_ci /* then we switch off gain if needed */ 1286141cc406Sopenharmony_ci if (dev->val[OPT_LAMP_CONTROL].w == SANE_TRUE) 1287141cc406Sopenharmony_ci { 1288141cc406Sopenharmony_ci rc = sanei_umax_pp_lamp (0); 1289141cc406Sopenharmony_ci if (rc == UMAX1220P_TRANSPORT_FAILED) 1290141cc406Sopenharmony_ci { 1291141cc406Sopenharmony_ci DBG (1, "close: switch off gain failed (ignored....)\n"); 1292141cc406Sopenharmony_ci } 1293141cc406Sopenharmony_ci } 1294141cc406Sopenharmony_ci 1295141cc406Sopenharmony_ci sanei_umax_pp_close (); 1296141cc406Sopenharmony_ci 1297141cc406Sopenharmony_ci 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci if (prev != NULL) 1300141cc406Sopenharmony_ci prev->next = dev->next; 1301141cc406Sopenharmony_ci else 1302141cc406Sopenharmony_ci first_dev = dev->next; 1303141cc406Sopenharmony_ci 1304141cc406Sopenharmony_ci free (dev->buf); 1305141cc406Sopenharmony_ci DBG (3, "close: device closed\n"); 1306141cc406Sopenharmony_ci 1307141cc406Sopenharmony_ci free (handle); 1308141cc406Sopenharmony_ci 1309141cc406Sopenharmony_ci} 1310141cc406Sopenharmony_ci 1311141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1312141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1313141cc406Sopenharmony_ci{ 1314141cc406Sopenharmony_ci Umax_PP_Device *dev = handle; 1315141cc406Sopenharmony_ci 1316141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 1317141cc406Sopenharmony_ci { 1318141cc406Sopenharmony_ci DBG (2, "get_option_descriptor: option %d doesn't exist\n", option); 1319141cc406Sopenharmony_ci DEBUG (); 1320141cc406Sopenharmony_ci return NULL; 1321141cc406Sopenharmony_ci } 1322141cc406Sopenharmony_ci 1323141cc406Sopenharmony_ci DBG (6, "get_option_descriptor: requested option %d (%s)\n", 1324141cc406Sopenharmony_ci option, dev->opt[option].name); 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci return dev->opt + option; 1327141cc406Sopenharmony_ci} 1328141cc406Sopenharmony_ci 1329141cc406Sopenharmony_ciSANE_Status 1330141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1331141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 1332141cc406Sopenharmony_ci{ 1333141cc406Sopenharmony_ci Umax_PP_Device *dev = handle; 1334141cc406Sopenharmony_ci SANE_Status status; 1335141cc406Sopenharmony_ci SANE_Word w, cap, tmpw; 1336141cc406Sopenharmony_ci int dpi, rc; 1337141cc406Sopenharmony_ci 1338141cc406Sopenharmony_ci DBG (6, "control_option: option %d, action %d\n", option, action); 1339141cc406Sopenharmony_ci 1340141cc406Sopenharmony_ci if (info) 1341141cc406Sopenharmony_ci *info = 0; 1342141cc406Sopenharmony_ci 1343141cc406Sopenharmony_ci if (dev->state == UMAX_PP_STATE_SCANNING) 1344141cc406Sopenharmony_ci { 1345141cc406Sopenharmony_ci DBG (2, "control_option: device is scanning\n"); 1346141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1347141cc406Sopenharmony_ci } 1348141cc406Sopenharmony_ci 1349141cc406Sopenharmony_ci if ((unsigned int) option >= NUM_OPTIONS) 1350141cc406Sopenharmony_ci { 1351141cc406Sopenharmony_ci DBG (2, "control_option: option doesn't exist\n"); 1352141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1353141cc406Sopenharmony_ci } 1354141cc406Sopenharmony_ci 1355141cc406Sopenharmony_ci 1356141cc406Sopenharmony_ci cap = dev->opt[option].cap; 1357141cc406Sopenharmony_ci 1358141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 1359141cc406Sopenharmony_ci { 1360141cc406Sopenharmony_ci DBG (2, "control_option: option isn't active\n"); 1361141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1362141cc406Sopenharmony_ci } 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci DBG (6, "control_option: option <%s>, action ... %d\n", 1365141cc406Sopenharmony_ci dev->opt[option].name, action); 1366141cc406Sopenharmony_ci 1367141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 1368141cc406Sopenharmony_ci { 1369141cc406Sopenharmony_ci DBG (6, " get value\n"); 1370141cc406Sopenharmony_ci switch (option) 1371141cc406Sopenharmony_ci { 1372141cc406Sopenharmony_ci /* word options: */ 1373141cc406Sopenharmony_ci case OPT_PREVIEW: 1374141cc406Sopenharmony_ci case OPT_GRAY_PREVIEW: 1375141cc406Sopenharmony_ci case OPT_LAMP_CONTROL: 1376141cc406Sopenharmony_ci case OPT_UTA_CONTROL: 1377141cc406Sopenharmony_ci case OPT_RESOLUTION: 1378141cc406Sopenharmony_ci case OPT_TL_X: 1379141cc406Sopenharmony_ci case OPT_TL_Y: 1380141cc406Sopenharmony_ci case OPT_BR_X: 1381141cc406Sopenharmony_ci case OPT_BR_Y: 1382141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1383141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1384141cc406Sopenharmony_ci case OPT_MANUAL_GAIN: 1385141cc406Sopenharmony_ci case OPT_GRAY_GAIN: 1386141cc406Sopenharmony_ci case OPT_GREEN_GAIN: 1387141cc406Sopenharmony_ci case OPT_RED_GAIN: 1388141cc406Sopenharmony_ci case OPT_BLUE_GAIN: 1389141cc406Sopenharmony_ci case OPT_MANUAL_OFFSET: 1390141cc406Sopenharmony_ci case OPT_GRAY_OFFSET: 1391141cc406Sopenharmony_ci case OPT_GREEN_OFFSET: 1392141cc406Sopenharmony_ci case OPT_RED_OFFSET: 1393141cc406Sopenharmony_ci case OPT_BLUE_OFFSET: 1394141cc406Sopenharmony_ci 1395141cc406Sopenharmony_ci *(SANE_Word *) val = dev->val[option].w; 1396141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1397141cc406Sopenharmony_ci 1398141cc406Sopenharmony_ci /* word-array options: */ 1399141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1400141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1401141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1402141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1403141cc406Sopenharmony_ci memcpy (val, dev->val[option].wa, dev->opt[option].size); 1404141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1405141cc406Sopenharmony_ci 1406141cc406Sopenharmony_ci /* string options: */ 1407141cc406Sopenharmony_ci case OPT_MODE: 1408141cc406Sopenharmony_ci 1409141cc406Sopenharmony_ci strcpy (val, dev->val[option].s); 1410141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1411141cc406Sopenharmony_ci } 1412141cc406Sopenharmony_ci } 1413141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 1414141cc406Sopenharmony_ci { 1415141cc406Sopenharmony_ci DBG (6, " set value\n"); 1416141cc406Sopenharmony_ci 1417141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 1418141cc406Sopenharmony_ci { 1419141cc406Sopenharmony_ci DBG (2, "control_option: option can't be set\n"); 1420141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1421141cc406Sopenharmony_ci } 1422141cc406Sopenharmony_ci 1423141cc406Sopenharmony_ci status = sanei_constrain_value (dev->opt + option, val, info); 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1426141cc406Sopenharmony_ci { 1427141cc406Sopenharmony_ci DBG (2, "control_option: constrain_value failed (%s)\n", 1428141cc406Sopenharmony_ci sane_strstatus (status)); 1429141cc406Sopenharmony_ci return status; 1430141cc406Sopenharmony_ci } 1431141cc406Sopenharmony_ci 1432141cc406Sopenharmony_ci if (option == OPT_RESOLUTION) 1433141cc406Sopenharmony_ci { 1434141cc406Sopenharmony_ci DBG (16, "control_option: setting resolution to %d\n", 1435141cc406Sopenharmony_ci *(SANE_Int *) val); 1436141cc406Sopenharmony_ci } 1437141cc406Sopenharmony_ci if (option == OPT_PREVIEW) 1438141cc406Sopenharmony_ci { 1439141cc406Sopenharmony_ci DBG (16, "control_option: setting preview to %d\n", 1440141cc406Sopenharmony_ci *(SANE_Word *) val); 1441141cc406Sopenharmony_ci } 1442141cc406Sopenharmony_ci 1443141cc406Sopenharmony_ci switch (option) 1444141cc406Sopenharmony_ci { 1445141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 1446141cc406Sopenharmony_ci case OPT_PREVIEW: 1447141cc406Sopenharmony_ci case OPT_GRAY_PREVIEW: 1448141cc406Sopenharmony_ci case OPT_TL_Y: 1449141cc406Sopenharmony_ci case OPT_BR_Y: 1450141cc406Sopenharmony_ci 1451141cc406Sopenharmony_ci if (info) 1452141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1453141cc406Sopenharmony_ci 1454141cc406Sopenharmony_ci // fall through 1455141cc406Sopenharmony_ci case OPT_GRAY_GAIN: 1456141cc406Sopenharmony_ci case OPT_GREEN_GAIN: 1457141cc406Sopenharmony_ci case OPT_RED_GAIN: 1458141cc406Sopenharmony_ci case OPT_BLUE_GAIN: 1459141cc406Sopenharmony_ci case OPT_GRAY_OFFSET: 1460141cc406Sopenharmony_ci case OPT_GREEN_OFFSET: 1461141cc406Sopenharmony_ci case OPT_RED_OFFSET: 1462141cc406Sopenharmony_ci case OPT_BLUE_OFFSET: 1463141cc406Sopenharmony_ci 1464141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1465141cc406Sopenharmony_ci /* sanity check */ 1466141cc406Sopenharmony_ci if (dev->val[OPT_BR_Y].w < dev->val[OPT_TL_Y].w) 1467141cc406Sopenharmony_ci { 1468141cc406Sopenharmony_ci tmpw = dev->val[OPT_BR_Y].w; 1469141cc406Sopenharmony_ci dev->val[OPT_BR_Y].w = dev->val[OPT_TL_Y].w; 1470141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = tmpw; 1471141cc406Sopenharmony_ci if (info) 1472141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1473141cc406Sopenharmony_ci DBG (16, "control_option: swapping Y coordinates\n"); 1474141cc406Sopenharmony_ci } 1475141cc406Sopenharmony_ci if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1476141cc406Sopenharmony_ci { 1477141cc406Sopenharmony_ci dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); 1478141cc406Sopenharmony_ci if (dev->val[OPT_TL_Y].w < 2 * umax_pp_get_sync (dpi)) 1479141cc406Sopenharmony_ci { 1480141cc406Sopenharmony_ci DBG (16, "control_option: correcting TL_Y coordinates\n"); 1481141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = 2 * umax_pp_get_sync (dpi); 1482141cc406Sopenharmony_ci if (info) 1483141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1484141cc406Sopenharmony_ci } 1485141cc406Sopenharmony_ci } 1486141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1487141cc406Sopenharmony_ci 1488141cc406Sopenharmony_ci /* side-effect-free word-array options: */ 1489141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1490141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1491141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1492141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1493141cc406Sopenharmony_ci 1494141cc406Sopenharmony_ci memcpy (dev->val[option].wa, val, dev->opt[option].size); 1495141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1496141cc406Sopenharmony_ci 1497141cc406Sopenharmony_ci 1498141cc406Sopenharmony_ci /* options with side-effects: */ 1499141cc406Sopenharmony_ci case OPT_UTA_CONTROL: 1500141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1501141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1502141cc406Sopenharmony_ci 1503141cc406Sopenharmony_ci case OPT_LAMP_CONTROL: 1504141cc406Sopenharmony_ci if (dev->state != UMAX_PP_STATE_IDLE) 1505141cc406Sopenharmony_ci { 1506141cc406Sopenharmony_ci rc = sanei_umax_pp_status (); 1507141cc406Sopenharmony_ci 1508141cc406Sopenharmony_ci /* check if scanner busy parking */ 1509141cc406Sopenharmony_ci if (rc == UMAX1220P_BUSY) 1510141cc406Sopenharmony_ci { 1511141cc406Sopenharmony_ci DBG (2, "control_option: scanner busy\n"); 1512141cc406Sopenharmony_ci if (info) 1513141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1514141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1515141cc406Sopenharmony_ci } 1516141cc406Sopenharmony_ci dev->state = UMAX_PP_STATE_IDLE; 1517141cc406Sopenharmony_ci } 1518141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1519141cc406Sopenharmony_ci if (dev->val[option].w == SANE_TRUE) 1520141cc406Sopenharmony_ci rc = sanei_umax_pp_lamp (1); 1521141cc406Sopenharmony_ci else 1522141cc406Sopenharmony_ci rc = sanei_umax_pp_lamp (0); 1523141cc406Sopenharmony_ci if (rc == UMAX1220P_TRANSPORT_FAILED) 1524141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1525141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1526141cc406Sopenharmony_ci 1527141cc406Sopenharmony_ci case OPT_TL_X: 1528141cc406Sopenharmony_ci case OPT_BR_X: 1529141cc406Sopenharmony_ci if (info) 1530141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1531141cc406Sopenharmony_ci dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); 1532141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1533141cc406Sopenharmony_ci /* coords rounded to allow 32 bit IO/transfer */ 1534141cc406Sopenharmony_ci /* at high resolution */ 1535141cc406Sopenharmony_ci if (dpi >= 600) 1536141cc406Sopenharmony_ci { 1537141cc406Sopenharmony_ci if (dev->val[option].w & 0x03) 1538141cc406Sopenharmony_ci { 1539141cc406Sopenharmony_ci if (info) 1540141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1541141cc406Sopenharmony_ci dev->val[option].w = dev->val[option].w & 0xFFFC; 1542141cc406Sopenharmony_ci *(SANE_Word *) val = dev->val[option].w; 1543141cc406Sopenharmony_ci DBG (16, "control_option: rounding X to %d\n", 1544141cc406Sopenharmony_ci *(SANE_Word *) val); 1545141cc406Sopenharmony_ci } 1546141cc406Sopenharmony_ci } 1547141cc406Sopenharmony_ci /* sanity check */ 1548141cc406Sopenharmony_ci if (dev->val[OPT_BR_X].w < dev->val[OPT_TL_X].w) 1549141cc406Sopenharmony_ci { 1550141cc406Sopenharmony_ci tmpw = dev->val[OPT_BR_X].w; 1551141cc406Sopenharmony_ci dev->val[OPT_BR_X].w = dev->val[OPT_TL_X].w; 1552141cc406Sopenharmony_ci dev->val[OPT_TL_X].w = tmpw; 1553141cc406Sopenharmony_ci if (info) 1554141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1555141cc406Sopenharmony_ci DBG (16, "control_option: swapping X coordinates\n"); 1556141cc406Sopenharmony_ci } 1557141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci case OPT_RESOLUTION: 1562141cc406Sopenharmony_ci if (info) 1563141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1564141cc406Sopenharmony_ci /* resolution : only have 75, 150, 300, 600 and 1200 */ 1565141cc406Sopenharmony_ci dpi = (int) (SANE_UNFIX (*(SANE_Word *) val)); 1566141cc406Sopenharmony_ci if ((dpi != 75) 1567141cc406Sopenharmony_ci && (dpi != 150) 1568141cc406Sopenharmony_ci && (dpi != 300) && (dpi != 600) && (dpi != 1200)) 1569141cc406Sopenharmony_ci { 1570141cc406Sopenharmony_ci if (dpi <= 75) 1571141cc406Sopenharmony_ci dpi = 75; 1572141cc406Sopenharmony_ci else if (dpi <= 150) 1573141cc406Sopenharmony_ci dpi = 150; 1574141cc406Sopenharmony_ci else if (dpi <= 300) 1575141cc406Sopenharmony_ci dpi = 300; 1576141cc406Sopenharmony_ci else if (dpi <= 600) 1577141cc406Sopenharmony_ci dpi = 600; 1578141cc406Sopenharmony_ci else 1579141cc406Sopenharmony_ci dpi = 1200; 1580141cc406Sopenharmony_ci if (info) 1581141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1582141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX ((SANE_Word) dpi); 1583141cc406Sopenharmony_ci } 1584141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1585141cc406Sopenharmony_ci 1586141cc406Sopenharmony_ci /* correct top x and bottom x if needed */ 1587141cc406Sopenharmony_ci if (dpi >= 600) 1588141cc406Sopenharmony_ci { 1589141cc406Sopenharmony_ci dev->val[OPT_TL_X].w = dev->val[OPT_TL_X].w & 0xFFFC; 1590141cc406Sopenharmony_ci dev->val[OPT_BR_X].w = dev->val[OPT_BR_X].w & 0xFFFC; 1591141cc406Sopenharmony_ci } 1592141cc406Sopenharmony_ci /* corrects top y for offset */ 1593141cc406Sopenharmony_ci if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1594141cc406Sopenharmony_ci { 1595141cc406Sopenharmony_ci if (dev->val[OPT_TL_Y].w < 2 * umax_pp_get_sync (dpi)) 1596141cc406Sopenharmony_ci { 1597141cc406Sopenharmony_ci DBG (16, "control_option: correcting TL_Y coordinates\n"); 1598141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = 2 * umax_pp_get_sync (dpi); 1599141cc406Sopenharmony_ci if (info) 1600141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1601141cc406Sopenharmony_ci } 1602141cc406Sopenharmony_ci } 1603141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1604141cc406Sopenharmony_ci 1605141cc406Sopenharmony_ci case OPT_MANUAL_OFFSET: 1606141cc406Sopenharmony_ci w = *(SANE_Word *) val; 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci if (w == dev->val[OPT_MANUAL_OFFSET].w) 1609141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 1610141cc406Sopenharmony_ci 1611141cc406Sopenharmony_ci if (info) 1612141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 1613141cc406Sopenharmony_ci 1614141cc406Sopenharmony_ci dev->val[OPT_MANUAL_OFFSET].w = w; 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci if (w == SANE_TRUE) 1617141cc406Sopenharmony_ci { 1618141cc406Sopenharmony_ci const char *mode = dev->val[OPT_MODE].s; 1619141cc406Sopenharmony_ci 1620141cc406Sopenharmony_ci if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1621141cc406Sopenharmony_ci || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) 1622141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1623141cc406Sopenharmony_ci else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1624141cc406Sopenharmony_ci { 1625141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE; 1626141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1627141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1628141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1629141cc406Sopenharmony_ci } 1630141cc406Sopenharmony_ci } 1631141cc406Sopenharmony_ci else 1632141cc406Sopenharmony_ci { 1633141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE; 1634141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].cap |= SANE_CAP_INACTIVE; 1635141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].cap |= SANE_CAP_INACTIVE; 1636141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].cap |= SANE_CAP_INACTIVE; 1637141cc406Sopenharmony_ci } 1638141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1639141cc406Sopenharmony_ci 1640141cc406Sopenharmony_ci 1641141cc406Sopenharmony_ci 1642141cc406Sopenharmony_ci case OPT_MANUAL_GAIN: 1643141cc406Sopenharmony_ci w = *(SANE_Word *) val; 1644141cc406Sopenharmony_ci 1645141cc406Sopenharmony_ci if (w == dev->val[OPT_MANUAL_GAIN].w) 1646141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 1647141cc406Sopenharmony_ci 1648141cc406Sopenharmony_ci if (info) 1649141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 1650141cc406Sopenharmony_ci 1651141cc406Sopenharmony_ci dev->val[OPT_MANUAL_GAIN].w = w; 1652141cc406Sopenharmony_ci 1653141cc406Sopenharmony_ci if (w == SANE_TRUE) 1654141cc406Sopenharmony_ci { 1655141cc406Sopenharmony_ci const char *mode = dev->val[OPT_MODE].s; 1656141cc406Sopenharmony_ci 1657141cc406Sopenharmony_ci if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1658141cc406Sopenharmony_ci || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) 1659141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].cap &= ~SANE_CAP_INACTIVE; 1660141cc406Sopenharmony_ci else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1661141cc406Sopenharmony_ci { 1662141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; 1663141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].cap &= ~SANE_CAP_INACTIVE; 1664141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].cap &= ~SANE_CAP_INACTIVE; 1665141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].cap &= ~SANE_CAP_INACTIVE; 1666141cc406Sopenharmony_ci } 1667141cc406Sopenharmony_ci } 1668141cc406Sopenharmony_ci else 1669141cc406Sopenharmony_ci { 1670141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; 1671141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; 1672141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; 1673141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; 1674141cc406Sopenharmony_ci } 1675141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1676141cc406Sopenharmony_ci 1677141cc406Sopenharmony_ci 1678141cc406Sopenharmony_ci 1679141cc406Sopenharmony_ci 1680141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1681141cc406Sopenharmony_ci w = *(SANE_Word *) val; 1682141cc406Sopenharmony_ci 1683141cc406Sopenharmony_ci if (w == dev->val[OPT_CUSTOM_GAMMA].w) 1684141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 1685141cc406Sopenharmony_ci 1686141cc406Sopenharmony_ci if (info) 1687141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 1688141cc406Sopenharmony_ci 1689141cc406Sopenharmony_ci dev->val[OPT_CUSTOM_GAMMA].w = w; 1690141cc406Sopenharmony_ci 1691141cc406Sopenharmony_ci if (w == SANE_TRUE) 1692141cc406Sopenharmony_ci { 1693141cc406Sopenharmony_ci const char *mode = dev->val[OPT_MODE].s; 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1696141cc406Sopenharmony_ci || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) 1697141cc406Sopenharmony_ci { 1698141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1699141cc406Sopenharmony_ci sanei_umax_pp_gamma (NULL, dev->val[OPT_GAMMA_VECTOR].wa, 1700141cc406Sopenharmony_ci NULL); 1701141cc406Sopenharmony_ci } 1702141cc406Sopenharmony_ci else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1703141cc406Sopenharmony_ci { 1704141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1705141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1706141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1707141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1708141cc406Sopenharmony_ci sanei_umax_pp_gamma (dev->val[OPT_GAMMA_VECTOR_R].wa, 1709141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_G].wa, 1710141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_B].wa); 1711141cc406Sopenharmony_ci } 1712141cc406Sopenharmony_ci } 1713141cc406Sopenharmony_ci else 1714141cc406Sopenharmony_ci { 1715141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1716141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1717141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1718141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1719141cc406Sopenharmony_ci sanei_umax_pp_gamma (NULL, NULL, NULL); 1720141cc406Sopenharmony_ci } 1721141cc406Sopenharmony_ci 1722141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1723141cc406Sopenharmony_ci 1724141cc406Sopenharmony_ci case OPT_MODE: 1725141cc406Sopenharmony_ci { 1726141cc406Sopenharmony_ci char *old_val = dev->val[option].s; 1727141cc406Sopenharmony_ci 1728141cc406Sopenharmony_ci if (old_val) 1729141cc406Sopenharmony_ci { 1730141cc406Sopenharmony_ci if (strcmp (old_val, val) == 0) 1731141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 1732141cc406Sopenharmony_ci 1733141cc406Sopenharmony_ci free (old_val); 1734141cc406Sopenharmony_ci } 1735141cc406Sopenharmony_ci 1736141cc406Sopenharmony_ci if (info) 1737141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1738141cc406Sopenharmony_ci 1739141cc406Sopenharmony_ci dev->val[option].s = strdup (val); 1740141cc406Sopenharmony_ci 1741141cc406Sopenharmony_ci /* corrects top y for offset */ 1742141cc406Sopenharmony_ci if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1743141cc406Sopenharmony_ci { 1744141cc406Sopenharmony_ci dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); 1745141cc406Sopenharmony_ci if (dev->val[OPT_TL_Y].w < 2 * umax_pp_get_sync (dpi)) 1746141cc406Sopenharmony_ci { 1747141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = 2 * umax_pp_get_sync (dpi); 1748141cc406Sopenharmony_ci DBG (16, "control_option: correcting TL_Y coordinates\n"); 1749141cc406Sopenharmony_ci if (info) 1750141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1751141cc406Sopenharmony_ci } 1752141cc406Sopenharmony_ci } 1753141cc406Sopenharmony_ci 1754141cc406Sopenharmony_ci dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1755141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1756141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1757141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1758141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1759141cc406Sopenharmony_ci sanei_umax_pp_gamma (NULL, NULL, NULL); 1760141cc406Sopenharmony_ci 1761141cc406Sopenharmony_ci 1762141cc406Sopenharmony_ci if (dev->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) 1763141cc406Sopenharmony_ci { 1764141cc406Sopenharmony_ci if ((strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1765141cc406Sopenharmony_ci || (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)) 1766141cc406Sopenharmony_ci { 1767141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1768141cc406Sopenharmony_ci sanei_umax_pp_gamma (NULL, dev->val[OPT_GAMMA_VECTOR].wa, 1769141cc406Sopenharmony_ci NULL); 1770141cc406Sopenharmony_ci } 1771141cc406Sopenharmony_ci else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1772141cc406Sopenharmony_ci { 1773141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1774141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1775141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1776141cc406Sopenharmony_ci dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1777141cc406Sopenharmony_ci sanei_umax_pp_gamma (dev->val[OPT_GAMMA_VECTOR_R].wa, 1778141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_G].wa, 1779141cc406Sopenharmony_ci dev->val[OPT_GAMMA_VECTOR_B].wa); 1780141cc406Sopenharmony_ci } 1781141cc406Sopenharmony_ci } 1782141cc406Sopenharmony_ci 1783141cc406Sopenharmony_ci /* rebuild OPT OFFSET */ 1784141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE; 1785141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].cap |= SANE_CAP_INACTIVE; 1786141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].cap |= SANE_CAP_INACTIVE; 1787141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].cap |= SANE_CAP_INACTIVE; 1788141cc406Sopenharmony_ci 1789141cc406Sopenharmony_ci 1790141cc406Sopenharmony_ci if (dev->val[OPT_MANUAL_OFFSET].w == SANE_TRUE) 1791141cc406Sopenharmony_ci { 1792141cc406Sopenharmony_ci if ((strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1793141cc406Sopenharmony_ci || (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)) 1794141cc406Sopenharmony_ci dev->opt[OPT_GRAY_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1795141cc406Sopenharmony_ci else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1796141cc406Sopenharmony_ci { 1797141cc406Sopenharmony_ci dev->opt[OPT_RED_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1798141cc406Sopenharmony_ci dev->opt[OPT_GREEN_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1799141cc406Sopenharmony_ci dev->opt[OPT_BLUE_OFFSET].cap &= ~SANE_CAP_INACTIVE; 1800141cc406Sopenharmony_ci } 1801141cc406Sopenharmony_ci } 1802141cc406Sopenharmony_ci 1803141cc406Sopenharmony_ci /* rebuild OPT GAIN */ 1804141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; 1805141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; 1806141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; 1807141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; 1808141cc406Sopenharmony_ci 1809141cc406Sopenharmony_ci 1810141cc406Sopenharmony_ci if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) 1811141cc406Sopenharmony_ci { 1812141cc406Sopenharmony_ci if ((strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1813141cc406Sopenharmony_ci || (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)) 1814141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].cap &= ~SANE_CAP_INACTIVE; 1815141cc406Sopenharmony_ci else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1816141cc406Sopenharmony_ci { 1817141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].cap &= ~SANE_CAP_INACTIVE; 1818141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].cap &= ~SANE_CAP_INACTIVE; 1819141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].cap &= ~SANE_CAP_INACTIVE; 1820141cc406Sopenharmony_ci } 1821141cc406Sopenharmony_ci } 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1824141cc406Sopenharmony_ci } 1825141cc406Sopenharmony_ci } 1826141cc406Sopenharmony_ci } 1827141cc406Sopenharmony_ci 1828141cc406Sopenharmony_ci 1829141cc406Sopenharmony_ci DBG (2, "control_option: unknown action %d \n", action); 1830141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1831141cc406Sopenharmony_ci} 1832141cc406Sopenharmony_ci 1833141cc406Sopenharmony_ci 1834141cc406Sopenharmony_ciSANE_Status 1835141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1836141cc406Sopenharmony_ci{ 1837141cc406Sopenharmony_ci Umax_PP_Device *dev = handle; 1838141cc406Sopenharmony_ci int dpi, remain; 1839141cc406Sopenharmony_ci 1840141cc406Sopenharmony_ci memset (&(dev->params), 0, sizeof (dev->params)); 1841141cc406Sopenharmony_ci DBG (64, "sane_get_parameters\n"); 1842141cc406Sopenharmony_ci 1843141cc406Sopenharmony_ci /* color/gray */ 1844141cc406Sopenharmony_ci if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) != 0) 1845141cc406Sopenharmony_ci { 1846141cc406Sopenharmony_ci if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) != 0) 1847141cc406Sopenharmony_ci dev->color = UMAX_PP_MODE_LINEART; 1848141cc406Sopenharmony_ci else 1849141cc406Sopenharmony_ci dev->color = UMAX_PP_MODE_GRAYSCALE; 1850141cc406Sopenharmony_ci } 1851141cc406Sopenharmony_ci else 1852141cc406Sopenharmony_ci dev->color = UMAX_PP_MODE_COLOR; 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci /* offset control */ 1855141cc406Sopenharmony_ci if (dev->val[OPT_MANUAL_OFFSET].w == SANE_TRUE) 1856141cc406Sopenharmony_ci { 1857141cc406Sopenharmony_ci if (dev->color != UMAX_PP_MODE_COLOR) 1858141cc406Sopenharmony_ci { 1859141cc406Sopenharmony_ci dev->red_offset = 0; 1860141cc406Sopenharmony_ci dev->green_offset = (int) (dev->val[OPT_GRAY_OFFSET].w); 1861141cc406Sopenharmony_ci dev->blue_offset = 0; 1862141cc406Sopenharmony_ci } 1863141cc406Sopenharmony_ci else 1864141cc406Sopenharmony_ci { 1865141cc406Sopenharmony_ci dev->red_offset = (int) (dev->val[OPT_RED_OFFSET].w); 1866141cc406Sopenharmony_ci dev->green_offset = (int) (dev->val[OPT_GREEN_OFFSET].w); 1867141cc406Sopenharmony_ci dev->blue_offset = (int) (dev->val[OPT_BLUE_OFFSET].w); 1868141cc406Sopenharmony_ci } 1869141cc406Sopenharmony_ci } 1870141cc406Sopenharmony_ci else 1871141cc406Sopenharmony_ci { 1872141cc406Sopenharmony_ci dev->red_offset = 6; 1873141cc406Sopenharmony_ci dev->green_offset = 6; 1874141cc406Sopenharmony_ci dev->blue_offset = 6; 1875141cc406Sopenharmony_ci } 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci /* gain control */ 1878141cc406Sopenharmony_ci if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) 1879141cc406Sopenharmony_ci { 1880141cc406Sopenharmony_ci if (dev->color != UMAX_PP_MODE_COLOR) 1881141cc406Sopenharmony_ci { 1882141cc406Sopenharmony_ci dev->red_gain = 0; 1883141cc406Sopenharmony_ci dev->green_gain = (int) (dev->val[OPT_GRAY_GAIN].w); 1884141cc406Sopenharmony_ci dev->blue_gain = 0; 1885141cc406Sopenharmony_ci } 1886141cc406Sopenharmony_ci else 1887141cc406Sopenharmony_ci { 1888141cc406Sopenharmony_ci dev->red_gain = (int) (dev->val[OPT_RED_GAIN].w); 1889141cc406Sopenharmony_ci dev->green_gain = (int) (dev->val[OPT_GREEN_GAIN].w); 1890141cc406Sopenharmony_ci dev->blue_gain = (int) (dev->val[OPT_BLUE_GAIN].w); 1891141cc406Sopenharmony_ci } 1892141cc406Sopenharmony_ci } 1893141cc406Sopenharmony_ci else 1894141cc406Sopenharmony_ci { 1895141cc406Sopenharmony_ci dev->red_gain = red_gain; 1896141cc406Sopenharmony_ci dev->green_gain = green_gain; 1897141cc406Sopenharmony_ci dev->blue_gain = blue_gain; 1898141cc406Sopenharmony_ci } 1899141cc406Sopenharmony_ci 1900141cc406Sopenharmony_ci /* geometry */ 1901141cc406Sopenharmony_ci dev->TopX = dev->val[OPT_TL_X].w; 1902141cc406Sopenharmony_ci dev->TopY = dev->val[OPT_TL_Y].w; 1903141cc406Sopenharmony_ci dev->BottomX = dev->val[OPT_BR_X].w; 1904141cc406Sopenharmony_ci dev->BottomY = dev->val[OPT_BR_Y].w; 1905141cc406Sopenharmony_ci 1906141cc406Sopenharmony_ci /* resolution : only have 75, 150, 300, 600 and 1200 */ 1907141cc406Sopenharmony_ci dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); 1908141cc406Sopenharmony_ci if (dpi <= 75) 1909141cc406Sopenharmony_ci dpi = 75; 1910141cc406Sopenharmony_ci else if (dpi <= 150) 1911141cc406Sopenharmony_ci dpi = 150; 1912141cc406Sopenharmony_ci else if (dpi <= 300) 1913141cc406Sopenharmony_ci dpi = 300; 1914141cc406Sopenharmony_ci else if (dpi <= 600) 1915141cc406Sopenharmony_ci dpi = 600; 1916141cc406Sopenharmony_ci else 1917141cc406Sopenharmony_ci dpi = 1200; 1918141cc406Sopenharmony_ci dev->dpi = dpi; 1919141cc406Sopenharmony_ci 1920141cc406Sopenharmony_ci DBG (16, "sane_get_parameters: dpi set to %d\n", dpi); 1921141cc406Sopenharmony_ci 1922141cc406Sopenharmony_ci /* for highest resolutions , width must be aligned on 32 bit word */ 1923141cc406Sopenharmony_ci if (dpi >= 600) 1924141cc406Sopenharmony_ci { 1925141cc406Sopenharmony_ci remain = (dev->BottomX - dev->TopX) & 0x03; 1926141cc406Sopenharmony_ci if (remain) 1927141cc406Sopenharmony_ci { 1928141cc406Sopenharmony_ci DBG (64, "sane_get_parameters: %d-%d -> remain is %d\n", 1929141cc406Sopenharmony_ci dev->BottomX, dev->TopX, remain); 1930141cc406Sopenharmony_ci if (dev->BottomX + remain < dev->desc->max_h_size) 1931141cc406Sopenharmony_ci dev->BottomX += remain; 1932141cc406Sopenharmony_ci else 1933141cc406Sopenharmony_ci { 1934141cc406Sopenharmony_ci remain -= (dev->desc->max_h_size - dev->BottomX); 1935141cc406Sopenharmony_ci dev->BottomX = dev->desc->max_h_size; 1936141cc406Sopenharmony_ci dev->TopX -= remain; 1937141cc406Sopenharmony_ci } 1938141cc406Sopenharmony_ci } 1939141cc406Sopenharmony_ci } 1940141cc406Sopenharmony_ci 1941141cc406Sopenharmony_ci if (dev->val[OPT_PREVIEW].w == SANE_TRUE) 1942141cc406Sopenharmony_ci { 1943141cc406Sopenharmony_ci 1944141cc406Sopenharmony_ci if (dev->val[OPT_GRAY_PREVIEW].w == SANE_TRUE) 1945141cc406Sopenharmony_ci { 1946141cc406Sopenharmony_ci DBG (16, "sane_get_parameters: gray preview\n"); 1947141cc406Sopenharmony_ci dev->color = UMAX_PP_MODE_GRAYSCALE; 1948141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 1949141cc406Sopenharmony_ci } 1950141cc406Sopenharmony_ci else 1951141cc406Sopenharmony_ci { 1952141cc406Sopenharmony_ci DBG (16, "sane_get_parameters: color preview\n"); 1953141cc406Sopenharmony_ci dev->color = UMAX_PP_MODE_COLOR; 1954141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_RGB; 1955141cc406Sopenharmony_ci } 1956141cc406Sopenharmony_ci 1957141cc406Sopenharmony_ci dev->dpi = 75; 1958141cc406Sopenharmony_ci dev->TopX = 0; 1959141cc406Sopenharmony_ci dev->TopY = 0; 1960141cc406Sopenharmony_ci dev->BottomX = dev->desc->max_h_size; 1961141cc406Sopenharmony_ci dev->BottomY = dev->desc->max_v_size; 1962141cc406Sopenharmony_ci } 1963141cc406Sopenharmony_ci 1964141cc406Sopenharmony_ci 1965141cc406Sopenharmony_ci /* fill params */ 1966141cc406Sopenharmony_ci dev->params.last_frame = SANE_TRUE; 1967141cc406Sopenharmony_ci dev->params.lines = 1968141cc406Sopenharmony_ci ((dev->BottomY - dev->TopY) * dev->dpi) / dev->desc->ccd_res; 1969141cc406Sopenharmony_ci if (dev->dpi >= dev->desc->ccd_res) 1970141cc406Sopenharmony_ci dpi = dev->desc->ccd_res; 1971141cc406Sopenharmony_ci else 1972141cc406Sopenharmony_ci dpi = dev->dpi; 1973141cc406Sopenharmony_ci dev->params.pixels_per_line = 1974141cc406Sopenharmony_ci ((dev->BottomX - dev->TopX) * dpi) / dev->desc->ccd_res; 1975141cc406Sopenharmony_ci if (dev->color == UMAX_PP_MODE_COLOR) 1976141cc406Sopenharmony_ci { 1977141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line * 3; 1978141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_RGB; 1979141cc406Sopenharmony_ci } 1980141cc406Sopenharmony_ci else 1981141cc406Sopenharmony_ci { 1982141cc406Sopenharmony_ci dev->params.bytes_per_line = dev->params.pixels_per_line; 1983141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 1984141cc406Sopenharmony_ci } 1985141cc406Sopenharmony_ci dev->params.depth = 8; 1986141cc406Sopenharmony_ci 1987141cc406Sopenharmony_ci /* success */ 1988141cc406Sopenharmony_ci if (params != NULL) 1989141cc406Sopenharmony_ci memcpy (params, &(dev->params), sizeof (dev->params)); 1990141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1991141cc406Sopenharmony_ci 1992141cc406Sopenharmony_ci} 1993141cc406Sopenharmony_ci 1994141cc406Sopenharmony_ciSANE_Status 1995141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1996141cc406Sopenharmony_ci{ 1997141cc406Sopenharmony_ci Umax_PP_Device *dev = handle; 1998141cc406Sopenharmony_ci int rc, autoset; 1999141cc406Sopenharmony_ci int delta = 0, points; 2000141cc406Sopenharmony_ci 2001141cc406Sopenharmony_ci /* sanity check */ 2002141cc406Sopenharmony_ci if (dev->state == UMAX_PP_STATE_SCANNING) 2003141cc406Sopenharmony_ci { 2004141cc406Sopenharmony_ci DBG (2, "sane_start: device is already scanning\n"); 2005141cc406Sopenharmony_ci DEBUG (); 2006141cc406Sopenharmony_ci 2007141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 2008141cc406Sopenharmony_ci } 2009141cc406Sopenharmony_ci 2010141cc406Sopenharmony_ci /* if cancelled, check if head is back home */ 2011141cc406Sopenharmony_ci if (dev->state == UMAX_PP_STATE_CANCELLED) 2012141cc406Sopenharmony_ci { 2013141cc406Sopenharmony_ci DBG (2, "sane_start: checking if scanner is parking head .... \n"); 2014141cc406Sopenharmony_ci 2015141cc406Sopenharmony_ci rc = sanei_umax_pp_status (); 2016141cc406Sopenharmony_ci points = 0; 2017141cc406Sopenharmony_ci 2018141cc406Sopenharmony_ci /* check if scanner busy parking */ 2019141cc406Sopenharmony_ci /* if so, wait parking completion */ 2020141cc406Sopenharmony_ci DBG (2, "sane_start: scanner busy\n"); 2021141cc406Sopenharmony_ci while ((rc == UMAX1220P_BUSY) && (points < 30)) 2022141cc406Sopenharmony_ci { 2023141cc406Sopenharmony_ci sleep (1); 2024141cc406Sopenharmony_ci rc = sanei_umax_pp_status (); 2025141cc406Sopenharmony_ci points++; 2026141cc406Sopenharmony_ci } 2027141cc406Sopenharmony_ci /* timeout waiting for scanner */ 2028141cc406Sopenharmony_ci if (rc == UMAX1220P_BUSY) 2029141cc406Sopenharmony_ci { 2030141cc406Sopenharmony_ci DBG (2, "sane_start: scanner still busy\n"); 2031141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 2032141cc406Sopenharmony_ci } 2033141cc406Sopenharmony_ci dev->state = UMAX_PP_STATE_IDLE; 2034141cc406Sopenharmony_ci } 2035141cc406Sopenharmony_ci 2036141cc406Sopenharmony_ci 2037141cc406Sopenharmony_ci /* get values from options */ 2038141cc406Sopenharmony_ci sane_get_parameters (handle, NULL); 2039141cc406Sopenharmony_ci 2040141cc406Sopenharmony_ci /* sets lamp flag to TRUE */ 2041141cc406Sopenharmony_ci dev->val[OPT_LAMP_CONTROL].w = SANE_TRUE; 2042141cc406Sopenharmony_ci 2043141cc406Sopenharmony_ci /* tests if we do auto setting */ 2044141cc406Sopenharmony_ci if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) 2045141cc406Sopenharmony_ci autoset = 0; 2046141cc406Sopenharmony_ci else 2047141cc406Sopenharmony_ci autoset = 1; 2048141cc406Sopenharmony_ci 2049141cc406Sopenharmony_ci 2050141cc406Sopenharmony_ci /* call start scan */ 2051141cc406Sopenharmony_ci if (dev->color == UMAX_PP_MODE_COLOR) 2052141cc406Sopenharmony_ci { 2053141cc406Sopenharmony_ci delta = umax_pp_get_sync (dev->dpi); 2054141cc406Sopenharmony_ci points = 2 * delta; 2055141cc406Sopenharmony_ci /* first lines are 'garbage' for 610P */ 2056141cc406Sopenharmony_ci if (sanei_umax_pp_getastra () < 1210) 2057141cc406Sopenharmony_ci points *= 2; 2058141cc406Sopenharmony_ci DBG (64, "sane_start:umax_pp_start(%d,%d,%d,%d,%d,1,%X,%X)\n", 2059141cc406Sopenharmony_ci dev->TopX, 2060141cc406Sopenharmony_ci dev->TopY - points, 2061141cc406Sopenharmony_ci dev->BottomX - dev->TopX, 2062141cc406Sopenharmony_ci dev->BottomY - dev->TopY + points, 2063141cc406Sopenharmony_ci dev->dpi, 2064141cc406Sopenharmony_ci (dev->red_gain << 8) + (dev->green_gain << 4) + 2065141cc406Sopenharmony_ci dev->blue_gain, 2066141cc406Sopenharmony_ci (dev->red_offset << 8) + (dev->green_offset << 4) + 2067141cc406Sopenharmony_ci dev->blue_offset); 2068141cc406Sopenharmony_ci 2069141cc406Sopenharmony_ci rc = sanei_umax_pp_start (dev->TopX, 2070141cc406Sopenharmony_ci dev->TopY - points, 2071141cc406Sopenharmony_ci dev->BottomX - dev->TopX, 2072141cc406Sopenharmony_ci dev->BottomY - dev->TopY + points, 2073141cc406Sopenharmony_ci dev->dpi, 2074141cc406Sopenharmony_ci 2, 2075141cc406Sopenharmony_ci autoset, 2076141cc406Sopenharmony_ci (dev->red_gain << 8) | 2077141cc406Sopenharmony_ci (dev->green_gain << 4) | 2078141cc406Sopenharmony_ci dev->blue_gain, 2079141cc406Sopenharmony_ci (dev->red_offset << 8) | 2080141cc406Sopenharmony_ci (dev->green_offset << 4) | 2081141cc406Sopenharmony_ci dev->blue_offset, &(dev->bpp), &(dev->tw), 2082141cc406Sopenharmony_ci &(dev->th)); 2083141cc406Sopenharmony_ci /* we enlarged the scanning zone */ 2084141cc406Sopenharmony_ci /* to allow reordering, we must */ 2085141cc406Sopenharmony_ci /* subtract it from real scanning */ 2086141cc406Sopenharmony_ci /* zone */ 2087141cc406Sopenharmony_ci dev->th -= points; 2088141cc406Sopenharmony_ci DBG (64, "sane_start: bpp=%d,tw=%d,th=%d\n", dev->bpp, dev->tw, 2089141cc406Sopenharmony_ci dev->th); 2090141cc406Sopenharmony_ci } 2091141cc406Sopenharmony_ci else 2092141cc406Sopenharmony_ci { 2093141cc406Sopenharmony_ci DBG (64, "sane_start:umax_pp_start(%d,%d,%d,%d,%d,0,%X,%X)\n", 2094141cc406Sopenharmony_ci dev->TopX, 2095141cc406Sopenharmony_ci dev->TopY, 2096141cc406Sopenharmony_ci dev->BottomX - dev->TopX, 2097141cc406Sopenharmony_ci dev->BottomY - dev->TopY, dev->dpi, dev->gray_gain << 4, 2098141cc406Sopenharmony_ci dev->gray_offset << 4); 2099141cc406Sopenharmony_ci rc = sanei_umax_pp_start (dev->TopX, 2100141cc406Sopenharmony_ci dev->TopY, 2101141cc406Sopenharmony_ci dev->BottomX - dev->TopX, 2102141cc406Sopenharmony_ci dev->BottomY - dev->TopY, 2103141cc406Sopenharmony_ci dev->dpi, 2104141cc406Sopenharmony_ci 1, 2105141cc406Sopenharmony_ci autoset, 2106141cc406Sopenharmony_ci dev->gray_gain << 4, 2107141cc406Sopenharmony_ci dev->gray_offset << 4, &(dev->bpp), 2108141cc406Sopenharmony_ci &(dev->tw), &(dev->th)); 2109141cc406Sopenharmony_ci DBG (64, "sane_start: bpp=%d,tw=%d,th=%d\n", dev->bpp, dev->tw, 2110141cc406Sopenharmony_ci dev->th); 2111141cc406Sopenharmony_ci } 2112141cc406Sopenharmony_ci 2113141cc406Sopenharmony_ci if (rc != UMAX1220P_OK) 2114141cc406Sopenharmony_ci { 2115141cc406Sopenharmony_ci DBG (2, "sane_start: failure\n"); 2116141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2117141cc406Sopenharmony_ci } 2118141cc406Sopenharmony_ci 2119141cc406Sopenharmony_ci /* scan started, no bytes read */ 2120141cc406Sopenharmony_ci dev->state = UMAX_PP_STATE_SCANNING; 2121141cc406Sopenharmony_ci dev->buflen = 0; 2122141cc406Sopenharmony_ci dev->bufread = 0; 2123141cc406Sopenharmony_ci dev->read = 0; 2124141cc406Sopenharmony_ci 2125141cc406Sopenharmony_ci /* leading lines for 610P aren't complete in color mode */ 2126141cc406Sopenharmony_ci /* and should be discarded */ 2127141cc406Sopenharmony_ci if ((sanei_umax_pp_getastra () < 1210) 2128141cc406Sopenharmony_ci && (dev->color == UMAX_PP_MODE_COLOR)) 2129141cc406Sopenharmony_ci { 2130141cc406Sopenharmony_ci rc = 2131141cc406Sopenharmony_ci sanei_umax_pp_read (2 * delta * dev->tw * dev->bpp, dev->tw, dev->dpi, 2132141cc406Sopenharmony_ci 0, 2133141cc406Sopenharmony_ci dev->buf + UMAX_PP_RESERVE - 2134141cc406Sopenharmony_ci 2 * delta * dev->tw * dev->bpp); 2135141cc406Sopenharmony_ci if (rc != UMAX1220P_OK) 2136141cc406Sopenharmony_ci { 2137141cc406Sopenharmony_ci DBG (2, "sane_start: first lines discarding failed\n"); 2138141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2139141cc406Sopenharmony_ci } 2140141cc406Sopenharmony_ci } 2141141cc406Sopenharmony_ci 2142141cc406Sopenharmony_ci /* in case of color, we have to preload blue and green */ 2143141cc406Sopenharmony_ci /* data to allow reordering while later read */ 2144141cc406Sopenharmony_ci if ((dev->color == UMAX_PP_MODE_COLOR) && (delta > 0)) 2145141cc406Sopenharmony_ci { 2146141cc406Sopenharmony_ci rc = 2147141cc406Sopenharmony_ci sanei_umax_pp_read (2 * delta * dev->tw * dev->bpp, dev->tw, dev->dpi, 2148141cc406Sopenharmony_ci 0, 2149141cc406Sopenharmony_ci dev->buf + UMAX_PP_RESERVE - 2150141cc406Sopenharmony_ci 2 * delta * dev->tw * dev->bpp); 2151141cc406Sopenharmony_ci if (rc != UMAX1220P_OK) 2152141cc406Sopenharmony_ci { 2153141cc406Sopenharmony_ci DBG (2, "sane_start: preload buffer failed\n"); 2154141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2155141cc406Sopenharmony_ci } 2156141cc406Sopenharmony_ci } 2157141cc406Sopenharmony_ci 2158141cc406Sopenharmony_ci /* OK .... */ 2159141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2160141cc406Sopenharmony_ci 2161141cc406Sopenharmony_ci} 2162141cc406Sopenharmony_ci 2163141cc406Sopenharmony_ciSANE_Status 2164141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 2165141cc406Sopenharmony_ci SANE_Int * len) 2166141cc406Sopenharmony_ci{ 2167141cc406Sopenharmony_ci Umax_PP_Device *dev = handle; 2168141cc406Sopenharmony_ci long int length; 2169141cc406Sopenharmony_ci int last, rc; 2170141cc406Sopenharmony_ci int x, y, nl, ll; 2171141cc406Sopenharmony_ci SANE_Byte *lbuf; 2172141cc406Sopenharmony_ci int max = 0; 2173141cc406Sopenharmony_ci int min = 255; 2174141cc406Sopenharmony_ci int delta = 0; 2175141cc406Sopenharmony_ci 2176141cc406Sopenharmony_ci 2177141cc406Sopenharmony_ci /* no data until further notice */ 2178141cc406Sopenharmony_ci *len = 0; 2179141cc406Sopenharmony_ci DBG (64, "sane_read(max_len=%d)\n", max_len); 2180141cc406Sopenharmony_ci ll = dev->tw * dev->bpp; 2181141cc406Sopenharmony_ci 2182141cc406Sopenharmony_ci /* sanity check */ 2183141cc406Sopenharmony_ci if (dev->state == UMAX_PP_STATE_CANCELLED) 2184141cc406Sopenharmony_ci { 2185141cc406Sopenharmony_ci DBG (2, "sane_read: scan cancelled\n"); 2186141cc406Sopenharmony_ci DEBUG (); 2187141cc406Sopenharmony_ci 2188141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 2189141cc406Sopenharmony_ci } 2190141cc406Sopenharmony_ci 2191141cc406Sopenharmony_ci /* eof test */ 2192141cc406Sopenharmony_ci if (dev->read >= dev->th * ll) 2193141cc406Sopenharmony_ci { 2194141cc406Sopenharmony_ci DBG (2, "sane_read: end of scan reached\n"); 2195141cc406Sopenharmony_ci return SANE_STATUS_EOF; 2196141cc406Sopenharmony_ci } 2197141cc406Sopenharmony_ci 2198141cc406Sopenharmony_ci /* read data from scanner if needed */ 2199141cc406Sopenharmony_ci if ((dev->buflen == 0) || (dev->bufread >= dev->buflen)) 2200141cc406Sopenharmony_ci { 2201141cc406Sopenharmony_ci DBG (64, "sane_read: reading data from scanner\n"); 2202141cc406Sopenharmony_ci /* absolute number of bytes needed */ 2203141cc406Sopenharmony_ci length = ll * dev->th - dev->read; 2204141cc406Sopenharmony_ci 2205141cc406Sopenharmony_ci /* does all fit in a single last read ? */ 2206141cc406Sopenharmony_ci if (length <= dev->bufsize) 2207141cc406Sopenharmony_ci { 2208141cc406Sopenharmony_ci last = 1; 2209141cc406Sopenharmony_ci } 2210141cc406Sopenharmony_ci else 2211141cc406Sopenharmony_ci { 2212141cc406Sopenharmony_ci last = 0; 2213141cc406Sopenharmony_ci /* round number of scan lines */ 2214141cc406Sopenharmony_ci length = (dev->bufsize / ll) * ll; 2215141cc406Sopenharmony_ci } 2216141cc406Sopenharmony_ci 2217141cc406Sopenharmony_ci 2218141cc406Sopenharmony_ci if (dev->color == UMAX_PP_MODE_COLOR) 2219141cc406Sopenharmony_ci { 2220141cc406Sopenharmony_ci delta = umax_pp_get_sync (dev->dpi); 2221141cc406Sopenharmony_ci rc = 2222141cc406Sopenharmony_ci sanei_umax_pp_read (length, dev->tw, dev->dpi, last, 2223141cc406Sopenharmony_ci dev->buf + UMAX_PP_RESERVE); 2224141cc406Sopenharmony_ci } 2225141cc406Sopenharmony_ci else 2226141cc406Sopenharmony_ci rc = sanei_umax_pp_read (length, dev->tw, dev->dpi, last, dev->buf); 2227141cc406Sopenharmony_ci if (rc != UMAX1220P_OK) 2228141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2229141cc406Sopenharmony_ci dev->buflen = length; 2230141cc406Sopenharmony_ci DBG (64, "sane_read: got %ld bytes of data from scanner\n", length); 2231141cc406Sopenharmony_ci 2232141cc406Sopenharmony_ci /* we transform data for software lineart */ 2233141cc406Sopenharmony_ci if (dev->color == UMAX_PP_MODE_LINEART) 2234141cc406Sopenharmony_ci { 2235141cc406Sopenharmony_ci DBG (64, "sane_read: software lineart\n"); 2236141cc406Sopenharmony_ci 2237141cc406Sopenharmony_ci for (y = 0; y < length; y++) 2238141cc406Sopenharmony_ci { 2239141cc406Sopenharmony_ci if (dev->buf[y] > max) 2240141cc406Sopenharmony_ci max = dev->buf[y]; 2241141cc406Sopenharmony_ci if (dev->buf[y] < min) 2242141cc406Sopenharmony_ci min = dev->buf[y]; 2243141cc406Sopenharmony_ci } 2244141cc406Sopenharmony_ci max = (min + max) / 2; 2245141cc406Sopenharmony_ci for (y = 0; y < length; y++) 2246141cc406Sopenharmony_ci { 2247141cc406Sopenharmony_ci if (dev->buf[y] > max) 2248141cc406Sopenharmony_ci dev->buf[y] = 255; 2249141cc406Sopenharmony_ci else 2250141cc406Sopenharmony_ci dev->buf[y] = 0; 2251141cc406Sopenharmony_ci } 2252141cc406Sopenharmony_ci } 2253141cc406Sopenharmony_ci else if (dev->color == UMAX_PP_MODE_COLOR) 2254141cc406Sopenharmony_ci { 2255141cc406Sopenharmony_ci /* number of lines */ 2256141cc406Sopenharmony_ci nl = dev->buflen / ll; 2257141cc406Sopenharmony_ci DBG (64, "sane_read: reordering %ld bytes of data (lines=%d)\n", 2258141cc406Sopenharmony_ci length, nl); 2259141cc406Sopenharmony_ci lbuf = (SANE_Byte *) malloc (dev->bufsize + UMAX_PP_RESERVE); 2260141cc406Sopenharmony_ci if (lbuf == NULL) 2261141cc406Sopenharmony_ci { 2262141cc406Sopenharmony_ci DBG (1, "sane_read: couldn't allocate %ld bytes\n", 2263141cc406Sopenharmony_ci dev->bufsize + UMAX_PP_RESERVE); 2264141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2265141cc406Sopenharmony_ci } 2266141cc406Sopenharmony_ci /* reorder data in R,G,B values */ 2267141cc406Sopenharmony_ci for (y = 0; y < nl; y++) 2268141cc406Sopenharmony_ci { 2269141cc406Sopenharmony_ci for (x = 0; x < dev->tw; x++) 2270141cc406Sopenharmony_ci { 2271141cc406Sopenharmony_ci switch (sanei_umax_pp_getastra ()) 2272141cc406Sopenharmony_ci { 2273141cc406Sopenharmony_ci case 610: 2274141cc406Sopenharmony_ci /* green value: sync'ed */ 2275141cc406Sopenharmony_ci lbuf[x * dev->bpp + y * ll + 1 + UMAX_PP_RESERVE] = 2276141cc406Sopenharmony_ci dev->buf[x + y * ll + 2 * dev->tw + UMAX_PP_RESERVE]; 2277141cc406Sopenharmony_ci 2278141cc406Sopenharmony_ci /* blue value, +delta line ahead of sync */ 2279141cc406Sopenharmony_ci lbuf[x * dev->bpp + y * ll + 2 + UMAX_PP_RESERVE] = 2280141cc406Sopenharmony_ci dev->buf[x + (y - delta) * ll + dev->tw + 2281141cc406Sopenharmony_ci UMAX_PP_RESERVE]; 2282141cc406Sopenharmony_ci 2283141cc406Sopenharmony_ci /* red value, +2*delta line ahead of sync */ 2284141cc406Sopenharmony_ci lbuf[x * dev->bpp + y * ll + UMAX_PP_RESERVE] = 2285141cc406Sopenharmony_ci dev->buf[x + (y - 2 * delta) * ll + UMAX_PP_RESERVE]; 2286141cc406Sopenharmony_ci 2287141cc406Sopenharmony_ci break; 2288141cc406Sopenharmony_ci default: 2289141cc406Sopenharmony_ci /* red value: sync'ed */ 2290141cc406Sopenharmony_ci lbuf[x * dev->bpp + y * ll + UMAX_PP_RESERVE] = 2291141cc406Sopenharmony_ci dev->buf[x + y * ll + 2 * dev->tw + UMAX_PP_RESERVE]; 2292141cc406Sopenharmony_ci 2293141cc406Sopenharmony_ci /* green value, +delta line ahead of sync */ 2294141cc406Sopenharmony_ci lbuf[x * dev->bpp + y * ll + 1 + UMAX_PP_RESERVE] = 2295141cc406Sopenharmony_ci dev->buf[x + (y - delta) * ll + dev->tw + 2296141cc406Sopenharmony_ci UMAX_PP_RESERVE]; 2297141cc406Sopenharmony_ci 2298141cc406Sopenharmony_ci /* blue value, +2*delta line ahead of sync */ 2299141cc406Sopenharmony_ci lbuf[x * dev->bpp + y * ll + 2 + UMAX_PP_RESERVE] = 2300141cc406Sopenharmony_ci dev->buf[x + (y - 2 * delta) * ll + UMAX_PP_RESERVE]; 2301141cc406Sopenharmony_ci } 2302141cc406Sopenharmony_ci } 2303141cc406Sopenharmony_ci } 2304141cc406Sopenharmony_ci /* store last data lines for next reordering */ 2305141cc406Sopenharmony_ci if (!last) 2306141cc406Sopenharmony_ci memcpy (lbuf + UMAX_PP_RESERVE - 2 * delta * ll, 2307141cc406Sopenharmony_ci dev->buf + UMAX_PP_RESERVE + dev->buflen - 2 * delta * ll, 2308141cc406Sopenharmony_ci 2 * delta * ll); 2309141cc406Sopenharmony_ci free (dev->buf); 2310141cc406Sopenharmony_ci dev->buf = lbuf; 2311141cc406Sopenharmony_ci } 2312141cc406Sopenharmony_ci dev->bufread = 0; 2313141cc406Sopenharmony_ci } 2314141cc406Sopenharmony_ci 2315141cc406Sopenharmony_ci /* how much get data we can get from memory buffer */ 2316141cc406Sopenharmony_ci length = dev->buflen - dev->bufread; 2317141cc406Sopenharmony_ci DBG (64, "sane_read: %ld bytes of data available\n", length); 2318141cc406Sopenharmony_ci if (length > max_len) 2319141cc406Sopenharmony_ci length = max_len; 2320141cc406Sopenharmony_ci 2321141cc406Sopenharmony_ci 2322141cc406Sopenharmony_ci 2323141cc406Sopenharmony_ci if (dev->color == UMAX_PP_MODE_COLOR) 2324141cc406Sopenharmony_ci memcpy (buf, dev->buf + dev->bufread + UMAX_PP_RESERVE, length); 2325141cc406Sopenharmony_ci else 2326141cc406Sopenharmony_ci memcpy (buf, dev->buf + dev->bufread, length); 2327141cc406Sopenharmony_ci *len = length; 2328141cc406Sopenharmony_ci dev->bufread += length; 2329141cc406Sopenharmony_ci dev->read += length; 2330141cc406Sopenharmony_ci DBG (64, "sane_read: %ld bytes read\n", length); 2331141cc406Sopenharmony_ci 2332141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2333141cc406Sopenharmony_ci 2334141cc406Sopenharmony_ci} 2335141cc406Sopenharmony_ci 2336141cc406Sopenharmony_civoid 2337141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 2338141cc406Sopenharmony_ci{ 2339141cc406Sopenharmony_ci Umax_PP_Device *dev = handle; 2340141cc406Sopenharmony_ci int rc; 2341141cc406Sopenharmony_ci 2342141cc406Sopenharmony_ci DBG (64, "sane_cancel\n"); 2343141cc406Sopenharmony_ci if (dev->state == UMAX_PP_STATE_IDLE) 2344141cc406Sopenharmony_ci { 2345141cc406Sopenharmony_ci DBG (3, "cancel: cancelling idle \n"); 2346141cc406Sopenharmony_ci return; 2347141cc406Sopenharmony_ci } 2348141cc406Sopenharmony_ci if (dev->state == UMAX_PP_STATE_SCANNING) 2349141cc406Sopenharmony_ci { 2350141cc406Sopenharmony_ci DBG (3, "cancel: stopping current scan\n"); 2351141cc406Sopenharmony_ci 2352141cc406Sopenharmony_ci dev->buflen = 0; 2353141cc406Sopenharmony_ci 2354141cc406Sopenharmony_ci dev->state = UMAX_PP_STATE_CANCELLED; 2355141cc406Sopenharmony_ci sanei_umax_pp_cancel (); 2356141cc406Sopenharmony_ci } 2357141cc406Sopenharmony_ci else 2358141cc406Sopenharmony_ci { 2359141cc406Sopenharmony_ci /* STATE_CANCELLED */ 2360141cc406Sopenharmony_ci DBG (2, "cancel: checking if scanner is still parking head .... \n"); 2361141cc406Sopenharmony_ci 2362141cc406Sopenharmony_ci rc = sanei_umax_pp_status (); 2363141cc406Sopenharmony_ci 2364141cc406Sopenharmony_ci /* check if scanner busy parking */ 2365141cc406Sopenharmony_ci if (rc == UMAX1220P_BUSY) 2366141cc406Sopenharmony_ci { 2367141cc406Sopenharmony_ci DBG (2, "cancel: scanner busy\n"); 2368141cc406Sopenharmony_ci return; 2369141cc406Sopenharmony_ci } 2370141cc406Sopenharmony_ci dev->state = UMAX_PP_STATE_IDLE; 2371141cc406Sopenharmony_ci } 2372141cc406Sopenharmony_ci} 2373141cc406Sopenharmony_ci 2374141cc406Sopenharmony_ciSANE_Status 2375141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 2376141cc406Sopenharmony_ci{ 2377141cc406Sopenharmony_ci DBG (129, "unused arg: handle = %p, non_blocking = %d\n", 2378141cc406Sopenharmony_ci handle, (int) non_blocking); 2379141cc406Sopenharmony_ci 2380141cc406Sopenharmony_ci DBG (2, "set_io_mode: not supported\n"); 2381141cc406Sopenharmony_ci 2382141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2383141cc406Sopenharmony_ci} 2384141cc406Sopenharmony_ci 2385141cc406Sopenharmony_ciSANE_Status 2386141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 2387141cc406Sopenharmony_ci{ 2388141cc406Sopenharmony_ci 2389141cc406Sopenharmony_ci DBG (129, "unused arg: handle = %p, fd = %p\n", handle, (void *) fd); 2390141cc406Sopenharmony_ci 2391141cc406Sopenharmony_ci DBG (2, "get_select_fd: not supported\n"); 2392141cc406Sopenharmony_ci 2393141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2394141cc406Sopenharmony_ci} 2395