1141cc406Sopenharmony_ci/*************************************************************************** 2141cc406Sopenharmony_ci * SANE - Scanner Access Now Easy. 3141cc406Sopenharmony_ci 4141cc406Sopenharmony_ci microtek2.c 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file (C) 1998, 1999 Bernd Schroeder 7141cc406Sopenharmony_ci modifications 2000, 2001 Karsten Festag 8141cc406Sopenharmony_ci 9141cc406Sopenharmony_ci This file is part of the SANE package. 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 12141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 13141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 14141cc406Sopenharmony_ci License, or (at your option) any later version. 15141cc406Sopenharmony_ci 16141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 17141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 18141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19141cc406Sopenharmony_ci General Public License for more details. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 22141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 25141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 28141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 29141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 30141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 31141cc406Sopenharmony_ci account of linking the SANE library code into it. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 34141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 35141cc406Sopenharmony_ci License. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 38141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 39141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 42141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 43141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci *************************************************************************** 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci This file implements a SANE backend for Microtek scanners with 48141cc406Sopenharmony_ci SCSI-2 command set. 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci (feedback to: bernd@aquila.muc.de) 51141cc406Sopenharmony_ci ( karsten.festag@t-online.de) 52141cc406Sopenharmony_ci ***************************************************************************/ 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci#ifdef _AIX 56141cc406Sopenharmony_ci# include <lalloca.h> /* MUST come first for AIX! */ 57141cc406Sopenharmony_ci#endif 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci#include "../include/sane/config.h" 60141cc406Sopenharmony_ci#include "../include/lalloca.h" 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_ci#include <stdio.h> 63141cc406Sopenharmony_ci#include <stdlib.h> 64141cc406Sopenharmony_ci#include <string.h> 65141cc406Sopenharmony_ci#include <unistd.h> 66141cc406Sopenharmony_ci#include <fcntl.h> 67141cc406Sopenharmony_ci#include <ctype.h> 68141cc406Sopenharmony_ci#include <sys/types.h> 69141cc406Sopenharmony_ci#include <signal.h> 70141cc406Sopenharmony_ci#include <errno.h> 71141cc406Sopenharmony_ci#include <math.h> 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_ci#include "../include/_stdint.h" 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci#ifdef HAVE_AUTHORIZATION 76141cc406Sopenharmony_ci#include <sys/stat.h> 77141cc406Sopenharmony_ci#endif 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci#include "../include/sane/sane.h" 80141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 81141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 82141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 83141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 84141cc406Sopenharmony_ci#include "../include/sane/sanei_thread.h" 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci#ifndef TESTBACKEND 87141cc406Sopenharmony_ci#define BACKEND_NAME microtek2 88141cc406Sopenharmony_ci#else 89141cc406Sopenharmony_ci#define BACKEND_NAME microtek2_test 90141cc406Sopenharmony_ci#endif 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci/* for testing*/ 93141cc406Sopenharmony_ci/*#define NO_PHANTOMTYPE_SHADING*/ 94141cc406Sopenharmony_ci 95141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci#include "microtek2.h" 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci#ifdef HAVE_AUTHORIZATION 100141cc406Sopenharmony_cistatic SANE_Auth_Callback auth_callback; 101141cc406Sopenharmony_ci#endif 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_cistatic int md_num_devices = 0; /* number of devices from config file */ 104141cc406Sopenharmony_cistatic Microtek2_Device *md_first_dev = NULL; /* list of known devices */ 105141cc406Sopenharmony_cistatic Microtek2_Scanner *ms_first_handle = NULL; /* list of open scanners */ 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_ci/* options that can be configured in the config file */ 108141cc406Sopenharmony_cistatic Config_Options md_options = 109141cc406Sopenharmony_ci { 1.0, "off", "off", "off", "off", "off", "off"}; 110141cc406Sopenharmony_cistatic Config_Temp *md_config_temp = NULL; 111141cc406Sopenharmony_cistatic int md_dump = 0; /* from config file: */ 112141cc406Sopenharmony_ci /* 1: inquiry + scanner attributes */ 113141cc406Sopenharmony_ci /* 2: + all scsi commands and data */ 114141cc406Sopenharmony_ci /* 3: + all scan data */ 115141cc406Sopenharmony_cistatic int md_dump_clear = 1; 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci/*---------- sane_cancel() ---------------------------------------------------*/ 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_civoid 121141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 122141cc406Sopenharmony_ci{ 123141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci DBG(30, "sane_cancel: handle=%p\n", handle); 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci if ( ms->scanning == SANE_TRUE ) 128141cc406Sopenharmony_ci cleanup_scanner(ms); 129141cc406Sopenharmony_ci ms->cancelled = SANE_TRUE; 130141cc406Sopenharmony_ci ms->fd[0] = ms->fd[1] = -1; 131141cc406Sopenharmony_ci} 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_ci/*---------- sane_close() ----------------------------------------------------*/ 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_civoid 138141cc406Sopenharmony_cisane_close (SANE_Handle handle) 139141cc406Sopenharmony_ci{ 140141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 141141cc406Sopenharmony_ci 142141cc406Sopenharmony_ci DBG(30, "sane_close: ms=%p\n", (void *) ms); 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci if ( ! ms ) 145141cc406Sopenharmony_ci return; 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci /* free malloc'ed stuff */ 148141cc406Sopenharmony_ci cleanup_scanner(ms); 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci /* remove Scanner from linked list */ 151141cc406Sopenharmony_ci if ( ms_first_handle == ms ) 152141cc406Sopenharmony_ci ms_first_handle = ms->next; 153141cc406Sopenharmony_ci else 154141cc406Sopenharmony_ci { 155141cc406Sopenharmony_ci Microtek2_Scanner *ts = ms_first_handle; 156141cc406Sopenharmony_ci while ( (ts != NULL) && (ts->next != ms) ) 157141cc406Sopenharmony_ci ts = ts->next; 158141cc406Sopenharmony_ci ts->next = ts->next->next; /* == ms->next */ 159141cc406Sopenharmony_ci } 160141cc406Sopenharmony_ci DBG(100, "free ms at %p\n", (void *) ms); 161141cc406Sopenharmony_ci free((void *) ms); 162141cc406Sopenharmony_ci ms = NULL; 163141cc406Sopenharmony_ci} 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_ci 166141cc406Sopenharmony_ci/*---------- sane_exit() -----------------------------------------------------*/ 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_civoid 169141cc406Sopenharmony_cisane_exit (void) 170141cc406Sopenharmony_ci{ 171141cc406Sopenharmony_ci Microtek2_Device *next; 172141cc406Sopenharmony_ci int i; 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci DBG(30, "sane_exit:\n"); 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci /* close all leftover Scanners */ 177141cc406Sopenharmony_ci while (ms_first_handle != NULL) 178141cc406Sopenharmony_ci sane_close(ms_first_handle); 179141cc406Sopenharmony_ci /* free up device list */ 180141cc406Sopenharmony_ci while (md_first_dev != NULL) 181141cc406Sopenharmony_ci { 182141cc406Sopenharmony_ci next = md_first_dev->next; 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci for ( i = 0; i < 4; i++ ) 185141cc406Sopenharmony_ci { 186141cc406Sopenharmony_ci if ( md_first_dev->custom_gamma_table[i] ) 187141cc406Sopenharmony_ci { 188141cc406Sopenharmony_ci DBG(100, "free md_first_dev->custom_gamma_table[%d] at %p\n", 189141cc406Sopenharmony_ci i, (void *) md_first_dev->custom_gamma_table[i]); 190141cc406Sopenharmony_ci free((void *) md_first_dev->custom_gamma_table[i]); 191141cc406Sopenharmony_ci md_first_dev->custom_gamma_table[i] = NULL; 192141cc406Sopenharmony_ci } 193141cc406Sopenharmony_ci } 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ci if ( md_first_dev->shading_table_w ) 196141cc406Sopenharmony_ci { 197141cc406Sopenharmony_ci DBG(100, "free md_first_dev->shading_table_w at %p\n", 198141cc406Sopenharmony_ci (void *) md_first_dev->shading_table_w); 199141cc406Sopenharmony_ci free((void *) md_first_dev->shading_table_w); 200141cc406Sopenharmony_ci md_first_dev->shading_table_w = NULL; 201141cc406Sopenharmony_ci } 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci if ( md_first_dev->shading_table_d ) 204141cc406Sopenharmony_ci { 205141cc406Sopenharmony_ci DBG(100, "free md_first_dev->shading_table_d at %p\n", 206141cc406Sopenharmony_ci (void *) md_first_dev->shading_table_d); 207141cc406Sopenharmony_ci free((void *) md_first_dev->shading_table_d); 208141cc406Sopenharmony_ci md_first_dev->shading_table_d = NULL; 209141cc406Sopenharmony_ci } 210141cc406Sopenharmony_ci 211141cc406Sopenharmony_ci DBG(100, "free md_first_dev at %p\n", (void *) md_first_dev); 212141cc406Sopenharmony_ci free((void *) md_first_dev); 213141cc406Sopenharmony_ci md_first_dev = next; 214141cc406Sopenharmony_ci } 215141cc406Sopenharmony_ci sane_get_devices(NULL, SANE_FALSE); /* free list of SANE_Devices */ 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci DBG(30, "sane_exit: MICROTEK2 says goodbye.\n"); 218141cc406Sopenharmony_ci} 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci/*---------- sane_get_devices()-----------------------------------------------*/ 222141cc406Sopenharmony_ci 223141cc406Sopenharmony_ciSANE_Status 224141cc406Sopenharmony_cisane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only) 225141cc406Sopenharmony_ci{ 226141cc406Sopenharmony_ci /* return a list of available devices; available here means that we get */ 227141cc406Sopenharmony_ci /* a positive response to an 'INQUIRY' and possibly to a */ 228141cc406Sopenharmony_ci /* 'READ SCANNER ATTRIBUTE' call */ 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci static const SANE_Device **sd_list = NULL; 231141cc406Sopenharmony_ci Microtek2_Device *md; 232141cc406Sopenharmony_ci SANE_Status status; 233141cc406Sopenharmony_ci int index; 234141cc406Sopenharmony_ci 235141cc406Sopenharmony_ci DBG(30, "sane_get_devices: local_only=%d\n", local_only); 236141cc406Sopenharmony_ci 237141cc406Sopenharmony_ci /* this is hack to get the list freed with a call from sane_exit() */ 238141cc406Sopenharmony_ci if ( device_list == NULL ) 239141cc406Sopenharmony_ci { 240141cc406Sopenharmony_ci if ( sd_list ) 241141cc406Sopenharmony_ci { 242141cc406Sopenharmony_ci DBG(100, "free sd_list at %p\n", (void *) sd_list); 243141cc406Sopenharmony_ci free(sd_list); 244141cc406Sopenharmony_ci sd_list=NULL; 245141cc406Sopenharmony_ci } 246141cc406Sopenharmony_ci DBG(30, "sane_get_devices: sd_list_freed\n"); 247141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 248141cc406Sopenharmony_ci } 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci /* first free old list, if there is one; frontend wants a new list */ 251141cc406Sopenharmony_ci if ( sd_list ) 252141cc406Sopenharmony_ci { 253141cc406Sopenharmony_ci DBG(100, "free sd_list at %p\n", (void *) sd_list); 254141cc406Sopenharmony_ci free(sd_list); /* free array of pointers */ 255141cc406Sopenharmony_ci } 256141cc406Sopenharmony_ci 257141cc406Sopenharmony_ci sd_list = (const SANE_Device **) 258141cc406Sopenharmony_ci malloc( (md_num_devices + 1) * sizeof(SANE_Device **)); 259141cc406Sopenharmony_ci DBG(100, "sane_get_devices: sd_list=%p, malloc'd %lu bytes\n", 260141cc406Sopenharmony_ci (void *) sd_list, (u_long) ((md_num_devices + 1) * sizeof(SANE_Device **))); 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci if ( ! sd_list ) 263141cc406Sopenharmony_ci { 264141cc406Sopenharmony_ci DBG(1, "sane_get_devices: malloc() for sd_list failed\n"); 265141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 266141cc406Sopenharmony_ci } 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci *device_list = sd_list; 269141cc406Sopenharmony_ci index = 0; 270141cc406Sopenharmony_ci md = md_first_dev; 271141cc406Sopenharmony_ci while ( md ) 272141cc406Sopenharmony_ci { 273141cc406Sopenharmony_ci status = attach(md); 274141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 275141cc406Sopenharmony_ci { 276141cc406Sopenharmony_ci DBG(10, "sane_get_devices: attach status '%s'\n", 277141cc406Sopenharmony_ci sane_strstatus(status)); 278141cc406Sopenharmony_ci md = md->next; 279141cc406Sopenharmony_ci continue; 280141cc406Sopenharmony_ci } 281141cc406Sopenharmony_ci 282141cc406Sopenharmony_ci /* check whether unit is ready, if so add it to the list */ 283141cc406Sopenharmony_ci status = scsi_test_unit_ready(md); 284141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 285141cc406Sopenharmony_ci { 286141cc406Sopenharmony_ci DBG(10, "sane_get_devices: test_unit_ready status '%s'\n", 287141cc406Sopenharmony_ci sane_strstatus(status)); 288141cc406Sopenharmony_ci md = md->next; 289141cc406Sopenharmony_ci continue; 290141cc406Sopenharmony_ci } 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci sd_list[index] = &md->sane; 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci ++index; 295141cc406Sopenharmony_ci md = md->next; 296141cc406Sopenharmony_ci } 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci sd_list[index] = NULL; 299141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 300141cc406Sopenharmony_ci} 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci/*---------- sane_get_parameters() -------------------------------------------*/ 304141cc406Sopenharmony_ci 305141cc406Sopenharmony_ciSANE_Status 306141cc406Sopenharmony_cisane_get_parameters(SANE_Handle handle, SANE_Parameters *params) 307141cc406Sopenharmony_ci{ 308141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 309141cc406Sopenharmony_ci Microtek2_Device *md; 310141cc406Sopenharmony_ci Option_Value *val; 311141cc406Sopenharmony_ci Microtek2_Info *mi; 312141cc406Sopenharmony_ci int mode; 313141cc406Sopenharmony_ci int depth; 314141cc406Sopenharmony_ci int bits_pp_in; /* bits per pixel from scanner */ 315141cc406Sopenharmony_ci int bits_pp_out; /* bits_per_pixel transferred to frontend */ 316141cc406Sopenharmony_ci int bytes_per_line; 317141cc406Sopenharmony_ci double x_pixel_per_mm; 318141cc406Sopenharmony_ci double y_pixel_per_mm; 319141cc406Sopenharmony_ci double x1_pixel; 320141cc406Sopenharmony_ci double y1_pixel; 321141cc406Sopenharmony_ci double width_pixel; 322141cc406Sopenharmony_ci double height_pixel; 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci DBG(40, "sane_get_parameters: handle=%p, params=%p\n", handle, 326141cc406Sopenharmony_ci (void *) params); 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci md = ms->dev; 330141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 331141cc406Sopenharmony_ci val= ms->val; 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci if ( ! ms->scanning ) /* get an estimate for the params */ 334141cc406Sopenharmony_ci { 335141cc406Sopenharmony_ci 336141cc406Sopenharmony_ci get_scan_mode_and_depth(ms, &mode, &depth, &bits_pp_in, &bits_pp_out); 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci switch ( mode ) 339141cc406Sopenharmony_ci { 340141cc406Sopenharmony_ci case MS_MODE_COLOR: 341141cc406Sopenharmony_ci if ( mi->onepass ) 342141cc406Sopenharmony_ci { 343141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_RGB; 344141cc406Sopenharmony_ci ms->params.last_frame = SANE_TRUE; 345141cc406Sopenharmony_ci } 346141cc406Sopenharmony_ci else 347141cc406Sopenharmony_ci { 348141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_RED; 349141cc406Sopenharmony_ci ms->params.last_frame = SANE_FALSE; 350141cc406Sopenharmony_ci } 351141cc406Sopenharmony_ci break; 352141cc406Sopenharmony_ci case MS_MODE_GRAY: 353141cc406Sopenharmony_ci case MS_MODE_HALFTONE: 354141cc406Sopenharmony_ci case MS_MODE_LINEART: 355141cc406Sopenharmony_ci case MS_MODE_LINEARTFAKE: 356141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_GRAY; 357141cc406Sopenharmony_ci ms->params.last_frame = SANE_TRUE; 358141cc406Sopenharmony_ci break; 359141cc406Sopenharmony_ci default: 360141cc406Sopenharmony_ci DBG(1, "sane_get_parameters: Unknown scan mode %d\n", mode); 361141cc406Sopenharmony_ci break; 362141cc406Sopenharmony_ci } 363141cc406Sopenharmony_ci 364141cc406Sopenharmony_ci ms->params.depth = (SANE_Int) bits_pp_out; 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci /* calculate lines, pixels per line and bytes per line */ 367141cc406Sopenharmony_ci if ( val[OPT_RESOLUTION_BIND].w == SANE_TRUE ) 368141cc406Sopenharmony_ci { 369141cc406Sopenharmony_ci x_pixel_per_mm = y_pixel_per_mm = 370141cc406Sopenharmony_ci SANE_UNFIX(val[OPT_RESOLUTION].w) / MM_PER_INCH; 371141cc406Sopenharmony_ci DBG(30, "sane_get_parameters: x_res=y_res=%f\n", 372141cc406Sopenharmony_ci SANE_UNFIX(val[OPT_RESOLUTION].w)); 373141cc406Sopenharmony_ci } 374141cc406Sopenharmony_ci else 375141cc406Sopenharmony_ci { 376141cc406Sopenharmony_ci x_pixel_per_mm = SANE_UNFIX(val[OPT_RESOLUTION].w) / MM_PER_INCH; 377141cc406Sopenharmony_ci y_pixel_per_mm = SANE_UNFIX(val[OPT_Y_RESOLUTION].w) / MM_PER_INCH; 378141cc406Sopenharmony_ci DBG(30, "sane_get_parameters: x_res=%f, y_res=%f\n", 379141cc406Sopenharmony_ci SANE_UNFIX(val[OPT_RESOLUTION].w), 380141cc406Sopenharmony_ci SANE_UNFIX(val[OPT_Y_RESOLUTION].w)); 381141cc406Sopenharmony_ci } 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci DBG(30, "sane_get_parameters: x_ppm=%f, y_ppm=%f\n", 384141cc406Sopenharmony_ci x_pixel_per_mm, y_pixel_per_mm); 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci y1_pixel = SANE_UNFIX(ms->val[OPT_TL_Y].w) * y_pixel_per_mm; 387141cc406Sopenharmony_ci height_pixel = fabs(SANE_UNFIX(ms->val[OPT_BR_Y].w) * y_pixel_per_mm 388141cc406Sopenharmony_ci - y1_pixel) + 0.5; 389141cc406Sopenharmony_ci ms->params.lines = (SANE_Int) height_pixel; 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci x1_pixel = SANE_UNFIX(ms->val[OPT_TL_X].w) * x_pixel_per_mm; 392141cc406Sopenharmony_ci width_pixel = fabs(SANE_UNFIX(ms->val[OPT_BR_X].w) * x_pixel_per_mm 393141cc406Sopenharmony_ci - x1_pixel) + 0.5; 394141cc406Sopenharmony_ci ms->params.pixels_per_line = (SANE_Int) width_pixel; 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci 397141cc406Sopenharmony_ci if ( bits_pp_out == 1 ) 398141cc406Sopenharmony_ci bytes_per_line = (width_pixel + 7 ) / 8; 399141cc406Sopenharmony_ci else 400141cc406Sopenharmony_ci { 401141cc406Sopenharmony_ci bytes_per_line = ( width_pixel * bits_pp_out ) / 8 ; 402141cc406Sopenharmony_ci if ( mode == MS_MODE_COLOR && mi->onepass ) 403141cc406Sopenharmony_ci bytes_per_line *= 3; 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci ms->params.bytes_per_line = (SANE_Int) bytes_per_line; 406141cc406Sopenharmony_ci } /* if ms->scanning */ 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci if ( params ) 409141cc406Sopenharmony_ci *params = ms->params; 410141cc406Sopenharmony_ci 411141cc406Sopenharmony_ci DBG(30,"sane_get_parameters: format=%d, last_frame=%d, lines=%d\n", 412141cc406Sopenharmony_ci ms->params.format,ms->params.last_frame, ms->params.lines); 413141cc406Sopenharmony_ci DBG(30,"sane_get_parameters: depth=%d, ppl=%d, bpl=%d\n", 414141cc406Sopenharmony_ci ms->params.depth,ms->params.pixels_per_line, ms->params.bytes_per_line); 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 417141cc406Sopenharmony_ci} 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci/*---------- sane_get_select_fd() --------------------------------------------*/ 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_ciSANE_Status 423141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int *fd) 424141cc406Sopenharmony_ci{ 425141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci DBG(30, "sane_get_select_fd: ms=%p\n", (void *) ms); 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci if ( ! ms->scanning ) 431141cc406Sopenharmony_ci { 432141cc406Sopenharmony_ci DBG(1, "sane_get_select_fd: Scanner not scanning\n"); 433141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 434141cc406Sopenharmony_ci } 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci *fd = (SANE_Int) ms->fd[0]; 437141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 438141cc406Sopenharmony_ci} 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci/*---------- sane_init() -----------------------------------------------------*/ 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ciSANE_Status 444141cc406Sopenharmony_ci#ifdef HAVE_AUTHORIZATION 445141cc406Sopenharmony_cisane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) 446141cc406Sopenharmony_ci#else 447141cc406Sopenharmony_cisane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) 448141cc406Sopenharmony_ci#endif 449141cc406Sopenharmony_ci{ 450141cc406Sopenharmony_ci Microtek2_Device *md; 451141cc406Sopenharmony_ci FILE *fp; 452141cc406Sopenharmony_ci 453141cc406Sopenharmony_ci 454141cc406Sopenharmony_ci DBG_INIT(); 455141cc406Sopenharmony_ci DBG(1, "sane_init: Microtek2 (v%d.%d build %s) says hello...\n", 456141cc406Sopenharmony_ci MICROTEK2_MAJOR, MICROTEK2_MINOR, MICROTEK2_BUILD); 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci if ( version_code ) 459141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci#ifdef HAVE_AUTHORIZATION 462141cc406Sopenharmony_ci auth_callback = authorize; 463141cc406Sopenharmony_ci#endif 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_ci sanei_thread_init(); 466141cc406Sopenharmony_ci 467141cc406Sopenharmony_ci fp = sanei_config_open(MICROTEK2_CONFIG_FILE); 468141cc406Sopenharmony_ci if ( fp == NULL ) 469141cc406Sopenharmony_ci DBG(10, "sane_init: file not opened: '%s'\n", MICROTEK2_CONFIG_FILE); 470141cc406Sopenharmony_ci else 471141cc406Sopenharmony_ci { 472141cc406Sopenharmony_ci /* check config file for devices and associated options */ 473141cc406Sopenharmony_ci parse_config_file(fp, &md_config_temp); 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci while ( md_config_temp ) 476141cc406Sopenharmony_ci { 477141cc406Sopenharmony_ci sanei_config_attach_matching_devices(md_config_temp->device, 478141cc406Sopenharmony_ci attach_one); 479141cc406Sopenharmony_ci if ( md_config_temp->next ) /* go to next device, if existent */ 480141cc406Sopenharmony_ci md_config_temp = md_config_temp->next; 481141cc406Sopenharmony_ci else 482141cc406Sopenharmony_ci break; 483141cc406Sopenharmony_ci } 484141cc406Sopenharmony_ci 485141cc406Sopenharmony_ci fclose(fp); 486141cc406Sopenharmony_ci } 487141cc406Sopenharmony_ci 488141cc406Sopenharmony_ci if ( md_first_dev == NULL ) 489141cc406Sopenharmony_ci { 490141cc406Sopenharmony_ci /* config file not found or no valid entry; default to /dev/scanner */ 491141cc406Sopenharmony_ci /* instead of insisting on config file */ 492141cc406Sopenharmony_ci add_device_list("/dev/scanner", &md); 493141cc406Sopenharmony_ci if ( md ) 494141cc406Sopenharmony_ci attach(md); 495141cc406Sopenharmony_ci } 496141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 497141cc406Sopenharmony_ci} 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci/*---------- sane_open() -----------------------------------------------------*/ 501141cc406Sopenharmony_ci 502141cc406Sopenharmony_ciSANE_Status 503141cc406Sopenharmony_cisane_open(SANE_String_Const name, SANE_Handle *handle) 504141cc406Sopenharmony_ci{ 505141cc406Sopenharmony_ci SANE_Status status; 506141cc406Sopenharmony_ci Microtek2_Scanner *ms; 507141cc406Sopenharmony_ci Microtek2_Device *md; 508141cc406Sopenharmony_ci#ifdef HAVE_AUTHORIZATION 509141cc406Sopenharmony_ci struct stat st; 510141cc406Sopenharmony_ci int rc; 511141cc406Sopenharmony_ci#endif 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci DBG(30, "sane_open: device='%s'\n", name); 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci *handle = NULL; 517141cc406Sopenharmony_ci md = md_first_dev; 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci if ( name ) 520141cc406Sopenharmony_ci { 521141cc406Sopenharmony_ci /* add_device_list() returns a pointer to the device struct if */ 522141cc406Sopenharmony_ci /* the device is known or newly added, else it returns NULL */ 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_ci status = add_device_list(name, &md); 525141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 526141cc406Sopenharmony_ci return status; 527141cc406Sopenharmony_ci } 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci if ( ! md ) 530141cc406Sopenharmony_ci { 531141cc406Sopenharmony_ci DBG(10, "sane_open: invalid device name '%s'\n", name); 532141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 533141cc406Sopenharmony_ci } 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci /* attach calls INQUIRY and READ SCANNER ATTRIBUTES */ 536141cc406Sopenharmony_ci status = attach(md); 537141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 538141cc406Sopenharmony_ci return status; 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci ms = malloc(sizeof(Microtek2_Scanner)); 541141cc406Sopenharmony_ci DBG(100, "sane_open: ms=%p, malloc'd %lu bytes\n", 542141cc406Sopenharmony_ci (void *) ms, (u_long) sizeof(Microtek2_Scanner)); 543141cc406Sopenharmony_ci if ( ms == NULL ) 544141cc406Sopenharmony_ci { 545141cc406Sopenharmony_ci DBG(1, "sane_open: malloc() for ms failed\n"); 546141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 547141cc406Sopenharmony_ci } 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci memset(ms, 0, sizeof(Microtek2_Scanner)); 550141cc406Sopenharmony_ci ms->dev = md; 551141cc406Sopenharmony_ci ms->scanning = SANE_FALSE; 552141cc406Sopenharmony_ci ms->cancelled = SANE_FALSE; 553141cc406Sopenharmony_ci ms->current_pass = 0; 554141cc406Sopenharmony_ci ms->sfd = -1; 555141cc406Sopenharmony_ci sanei_thread_initialize(ms->pid); 556141cc406Sopenharmony_ci ms->fp = NULL; 557141cc406Sopenharmony_ci ms->gamma_table = NULL; 558141cc406Sopenharmony_ci ms->buf.src_buf = ms->buf.src_buffer[0] = ms->buf.src_buffer[1] = NULL; 559141cc406Sopenharmony_ci ms->control_bytes = NULL; 560141cc406Sopenharmony_ci ms->shading_image = NULL; 561141cc406Sopenharmony_ci ms->condensed_shading_w = NULL; 562141cc406Sopenharmony_ci ms->condensed_shading_d = NULL; 563141cc406Sopenharmony_ci ms->current_color = MS_COLOR_ALL; 564141cc406Sopenharmony_ci ms->current_read_color = MS_COLOR_RED; 565141cc406Sopenharmony_ci 566141cc406Sopenharmony_ci init_options(ms, MD_SOURCE_FLATBED); 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci /* insert scanner into linked list */ 569141cc406Sopenharmony_ci ms->next = ms_first_handle; 570141cc406Sopenharmony_ci ms_first_handle = ms; 571141cc406Sopenharmony_ci 572141cc406Sopenharmony_ci *handle = ms; 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci#ifdef HAVE_AUTHORIZATION 575141cc406Sopenharmony_ci /* check whether the file with the passwords exists. If it doesn't */ 576141cc406Sopenharmony_ci /* exist, we don't use any authorization */ 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_ci rc = stat(PASSWD_FILE, &st); 579141cc406Sopenharmony_ci if ( rc == -1 && errno == ENOENT ) 580141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 581141cc406Sopenharmony_ci else 582141cc406Sopenharmony_ci { 583141cc406Sopenharmony_ci status = do_authorization(md->name); 584141cc406Sopenharmony_ci return status; 585141cc406Sopenharmony_ci } 586141cc406Sopenharmony_ci#else 587141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 588141cc406Sopenharmony_ci#endif 589141cc406Sopenharmony_ci} 590141cc406Sopenharmony_ci 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_ci/*---------- sane_read() -----------------------------------------------------*/ 593141cc406Sopenharmony_ci 594141cc406Sopenharmony_ciSANE_Status 595141cc406Sopenharmony_cisane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len ) 596141cc406Sopenharmony_ci{ 597141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 598141cc406Sopenharmony_ci SANE_Status status; 599141cc406Sopenharmony_ci ssize_t nread; 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci 602141cc406Sopenharmony_ci DBG(30, "sane_read: handle=%p, buf=%p, maxlen=%d\n", 603141cc406Sopenharmony_ci handle, (void *) buf, maxlen); 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci *len = 0; 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci if ( ! ms->scanning || ms->cancelled ) 608141cc406Sopenharmony_ci { 609141cc406Sopenharmony_ci if ( ms->cancelled ) 610141cc406Sopenharmony_ci { 611141cc406Sopenharmony_ci status = SANE_STATUS_CANCELLED; 612141cc406Sopenharmony_ci } 613141cc406Sopenharmony_ci else 614141cc406Sopenharmony_ci { 615141cc406Sopenharmony_ci DBG(15, "sane_read: Scanner %p not scanning\n", (void *) ms); 616141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 617141cc406Sopenharmony_ci } 618141cc406Sopenharmony_ci DBG(15, "sane_read: scan cancelled or scanner not scanning->cleanup\n"); 619141cc406Sopenharmony_ci cleanup_scanner(ms); 620141cc406Sopenharmony_ci return status; 621141cc406Sopenharmony_ci } 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_ci nread = read(ms->fd[0], (void *) buf, (int) maxlen); 625141cc406Sopenharmony_ci if ( nread == -1 ) 626141cc406Sopenharmony_ci { 627141cc406Sopenharmony_ci if ( errno == EAGAIN ) 628141cc406Sopenharmony_ci { 629141cc406Sopenharmony_ci DBG(30, "sane_read: currently no data available\n"); 630141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 631141cc406Sopenharmony_ci } 632141cc406Sopenharmony_ci else 633141cc406Sopenharmony_ci { 634141cc406Sopenharmony_ci DBG(1, "sane_read: read() failed, errno=%d\n", errno); 635141cc406Sopenharmony_ci cleanup_scanner(ms); 636141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 637141cc406Sopenharmony_ci } 638141cc406Sopenharmony_ci } 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci if ( nread == 0 ) 641141cc406Sopenharmony_ci { 642141cc406Sopenharmony_ci DBG(15, "sane_read: read 0 bytes -> EOF\n"); 643141cc406Sopenharmony_ci ms->scanning = SANE_FALSE; 644141cc406Sopenharmony_ci cleanup_scanner(ms); 645141cc406Sopenharmony_ci return SANE_STATUS_EOF; 646141cc406Sopenharmony_ci } 647141cc406Sopenharmony_ci 648141cc406Sopenharmony_ci 649141cc406Sopenharmony_ci *len = (SANE_Int) nread; 650141cc406Sopenharmony_ci DBG(30, "sane_read: *len=%d\n", *len); 651141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 652141cc406Sopenharmony_ci} 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci/*---------- sane_set_io_mode() ---------------------------------------------*/ 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_ciSANE_Status 658141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 659141cc406Sopenharmony_ci{ 660141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 661141cc406Sopenharmony_ci int rc; 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci 664141cc406Sopenharmony_ci DBG(30, "sane_set_io_mode: handle=%p, nonblocking=%d\n", 665141cc406Sopenharmony_ci handle, non_blocking); 666141cc406Sopenharmony_ci 667141cc406Sopenharmony_ci if ( ! ms->scanning ) 668141cc406Sopenharmony_ci { 669141cc406Sopenharmony_ci DBG(1, "sane_set_io_mode: Scanner not scanning\n"); 670141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 671141cc406Sopenharmony_ci } 672141cc406Sopenharmony_ci 673141cc406Sopenharmony_ci rc = fcntl(ms->fd[0], F_SETFL, non_blocking ? O_NONBLOCK : 0); 674141cc406Sopenharmony_ci if ( rc == -1 ) 675141cc406Sopenharmony_ci { 676141cc406Sopenharmony_ci DBG(1, "sane_set_io_mode: fcntl() failed\n"); 677141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 678141cc406Sopenharmony_ci } 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 681141cc406Sopenharmony_ci} 682141cc406Sopenharmony_ci 683141cc406Sopenharmony_ci/*---------- add_device_list() -----------------------------------------------*/ 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_cistatic SANE_Status 686141cc406Sopenharmony_ciadd_device_list(SANE_String_Const dev_name, Microtek2_Device **mdev) 687141cc406Sopenharmony_ci{ 688141cc406Sopenharmony_ci Microtek2_Device *md; 689141cc406Sopenharmony_ci SANE_String hdev; 690141cc406Sopenharmony_ci size_t len; 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci 693141cc406Sopenharmony_ci if ( (hdev = strdup(dev_name)) == NULL) 694141cc406Sopenharmony_ci { 695141cc406Sopenharmony_ci DBG(5, "add_device_list: malloc() for hdev failed\n"); 696141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 697141cc406Sopenharmony_ci } 698141cc406Sopenharmony_ci 699141cc406Sopenharmony_ci len = strlen(hdev); 700141cc406Sopenharmony_ci if ( hdev[len - 1] == '\n' ) 701141cc406Sopenharmony_ci hdev[--len] = '\0'; 702141cc406Sopenharmony_ci 703141cc406Sopenharmony_ci DBG(30, "add_device_list: device='%s'\n", hdev); 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci /* check, if device is already known */ 706141cc406Sopenharmony_ci md = md_first_dev; 707141cc406Sopenharmony_ci while ( md ) 708141cc406Sopenharmony_ci { 709141cc406Sopenharmony_ci if ( strcmp(hdev, md->name) == 0 ) 710141cc406Sopenharmony_ci { 711141cc406Sopenharmony_ci DBG(30, "add_device_list: device '%s' already in list\n", hdev); 712141cc406Sopenharmony_ci 713141cc406Sopenharmony_ci *mdev = md; 714141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 715141cc406Sopenharmony_ci } 716141cc406Sopenharmony_ci md = md->next; 717141cc406Sopenharmony_ci } 718141cc406Sopenharmony_ci 719141cc406Sopenharmony_ci md = (Microtek2_Device *) malloc(sizeof(Microtek2_Device)); 720141cc406Sopenharmony_ci DBG(100, "add_device_list: md=%p, malloc'd %lu bytes\n", 721141cc406Sopenharmony_ci (void *) md, (u_long) sizeof(Microtek2_Device)); 722141cc406Sopenharmony_ci if ( md == NULL ) 723141cc406Sopenharmony_ci { 724141cc406Sopenharmony_ci DBG(1, "add_device_list: malloc() for md failed\n"); 725141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 726141cc406Sopenharmony_ci } 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci /* initialize Device and add it at the beginning of the list */ 729141cc406Sopenharmony_ci memset(md, 0, sizeof(Microtek2_Device)); 730141cc406Sopenharmony_ci md->next = md_first_dev; 731141cc406Sopenharmony_ci md_first_dev = md; 732141cc406Sopenharmony_ci md->sane.name = NULL; 733141cc406Sopenharmony_ci md->sane.vendor = NULL; 734141cc406Sopenharmony_ci md->sane.model = NULL; 735141cc406Sopenharmony_ci md->sane.type = NULL; 736141cc406Sopenharmony_ci md->scan_source = MD_SOURCE_FLATBED; 737141cc406Sopenharmony_ci md->shading_table_w = NULL; 738141cc406Sopenharmony_ci md->shading_table_d = NULL; 739141cc406Sopenharmony_ci strncpy(md->name, hdev, PATH_MAX - 1); 740141cc406Sopenharmony_ci if ( md_config_temp ) 741141cc406Sopenharmony_ci md->opts = md_config_temp->opts; 742141cc406Sopenharmony_ci else 743141cc406Sopenharmony_ci md->opts = md_options; 744141cc406Sopenharmony_ci ++md_num_devices; 745141cc406Sopenharmony_ci *mdev = md; 746141cc406Sopenharmony_ci DBG(100, "free hdev at %p\n", (void *) hdev); 747141cc406Sopenharmony_ci free(hdev); 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 750141cc406Sopenharmony_ci} 751141cc406Sopenharmony_ci 752141cc406Sopenharmony_ci/*---------- attach() --------------------------------------------------------*/ 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_cistatic SANE_Status 755141cc406Sopenharmony_ciattach(Microtek2_Device *md) 756141cc406Sopenharmony_ci{ 757141cc406Sopenharmony_ci /* This function is called from sane_init() to do the inquiry and to read */ 758141cc406Sopenharmony_ci /* the scanner attributes. If one of these calls fails, or if a new */ 759141cc406Sopenharmony_ci /* device is passed in sane_open() this function may also be called */ 760141cc406Sopenharmony_ci /* from sane_open() or sane_get_devices(). */ 761141cc406Sopenharmony_ci 762141cc406Sopenharmony_ci SANE_String model_string; 763141cc406Sopenharmony_ci SANE_Status status; 764141cc406Sopenharmony_ci SANE_Byte source_info; 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci DBG(30, "attach: device='%s'\n", md->name); 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci status = scsi_inquiry( &md->info[MD_SOURCE_FLATBED], md->name ); 770141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 771141cc406Sopenharmony_ci { 772141cc406Sopenharmony_ci DBG(1, "attach: '%s'\n", sane_strstatus(status)); 773141cc406Sopenharmony_ci return status; 774141cc406Sopenharmony_ci } 775141cc406Sopenharmony_ci 776141cc406Sopenharmony_ci /* We copy the inquiry info into the info structures for each scansource */ 777141cc406Sopenharmony_ci /* like ADF, TMA, STRIPE and SLIDE */ 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci for ( source_info = 1; source_info < 5; ++source_info ) 780141cc406Sopenharmony_ci memcpy( &md->info[source_info], 781141cc406Sopenharmony_ci &md->info[MD_SOURCE_FLATBED], 782141cc406Sopenharmony_ci sizeof( Microtek2_Info ) ); 783141cc406Sopenharmony_ci 784141cc406Sopenharmony_ci /* Here we should insert a function, that stores all the relevant */ 785141cc406Sopenharmony_ci /* information in the info structure in a more conveniant format */ 786141cc406Sopenharmony_ci /* in the device structure, e.g. the model name with a trailing '\0'. */ 787141cc406Sopenharmony_ci 788141cc406Sopenharmony_ci status = check_inquiry(md, &model_string); 789141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 790141cc406Sopenharmony_ci return status; 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci md->sane.name = md->name; 793141cc406Sopenharmony_ci md->sane.vendor = "Microtek"; 794141cc406Sopenharmony_ci md->sane.model = strdup(model_string); 795141cc406Sopenharmony_ci if ( md->sane.model == NULL ) 796141cc406Sopenharmony_ci DBG(1, "attach: strdup for model string failed\n"); 797141cc406Sopenharmony_ci md->sane.type = "flatbed scanner"; 798141cc406Sopenharmony_ci md->revision = strtod(md->info[MD_SOURCE_FLATBED].revision, NULL); 799141cc406Sopenharmony_ci 800141cc406Sopenharmony_ci status = scsi_read_attributes(&md->info[0], 801141cc406Sopenharmony_ci md->name, MD_SOURCE_FLATBED); 802141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 803141cc406Sopenharmony_ci { 804141cc406Sopenharmony_ci DBG(1, "attach: '%s'\n", sane_strstatus(status)); 805141cc406Sopenharmony_ci return status; 806141cc406Sopenharmony_ci } 807141cc406Sopenharmony_ci 808141cc406Sopenharmony_ci if ( MI_LUTCAP_NONE( md->info[MD_SOURCE_FLATBED].lut_cap) ) 809141cc406Sopenharmony_ci /* no gamma tables */ 810141cc406Sopenharmony_ci md->model_flags |= MD_NO_GAMMA; 811141cc406Sopenharmony_ci 812141cc406Sopenharmony_ci /* check whether the device supports transparency media adapters */ 813141cc406Sopenharmony_ci if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_TMA ) 814141cc406Sopenharmony_ci { 815141cc406Sopenharmony_ci status = scsi_read_attributes(&md->info[0], 816141cc406Sopenharmony_ci md->name, MD_SOURCE_TMA); 817141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 818141cc406Sopenharmony_ci return status; 819141cc406Sopenharmony_ci } 820141cc406Sopenharmony_ci 821141cc406Sopenharmony_ci /* check whether the device supports an ADF */ 822141cc406Sopenharmony_ci if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_ADF ) 823141cc406Sopenharmony_ci { 824141cc406Sopenharmony_ci status = scsi_read_attributes(&md->info[0], 825141cc406Sopenharmony_ci md->name, MD_SOURCE_ADF); 826141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 827141cc406Sopenharmony_ci return status; 828141cc406Sopenharmony_ci } 829141cc406Sopenharmony_ci 830141cc406Sopenharmony_ci /* check whether the device supports STRIPES */ 831141cc406Sopenharmony_ci if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_STRIPE ) 832141cc406Sopenharmony_ci { 833141cc406Sopenharmony_ci status = scsi_read_attributes(&md->info[0], 834141cc406Sopenharmony_ci md->name, MD_SOURCE_STRIPE); 835141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 836141cc406Sopenharmony_ci return status; 837141cc406Sopenharmony_ci } 838141cc406Sopenharmony_ci 839141cc406Sopenharmony_ci /* check whether the device supports SLIDES */ 840141cc406Sopenharmony_ci if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_SLIDE ) 841141cc406Sopenharmony_ci { 842141cc406Sopenharmony_ci /* The Phantom 636cx indicates in its attributes that it supports */ 843141cc406Sopenharmony_ci /* slides, but it doesn't. Thus this command would fail. */ 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci if ( ! (md->model_flags & MD_NO_SLIDE_MODE) ) 846141cc406Sopenharmony_ci { 847141cc406Sopenharmony_ci status = scsi_read_attributes(&md->info[0], 848141cc406Sopenharmony_ci md->name, MD_SOURCE_SLIDE); 849141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 850141cc406Sopenharmony_ci return status; 851141cc406Sopenharmony_ci } 852141cc406Sopenharmony_ci } 853141cc406Sopenharmony_ci 854141cc406Sopenharmony_ci status = scsi_read_system_status(md, -1); 855141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 856141cc406Sopenharmony_ci return status; 857141cc406Sopenharmony_ci 858141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 859141cc406Sopenharmony_ci} 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci 862141cc406Sopenharmony_ci/*---------- attach_one() ----------------------------------------------------*/ 863141cc406Sopenharmony_ci 864141cc406Sopenharmony_cistatic SANE_Status 865141cc406Sopenharmony_ciattach_one (const char *name) 866141cc406Sopenharmony_ci{ 867141cc406Sopenharmony_ci Microtek2_Device *md; 868141cc406Sopenharmony_ci Microtek2_Device *md_tmp; 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_ci DBG(30, "attach_one: name='%s'\n", name); 872141cc406Sopenharmony_ci 873141cc406Sopenharmony_ci md_tmp = md_first_dev; 874141cc406Sopenharmony_ci /* if add_device_list() adds an entry it does this at the beginning */ 875141cc406Sopenharmony_ci /* of the list and thus changes md_first_dev */ 876141cc406Sopenharmony_ci add_device_list(name, &md); 877141cc406Sopenharmony_ci if ( md_tmp != md_first_dev ) 878141cc406Sopenharmony_ci attach(md); 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 881141cc406Sopenharmony_ci} 882141cc406Sopenharmony_ci 883141cc406Sopenharmony_ci/*---------- cancel_scan() ---------------------------------------------------*/ 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_cistatic SANE_Status 886141cc406Sopenharmony_cicancel_scan(Microtek2_Scanner *ms) 887141cc406Sopenharmony_ci{ 888141cc406Sopenharmony_ci SANE_Status status; 889141cc406Sopenharmony_ci 890141cc406Sopenharmony_ci 891141cc406Sopenharmony_ci DBG(30, "cancel_scan: ms=%p\n", (void *) ms); 892141cc406Sopenharmony_ci 893141cc406Sopenharmony_ci /* READ IMAGE with a transferlength of 0 aborts a scan */ 894141cc406Sopenharmony_ci ms->transfer_length = 0; 895141cc406Sopenharmony_ci status = scsi_read_image(ms, (uint8_t *) NULL, 1); 896141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 897141cc406Sopenharmony_ci { 898141cc406Sopenharmony_ci DBG(1, "cancel_scan: cancel failed: '%s'\n", sane_strstatus(status)); 899141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 900141cc406Sopenharmony_ci } 901141cc406Sopenharmony_ci else 902141cc406Sopenharmony_ci status = SANE_STATUS_CANCELLED; 903141cc406Sopenharmony_ci 904141cc406Sopenharmony_ci close(ms->fd[1]); 905141cc406Sopenharmony_ci 906141cc406Sopenharmony_ci /* if we are aborting a scan because, for example, we run out 907141cc406Sopenharmony_ci of material on a feeder, then pid may be already -1 and 908141cc406Sopenharmony_ci kill(-1, SIGTERM), i.e. killing all our processes, is not 909141cc406Sopenharmony_ci likely what we really want - --mj, 2001/Nov/19 */ 910141cc406Sopenharmony_ci if (sanei_thread_is_valid (ms->pid)) 911141cc406Sopenharmony_ci { 912141cc406Sopenharmony_ci sanei_thread_kill(ms->pid); 913141cc406Sopenharmony_ci sanei_thread_waitpid(ms->pid, NULL); 914141cc406Sopenharmony_ci } 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci return status; 917141cc406Sopenharmony_ci} 918141cc406Sopenharmony_ci 919141cc406Sopenharmony_ci 920141cc406Sopenharmony_ci/*---------- check_option() --------------------------------------------------*/ 921141cc406Sopenharmony_ci 922141cc406Sopenharmony_cistatic void 923141cc406Sopenharmony_cicheck_option(const char *cp, Config_Options *co) 924141cc406Sopenharmony_ci{ 925141cc406Sopenharmony_ci /* This function analyses options in the config file */ 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci char *endptr; 928141cc406Sopenharmony_ci 929141cc406Sopenharmony_ci /* When this function is called, it is already made sure that this */ 930141cc406Sopenharmony_ci /* is an option line, i.e. a line that starts with option */ 931141cc406Sopenharmony_ci 932141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp); /* skip blanks */ 933141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 6); /* skip "option" */ 934141cc406Sopenharmony_ci if ( strncmp(cp, "dump", 4) == 0 && isspace(cp[4]) ) 935141cc406Sopenharmony_ci { 936141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 4); 937141cc406Sopenharmony_ci if ( *cp ) 938141cc406Sopenharmony_ci { 939141cc406Sopenharmony_ci md_dump = (int) strtol(cp, &endptr, 10); 940141cc406Sopenharmony_ci if ( md_dump > 4 || md_dump < 0 ) 941141cc406Sopenharmony_ci { 942141cc406Sopenharmony_ci md_dump = 1; 943141cc406Sopenharmony_ci DBG(30, "check_option: setting dump to %d\n", md_dump); 944141cc406Sopenharmony_ci } 945141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(endptr); 946141cc406Sopenharmony_ci if ( *cp ) 947141cc406Sopenharmony_ci { 948141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 949141cc406Sopenharmony_ci md_dump = 1; 950141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong\n"); 951141cc406Sopenharmony_ci } 952141cc406Sopenharmony_ci } 953141cc406Sopenharmony_ci else 954141cc406Sopenharmony_ci { 955141cc406Sopenharmony_ci DBG(30, "check_option: missing option value\n"); 956141cc406Sopenharmony_ci /* reasonable fallback */ 957141cc406Sopenharmony_ci md_dump = 1; 958141cc406Sopenharmony_ci } 959141cc406Sopenharmony_ci } 960141cc406Sopenharmony_ci else if ( strncmp(cp, "strip-height", 12) == 0 && isspace(cp[12]) ) 961141cc406Sopenharmony_ci { 962141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 12); 963141cc406Sopenharmony_ci if ( *cp ) 964141cc406Sopenharmony_ci { 965141cc406Sopenharmony_ci co->strip_height = strtod(cp, &endptr); 966141cc406Sopenharmony_ci DBG(30, "check_option: setting strip_height to %f\n", 967141cc406Sopenharmony_ci co->strip_height); 968141cc406Sopenharmony_ci if ( co->strip_height <= 0.0 ) 969141cc406Sopenharmony_ci co->strip_height = 14.0; 970141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(endptr); 971141cc406Sopenharmony_ci if ( *cp ) 972141cc406Sopenharmony_ci { 973141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 974141cc406Sopenharmony_ci co->strip_height = 14.0; 975141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong: %f\n", 976141cc406Sopenharmony_ci co->strip_height); 977141cc406Sopenharmony_ci } 978141cc406Sopenharmony_ci } 979141cc406Sopenharmony_ci } 980141cc406Sopenharmony_ci else if ( strncmp(cp, "no-backtrack-option", 19) == 0 981141cc406Sopenharmony_ci && isspace(cp[19]) ) 982141cc406Sopenharmony_ci { 983141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 19); 984141cc406Sopenharmony_ci if ( strncmp(cp, "on", 2) == 0 ) 985141cc406Sopenharmony_ci { 986141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 2); 987141cc406Sopenharmony_ci co->no_backtracking = "on"; 988141cc406Sopenharmony_ci } 989141cc406Sopenharmony_ci else if ( strncmp(cp, "off", 3) == 0 ) 990141cc406Sopenharmony_ci { 991141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 3); 992141cc406Sopenharmony_ci co->no_backtracking = "off"; 993141cc406Sopenharmony_ci } 994141cc406Sopenharmony_ci else 995141cc406Sopenharmony_ci co->no_backtracking = "off"; 996141cc406Sopenharmony_ci 997141cc406Sopenharmony_ci if ( *cp ) 998141cc406Sopenharmony_ci { 999141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 1000141cc406Sopenharmony_ci co->no_backtracking = "off"; 1001141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong: %s\n", cp); 1002141cc406Sopenharmony_ci } 1003141cc406Sopenharmony_ci } 1004141cc406Sopenharmony_ci else if ( strncmp(cp, "lightlid-35", 11) == 0 1005141cc406Sopenharmony_ci && isspace(cp[11]) ) 1006141cc406Sopenharmony_ci { 1007141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 11); 1008141cc406Sopenharmony_ci if ( strncmp(cp, "on", 2) == 0 ) 1009141cc406Sopenharmony_ci { 1010141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 2); 1011141cc406Sopenharmony_ci co->lightlid35 = "on"; 1012141cc406Sopenharmony_ci } 1013141cc406Sopenharmony_ci else if ( strncmp(cp, "off", 3) == 0 ) 1014141cc406Sopenharmony_ci { 1015141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 3); 1016141cc406Sopenharmony_ci co->lightlid35 = "off"; 1017141cc406Sopenharmony_ci } 1018141cc406Sopenharmony_ci else 1019141cc406Sopenharmony_ci co->lightlid35 = "off"; 1020141cc406Sopenharmony_ci 1021141cc406Sopenharmony_ci if ( *cp ) 1022141cc406Sopenharmony_ci { 1023141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 1024141cc406Sopenharmony_ci co->lightlid35 = "off"; 1025141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong: %s\n", cp); 1026141cc406Sopenharmony_ci } 1027141cc406Sopenharmony_ci } 1028141cc406Sopenharmony_ci else if ( strncmp(cp, "toggle-lamp", 11) == 0 1029141cc406Sopenharmony_ci && isspace(cp[11]) ) 1030141cc406Sopenharmony_ci { 1031141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 11); 1032141cc406Sopenharmony_ci if ( strncmp(cp, "on", 2) == 0 ) 1033141cc406Sopenharmony_ci { 1034141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 2); 1035141cc406Sopenharmony_ci co->toggle_lamp = "on"; 1036141cc406Sopenharmony_ci } 1037141cc406Sopenharmony_ci else if ( strncmp(cp, "off", 3) == 0 ) 1038141cc406Sopenharmony_ci { 1039141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 3); 1040141cc406Sopenharmony_ci co->toggle_lamp = "off"; 1041141cc406Sopenharmony_ci } 1042141cc406Sopenharmony_ci else 1043141cc406Sopenharmony_ci co->toggle_lamp = "off"; 1044141cc406Sopenharmony_ci 1045141cc406Sopenharmony_ci if ( *cp ) 1046141cc406Sopenharmony_ci { 1047141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 1048141cc406Sopenharmony_ci co->toggle_lamp = "off"; 1049141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong: %s\n", cp); 1050141cc406Sopenharmony_ci } 1051141cc406Sopenharmony_ci } 1052141cc406Sopenharmony_ci else if ( strncmp(cp, "lineart-autoadjust", 18) == 0 1053141cc406Sopenharmony_ci && isspace(cp[18]) ) 1054141cc406Sopenharmony_ci { 1055141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 18); 1056141cc406Sopenharmony_ci if ( strncmp(cp, "on", 2) == 0 ) 1057141cc406Sopenharmony_ci { 1058141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 2); 1059141cc406Sopenharmony_ci co->auto_adjust = "on"; 1060141cc406Sopenharmony_ci } 1061141cc406Sopenharmony_ci else if ( strncmp(cp, "off", 3) == 0 ) 1062141cc406Sopenharmony_ci { 1063141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 3); 1064141cc406Sopenharmony_ci co->auto_adjust = "off"; 1065141cc406Sopenharmony_ci } 1066141cc406Sopenharmony_ci else 1067141cc406Sopenharmony_ci co->auto_adjust = "off"; 1068141cc406Sopenharmony_ci 1069141cc406Sopenharmony_ci if ( *cp ) 1070141cc406Sopenharmony_ci { 1071141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 1072141cc406Sopenharmony_ci co->auto_adjust = "off"; 1073141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong: %s\n", cp); 1074141cc406Sopenharmony_ci } 1075141cc406Sopenharmony_ci } 1076141cc406Sopenharmony_ci else if ( strncmp(cp, "backend-calibration", 19) == 0 1077141cc406Sopenharmony_ci && isspace(cp[19]) ) 1078141cc406Sopenharmony_ci { 1079141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 19); 1080141cc406Sopenharmony_ci if ( strncmp(cp, "on", 2) == 0 ) 1081141cc406Sopenharmony_ci { 1082141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 2); 1083141cc406Sopenharmony_ci co->backend_calibration = "on"; 1084141cc406Sopenharmony_ci } 1085141cc406Sopenharmony_ci else if ( strncmp(cp, "off", 3) == 0 ) 1086141cc406Sopenharmony_ci { 1087141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 3); 1088141cc406Sopenharmony_ci co->backend_calibration = "off"; 1089141cc406Sopenharmony_ci } 1090141cc406Sopenharmony_ci else 1091141cc406Sopenharmony_ci co->backend_calibration = "off"; 1092141cc406Sopenharmony_ci 1093141cc406Sopenharmony_ci if ( *cp ) 1094141cc406Sopenharmony_ci { 1095141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 1096141cc406Sopenharmony_ci co->backend_calibration = "off"; 1097141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong: %s\n", cp); 1098141cc406Sopenharmony_ci } 1099141cc406Sopenharmony_ci } 1100141cc406Sopenharmony_ci else if ( strncmp(cp, "colorbalance-adjust", 19) == 0 1101141cc406Sopenharmony_ci && isspace(cp[19]) ) 1102141cc406Sopenharmony_ci { 1103141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 19); 1104141cc406Sopenharmony_ci if ( strncmp(cp, "on", 2) == 0 ) 1105141cc406Sopenharmony_ci { 1106141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 2); 1107141cc406Sopenharmony_ci co->colorbalance_adjust = "on"; 1108141cc406Sopenharmony_ci } 1109141cc406Sopenharmony_ci else if ( strncmp(cp, "off", 3) == 0 ) 1110141cc406Sopenharmony_ci { 1111141cc406Sopenharmony_ci cp = sanei_config_skip_whitespace(cp + 3); 1112141cc406Sopenharmony_ci co->colorbalance_adjust = "off"; 1113141cc406Sopenharmony_ci } 1114141cc406Sopenharmony_ci else 1115141cc406Sopenharmony_ci co->colorbalance_adjust = "off"; 1116141cc406Sopenharmony_ci 1117141cc406Sopenharmony_ci if ( *cp ) 1118141cc406Sopenharmony_ci { 1119141cc406Sopenharmony_ci /* something behind the option value or value wrong */ 1120141cc406Sopenharmony_ci co->colorbalance_adjust = "off"; 1121141cc406Sopenharmony_ci DBG(30, "check_option: option value wrong: %s\n", cp); 1122141cc406Sopenharmony_ci } 1123141cc406Sopenharmony_ci } 1124141cc406Sopenharmony_ci else 1125141cc406Sopenharmony_ci DBG(30, "check_option: invalid option in '%s'\n", cp); 1126141cc406Sopenharmony_ci} 1127141cc406Sopenharmony_ci 1128141cc406Sopenharmony_ci 1129141cc406Sopenharmony_ci/*---------- check_inquiry() -------------------------------------------------*/ 1130141cc406Sopenharmony_ci 1131141cc406Sopenharmony_cistatic SANE_Status 1132141cc406Sopenharmony_cicheck_inquiry(Microtek2_Device *md, SANE_String *model_string) 1133141cc406Sopenharmony_ci{ 1134141cc406Sopenharmony_ci Microtek2_Info *mi; 1135141cc406Sopenharmony_ci 1136141cc406Sopenharmony_ci DBG(30, "check_inquiry: md=%p\n", (void *) md); 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci md->n_control_bytes = 0; 1139141cc406Sopenharmony_ci md->shading_length = 0; 1140141cc406Sopenharmony_ci md->shading_table_contents = 0; 1141141cc406Sopenharmony_ci 1142141cc406Sopenharmony_ci mi = &md->info[MD_SOURCE_FLATBED]; 1143141cc406Sopenharmony_ci if ( mi->scsi_version != MI_SCSI_II_VERSION ) 1144141cc406Sopenharmony_ci { 1145141cc406Sopenharmony_ci DBG(1, "check_inquiry: Device is not a SCSI-II device, but 0x%02x\n", 1146141cc406Sopenharmony_ci mi->scsi_version); 1147141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1148141cc406Sopenharmony_ci } 1149141cc406Sopenharmony_ci 1150141cc406Sopenharmony_ci if ( mi->device_type != MI_DEVTYPE_SCANNER ) 1151141cc406Sopenharmony_ci { 1152141cc406Sopenharmony_ci DBG(1, "check_inquiry: Device is not a scanner, but 0x%02x\n", 1153141cc406Sopenharmony_ci mi->device_type); 1154141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1155141cc406Sopenharmony_ci } 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci if ( strncasecmp("MICROTEK", mi->vendor, INQ_VENDOR_L) != 0 1158141cc406Sopenharmony_ci && strncmp(" ", mi->vendor, INQ_VENDOR_L) != 0 1159141cc406Sopenharmony_ci && strncmp("AGFA ", mi->vendor, INQ_VENDOR_L) != 0 ) 1160141cc406Sopenharmony_ci { 1161141cc406Sopenharmony_ci DBG(1, "check_inquiry: Device is not a Microtek, but '%.*s'\n", 1162141cc406Sopenharmony_ci INQ_VENDOR_L, mi->vendor); 1163141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1164141cc406Sopenharmony_ci } 1165141cc406Sopenharmony_ci 1166141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 1167141cc406Sopenharmony_ci md->shading_depth = 16; 1168141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_14 ) 1169141cc406Sopenharmony_ci md->shading_depth = 14; 1170141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_12 ) 1171141cc406Sopenharmony_ci md->shading_depth = 12; 1172141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_10 ) 1173141cc406Sopenharmony_ci md->shading_depth = 10; 1174141cc406Sopenharmony_ci else 1175141cc406Sopenharmony_ci md->shading_depth = 8; 1176141cc406Sopenharmony_ci 1177141cc406Sopenharmony_ci switch (mi->model_code) 1178141cc406Sopenharmony_ci { 1179141cc406Sopenharmony_ci case 0x81: 1180141cc406Sopenharmony_ci case 0xab: 1181141cc406Sopenharmony_ci *model_string = "ScanMaker 4"; 1182141cc406Sopenharmony_ci break; 1183141cc406Sopenharmony_ci case 0x85: 1184141cc406Sopenharmony_ci *model_string = "ScanMaker V300 / ColorPage-EP"; 1185141cc406Sopenharmony_ci /* The ScanMaker V300 (FW < 2.70) returns some values for the */ 1186141cc406Sopenharmony_ci /* "read image info" command in only two bytes */ 1187141cc406Sopenharmony_ci /* and doesn't understand read_image_status */ 1188141cc406Sopenharmony_ci md->model_flags |= MD_NO_RIS_COMMAND; 1189141cc406Sopenharmony_ci if ( md->revision < 2.70 ) 1190141cc406Sopenharmony_ci md->model_flags |= MD_RII_TWO_BYTES; 1191141cc406Sopenharmony_ci break; 1192141cc406Sopenharmony_ci case 0x87: 1193141cc406Sopenharmony_ci *model_string = "ScanMaker 5"; 1194141cc406Sopenharmony_ci md->model_flags |= MD_NO_GAMMA; 1195141cc406Sopenharmony_ci break; 1196141cc406Sopenharmony_ci case 0x89: 1197141cc406Sopenharmony_ci *model_string = "ScanMaker 6400XL"; 1198141cc406Sopenharmony_ci break; 1199141cc406Sopenharmony_ci case 0x8a: 1200141cc406Sopenharmony_ci *model_string = "ScanMaker 9600XL"; 1201141cc406Sopenharmony_ci break; 1202141cc406Sopenharmony_ci case 0x8c: 1203141cc406Sopenharmony_ci *model_string = "ScanMaker 630 / ScanMaker V600"; 1204141cc406Sopenharmony_ci break; 1205141cc406Sopenharmony_ci case 0x8d: 1206141cc406Sopenharmony_ci *model_string = "ScanMaker 336 / ScanMaker V310"; 1207141cc406Sopenharmony_ci break; 1208141cc406Sopenharmony_ci case 0x90: 1209141cc406Sopenharmony_ci case 0x92: 1210141cc406Sopenharmony_ci *model_string = "E3+ / Vobis HighScan"; 1211141cc406Sopenharmony_ci break; 1212141cc406Sopenharmony_ci case 0x91: 1213141cc406Sopenharmony_ci *model_string = "ScanMaker X6 / Phantom 636"; 1214141cc406Sopenharmony_ci /* The X6 indicates a data format of segregated data in TMA mode */ 1215141cc406Sopenharmony_ci /* but actually transfers as chunky data */ 1216141cc406Sopenharmony_ci md->model_flags |= MD_DATA_FORMAT_WRONG; 1217141cc406Sopenharmony_ci if ( md->revision == 1.00 ) 1218141cc406Sopenharmony_ci md->model_flags |= MD_OFFSET_2; 1219141cc406Sopenharmony_ci break; 1220141cc406Sopenharmony_ci case 0x93: 1221141cc406Sopenharmony_ci *model_string = "ScanMaker 336 / ScanMaker V310"; 1222141cc406Sopenharmony_ci break; 1223141cc406Sopenharmony_ci case 0x70: 1224141cc406Sopenharmony_ci case 0x71: 1225141cc406Sopenharmony_ci case 0x94: 1226141cc406Sopenharmony_ci case 0xa0: 1227141cc406Sopenharmony_ci *model_string = "Phantom 330cx / Phantom 336cx / SlimScan C3"; 1228141cc406Sopenharmony_ci /* These models do not accept gamma tables. Apparently they */ 1229141cc406Sopenharmony_ci /* read the control bits and do not accept shading tables */ 1230141cc406Sopenharmony_ci /* They also don't support enhancements (contrast, brightness...)*/ 1231141cc406Sopenharmony_ci md->model_flags |= MD_NO_SLIDE_MODE 1232141cc406Sopenharmony_ci | MD_NO_GAMMA 1233141cc406Sopenharmony_ci#ifndef NO_PHANTOMTYPE_SHADING 1234141cc406Sopenharmony_ci | MD_PHANTOM336CX_TYPE_SHADING 1235141cc406Sopenharmony_ci#endif 1236141cc406Sopenharmony_ci | MD_READ_CONTROL_BIT 1237141cc406Sopenharmony_ci | MD_NO_ENHANCEMENTS; 1238141cc406Sopenharmony_ci md->opt_backend_calib_default = SANE_TRUE; 1239141cc406Sopenharmony_ci md->opt_no_backtrack_default = SANE_TRUE; 1240141cc406Sopenharmony_ci md->n_control_bytes = 320; 1241141cc406Sopenharmony_ci md->shading_length = 18; 1242141cc406Sopenharmony_ci md->shading_depth = 10; 1243141cc406Sopenharmony_ci md->controlbit_offset = 7; 1244141cc406Sopenharmony_ci break; 1245141cc406Sopenharmony_ci case 0x95: 1246141cc406Sopenharmony_ci *model_string = "ArtixScan 1010"; 1247141cc406Sopenharmony_ci break; 1248141cc406Sopenharmony_ci case 0x97: 1249141cc406Sopenharmony_ci *model_string = "ScanMaker 636"; 1250141cc406Sopenharmony_ci break; 1251141cc406Sopenharmony_ci case 0x98: 1252141cc406Sopenharmony_ci *model_string = "ScanMaker X6EL"; 1253141cc406Sopenharmony_ci if ( md->revision == 1.00 ) 1254141cc406Sopenharmony_ci md->model_flags |= MD_OFFSET_2; 1255141cc406Sopenharmony_ci break; 1256141cc406Sopenharmony_ci case 0x99: 1257141cc406Sopenharmony_ci *model_string = "ScanMaker X6USB"; 1258141cc406Sopenharmony_ci if ( md->revision == 1.00 ) 1259141cc406Sopenharmony_ci md->model_flags |= MD_OFFSET_2; 1260141cc406Sopenharmony_ci md->model_flags |= MD_X6_SHORT_TRANSFER; 1261141cc406Sopenharmony_ci break; 1262141cc406Sopenharmony_ci case 0x9a: 1263141cc406Sopenharmony_ci *model_string = "Phantom 636cx / C6"; 1264141cc406Sopenharmony_ci /* The Phantom 636cx says it supports the SLIDE mode, but it */ 1265141cc406Sopenharmony_ci /* doesn't. Thus inquring the attributes for slide mode would */ 1266141cc406Sopenharmony_ci /* fail. Also it does not accept gamma tables. Apparently */ 1267141cc406Sopenharmony_ci /* it reads the control bits and does not accept shading tables */ 1268141cc406Sopenharmony_ci md->model_flags |= MD_NO_SLIDE_MODE 1269141cc406Sopenharmony_ci | MD_READ_CONTROL_BIT 1270141cc406Sopenharmony_ci | MD_NO_GAMMA 1271141cc406Sopenharmony_ci | MD_PHANTOM_C6; 1272141cc406Sopenharmony_ci md->opt_backend_calib_default = SANE_TRUE; 1273141cc406Sopenharmony_ci md->opt_no_backtrack_default = SANE_TRUE; 1274141cc406Sopenharmony_ci md->n_control_bytes = 647; 1275141cc406Sopenharmony_ci /* md->shading_length = 18; firmware values seem to work better */ 1276141cc406Sopenharmony_ci md->shading_depth = 12; 1277141cc406Sopenharmony_ci md->controlbit_offset = 18; 1278141cc406Sopenharmony_ci break; 1279141cc406Sopenharmony_ci case 0x9d: 1280141cc406Sopenharmony_ci *model_string = "AGFA Duoscan T1200"; 1281141cc406Sopenharmony_ci break; 1282141cc406Sopenharmony_ci case 0xa3: 1283141cc406Sopenharmony_ci *model_string = "ScanMaker V6USL"; 1284141cc406Sopenharmony_ci /* The V6USL does not accept gamma tables */ 1285141cc406Sopenharmony_ci md->model_flags |= MD_NO_GAMMA; 1286141cc406Sopenharmony_ci break; 1287141cc406Sopenharmony_ci case 0xa5: 1288141cc406Sopenharmony_ci *model_string = "ArtixScan 4000t"; 1289141cc406Sopenharmony_ci break; 1290141cc406Sopenharmony_ci case 0xac: 1291141cc406Sopenharmony_ci *model_string = "ScanMaker V6UL"; 1292141cc406Sopenharmony_ci /* The V6USL does not accept gamma tables, perhaps the V6UL also */ 1293141cc406Sopenharmony_ci md->model_flags |= MD_NO_GAMMA; 1294141cc406Sopenharmony_ci break; 1295141cc406Sopenharmony_ci case 0xaf: 1296141cc406Sopenharmony_ci *model_string = "SlimScan C3"; 1297141cc406Sopenharmony_ci md->model_flags |= MD_NO_SLIDE_MODE 1298141cc406Sopenharmony_ci | MD_NO_GAMMA 1299141cc406Sopenharmony_ci | MD_READ_CONTROL_BIT 1300141cc406Sopenharmony_ci | MD_NO_ENHANCEMENTS; 1301141cc406Sopenharmony_ci md->opt_backend_calib_default = SANE_TRUE; 1302141cc406Sopenharmony_ci md->opt_no_backtrack_default = SANE_TRUE; 1303141cc406Sopenharmony_ci md->n_control_bytes = 320; 1304141cc406Sopenharmony_ci md->controlbit_offset = 7; 1305141cc406Sopenharmony_ci break; 1306141cc406Sopenharmony_ci case 0xb0: 1307141cc406Sopenharmony_ci *model_string = "ScanMaker X12USL"; 1308141cc406Sopenharmony_ci md->opt_backend_calib_default = SANE_TRUE; 1309141cc406Sopenharmony_ci md->model_flags |= MD_16BIT_TRANSFER 1310141cc406Sopenharmony_ci | MD_CALIB_DIVISOR_600; 1311141cc406Sopenharmony_ci break; 1312141cc406Sopenharmony_ci case 0xb3: 1313141cc406Sopenharmony_ci *model_string = "ScanMaker 3600"; 1314141cc406Sopenharmony_ci break; 1315141cc406Sopenharmony_ci case 0xb4: 1316141cc406Sopenharmony_ci *model_string = "ScanMaker 4700"; 1317141cc406Sopenharmony_ci break; 1318141cc406Sopenharmony_ci case 0xb6: 1319141cc406Sopenharmony_ci *model_string = "ScanMaker V6UPL"; 1320141cc406Sopenharmony_ci /* is like V6USL but with USB and Parport interface ?? */ 1321141cc406Sopenharmony_ci md->model_flags |= MD_NO_GAMMA; 1322141cc406Sopenharmony_ci break; 1323141cc406Sopenharmony_ci case 0xb8: 1324141cc406Sopenharmony_ci *model_string = "ScanMaker 3700"; 1325141cc406Sopenharmony_ci break; 1326141cc406Sopenharmony_ci case 0xde: 1327141cc406Sopenharmony_ci *model_string = "ScanMaker 9800XL"; 1328141cc406Sopenharmony_ci md->model_flags |= MD_NO_GAMMA 1329141cc406Sopenharmony_ci | MD_16BIT_TRANSFER; 1330141cc406Sopenharmony_ci md->opt_backend_calib_default = SANE_TRUE; 1331141cc406Sopenharmony_ci md->opt_no_backtrack_default = SANE_TRUE; 1332141cc406Sopenharmony_ci break; 1333141cc406Sopenharmony_ci default: 1334141cc406Sopenharmony_ci DBG(1, "check_inquiry: Model 0x%02x not supported\n", mi->model_code); 1335141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1336141cc406Sopenharmony_ci } 1337141cc406Sopenharmony_ci 1338141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1339141cc406Sopenharmony_ci} 1340141cc406Sopenharmony_ci 1341141cc406Sopenharmony_ci 1342141cc406Sopenharmony_ci/*---------- cleanup_scanner() -----------------------------------------------*/ 1343141cc406Sopenharmony_ci 1344141cc406Sopenharmony_cistatic void 1345141cc406Sopenharmony_cicleanup_scanner(Microtek2_Scanner *ms) 1346141cc406Sopenharmony_ci{ 1347141cc406Sopenharmony_ci DBG(30, "cleanup_scanner: ms=%p, ms->sfd=%d\n", (void *) ms, ms->sfd); 1348141cc406Sopenharmony_ci 1349141cc406Sopenharmony_ci if ( ms->scanning == SANE_TRUE ) 1350141cc406Sopenharmony_ci cancel_scan(ms); 1351141cc406Sopenharmony_ci 1352141cc406Sopenharmony_ci if ( ms->sfd != -1 ) 1353141cc406Sopenharmony_ci sanei_scsi_close(ms->sfd); 1354141cc406Sopenharmony_ci ms->sfd = -1; 1355141cc406Sopenharmony_ci sanei_thread_invalidate(ms->pid); 1356141cc406Sopenharmony_ci ms->fp = NULL; 1357141cc406Sopenharmony_ci ms->current_pass = 0; 1358141cc406Sopenharmony_ci ms->scanning = SANE_FALSE; 1359141cc406Sopenharmony_ci ms->cancelled = SANE_FALSE; 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci /* free buffers */ 1362141cc406Sopenharmony_ci if ( ms->buf.src_buffer[0] ) 1363141cc406Sopenharmony_ci { 1364141cc406Sopenharmony_ci DBG(100, "free ms->buf.src_buffer[0] at %p\n", 1365141cc406Sopenharmony_ci (void *) ms->buf.src_buffer[0]); 1366141cc406Sopenharmony_ci free((void *) ms->buf.src_buffer[0]); 1367141cc406Sopenharmony_ci ms->buf.src_buffer[0] = NULL; 1368141cc406Sopenharmony_ci ms->buf.src_buf = NULL; 1369141cc406Sopenharmony_ci } 1370141cc406Sopenharmony_ci if ( ms->buf.src_buffer[1] ) 1371141cc406Sopenharmony_ci { 1372141cc406Sopenharmony_ci DBG(100, "free ms->buf.src_buffer[1] at %p\n", 1373141cc406Sopenharmony_ci (void *) ms->buf.src_buffer[1]); 1374141cc406Sopenharmony_ci free((void *) ms->buf.src_buffer[1]); 1375141cc406Sopenharmony_ci ms->buf.src_buffer[1] = NULL; 1376141cc406Sopenharmony_ci ms->buf.src_buf = NULL; 1377141cc406Sopenharmony_ci } 1378141cc406Sopenharmony_ci if ( ms->buf.src_buf ) 1379141cc406Sopenharmony_ci { 1380141cc406Sopenharmony_ci DBG(100, "free ms->buf.src_buf at %p\n", (void *) ms->buf.src_buf); 1381141cc406Sopenharmony_ci free((void *) ms->buf.src_buf); 1382141cc406Sopenharmony_ci ms->buf.src_buf = NULL; 1383141cc406Sopenharmony_ci } 1384141cc406Sopenharmony_ci if ( ms->temporary_buffer ) 1385141cc406Sopenharmony_ci { 1386141cc406Sopenharmony_ci DBG(100, "free ms->temporary_buffer at %p\n", 1387141cc406Sopenharmony_ci (void *) ms->temporary_buffer); 1388141cc406Sopenharmony_ci free((void *) ms->temporary_buffer); 1389141cc406Sopenharmony_ci ms->temporary_buffer = NULL; 1390141cc406Sopenharmony_ci } 1391141cc406Sopenharmony_ci if ( ms->gamma_table ) 1392141cc406Sopenharmony_ci { 1393141cc406Sopenharmony_ci DBG(100, "free ms->gamma_table at %p\n", (void *) ms->gamma_table); 1394141cc406Sopenharmony_ci free((void *) ms->gamma_table); 1395141cc406Sopenharmony_ci ms->gamma_table = NULL; 1396141cc406Sopenharmony_ci } 1397141cc406Sopenharmony_ci if ( ms->control_bytes ) 1398141cc406Sopenharmony_ci { 1399141cc406Sopenharmony_ci DBG(100, "free ms->control_bytes at %p\n", (void *) ms->control_bytes); 1400141cc406Sopenharmony_ci free((void *) ms->control_bytes); 1401141cc406Sopenharmony_ci ms->control_bytes = NULL; 1402141cc406Sopenharmony_ci } 1403141cc406Sopenharmony_ci if ( ms->condensed_shading_w ) 1404141cc406Sopenharmony_ci { 1405141cc406Sopenharmony_ci DBG(100, "free ms->condensed_shading_w at %p\n", 1406141cc406Sopenharmony_ci (void *) ms->condensed_shading_w); 1407141cc406Sopenharmony_ci free((void *) ms->condensed_shading_w); 1408141cc406Sopenharmony_ci ms->condensed_shading_w = NULL; 1409141cc406Sopenharmony_ci } 1410141cc406Sopenharmony_ci if ( ms->condensed_shading_d ) 1411141cc406Sopenharmony_ci { 1412141cc406Sopenharmony_ci DBG(100, "free ms->condensed_shading_d at %p\n", 1413141cc406Sopenharmony_ci (void *) ms->condensed_shading_d); 1414141cc406Sopenharmony_ci free((void *) ms->condensed_shading_d); 1415141cc406Sopenharmony_ci ms->condensed_shading_d = NULL; 1416141cc406Sopenharmony_ci } 1417141cc406Sopenharmony_ci 1418141cc406Sopenharmony_ci return; 1419141cc406Sopenharmony_ci} 1420141cc406Sopenharmony_ci 1421141cc406Sopenharmony_ci#ifdef HAVE_AUTHORIZATION 1422141cc406Sopenharmony_ci/*---------- do_authorization() ----------------------------------------------*/ 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_cistatic SANE_Status 1425141cc406Sopenharmony_cido_authorization(char *resource) 1426141cc406Sopenharmony_ci{ 1427141cc406Sopenharmony_ci /* This function implements a simple authorization function. It looks */ 1428141cc406Sopenharmony_ci /* up an entry in the file SANE_PATH_CONFIG_DIR/auth. Such an entry */ 1429141cc406Sopenharmony_ci /* must be of the form device:user:password where password is a crypt() */ 1430141cc406Sopenharmony_ci /* encrypted password. If several users are allowed to access a device */ 1431141cc406Sopenharmony_ci /* an entry must be created for each user. If no entry exists for device */ 1432141cc406Sopenharmony_ci /* or the file does not exist no authentication is necessary. If the */ 1433141cc406Sopenharmony_ci /* file exists, but can't be opened the authentication fails */ 1434141cc406Sopenharmony_ci 1435141cc406Sopenharmony_ci SANE_Status status; 1436141cc406Sopenharmony_ci FILE *fp; 1437141cc406Sopenharmony_ci int device_found; 1438141cc406Sopenharmony_ci char username[SANE_MAX_USERNAME_LEN]; 1439141cc406Sopenharmony_ci char password[SANE_MAX_PASSWORD_LEN]; 1440141cc406Sopenharmony_ci char line[MAX_LINE_LEN]; 1441141cc406Sopenharmony_ci char *linep; 1442141cc406Sopenharmony_ci char *device; 1443141cc406Sopenharmony_ci char *user; 1444141cc406Sopenharmony_ci char *passwd; 1445141cc406Sopenharmony_ci char *p; 1446141cc406Sopenharmony_ci 1447141cc406Sopenharmony_ci 1448141cc406Sopenharmony_ci DBG(30, "do_authorization: resource=%s\n", resource); 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_ci if ( auth_callback == NULL ) /* frontend does not require authorization */ 1451141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1452141cc406Sopenharmony_ci 1453141cc406Sopenharmony_ci /* first check if an entry exists in for this device. If not, we don't */ 1454141cc406Sopenharmony_ci /* use authorization */ 1455141cc406Sopenharmony_ci 1456141cc406Sopenharmony_ci fp = fopen(PASSWD_FILE, "r"); 1457141cc406Sopenharmony_ci if ( fp == NULL ) 1458141cc406Sopenharmony_ci { 1459141cc406Sopenharmony_ci if ( errno == ENOENT ) 1460141cc406Sopenharmony_ci { 1461141cc406Sopenharmony_ci DBG(1, "do_authorization: file not found: %s\n", PASSWD_FILE); 1462141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1463141cc406Sopenharmony_ci } 1464141cc406Sopenharmony_ci else 1465141cc406Sopenharmony_ci { 1466141cc406Sopenharmony_ci DBG(1, "do_authorization: fopen() failed, errno=%d\n", errno); 1467141cc406Sopenharmony_ci return SANE_STATUS_ACCESS_DENIED; 1468141cc406Sopenharmony_ci } 1469141cc406Sopenharmony_ci } 1470141cc406Sopenharmony_ci 1471141cc406Sopenharmony_ci linep = &line[0]; 1472141cc406Sopenharmony_ci device_found = 0; 1473141cc406Sopenharmony_ci while ( fgets(line, MAX_LINE_LEN, fp) ) 1474141cc406Sopenharmony_ci { 1475141cc406Sopenharmony_ci p = index(linep, SEPARATOR); 1476141cc406Sopenharmony_ci if ( p ) 1477141cc406Sopenharmony_ci { 1478141cc406Sopenharmony_ci *p = '\0'; 1479141cc406Sopenharmony_ci device = linep; 1480141cc406Sopenharmony_ci if ( strcmp(device, resource) == 0 ) 1481141cc406Sopenharmony_ci { 1482141cc406Sopenharmony_ci DBG(2, "equal\n"); 1483141cc406Sopenharmony_ci device_found = 1; 1484141cc406Sopenharmony_ci break; 1485141cc406Sopenharmony_ci } 1486141cc406Sopenharmony_ci } 1487141cc406Sopenharmony_ci } 1488141cc406Sopenharmony_ci 1489141cc406Sopenharmony_ci if ( ! device_found ) 1490141cc406Sopenharmony_ci { 1491141cc406Sopenharmony_ci fclose(fp); 1492141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1493141cc406Sopenharmony_ci } 1494141cc406Sopenharmony_ci 1495141cc406Sopenharmony_ci fseek(fp, 0L, SEEK_SET); 1496141cc406Sopenharmony_ci 1497141cc406Sopenharmony_ci (*auth_callback) (resource, username, password); 1498141cc406Sopenharmony_ci 1499141cc406Sopenharmony_ci status = SANE_STATUS_ACCESS_DENIED; 1500141cc406Sopenharmony_ci do 1501141cc406Sopenharmony_ci { 1502141cc406Sopenharmony_ci fgets(line, MAX_LINE_LEN, fp); 1503141cc406Sopenharmony_ci if ( ! ferror(fp) && ! feof(fp) ) 1504141cc406Sopenharmony_ci { 1505141cc406Sopenharmony_ci /* neither strsep(3) nor strtok(3) seem to work on my system */ 1506141cc406Sopenharmony_ci p = index(linep, SEPARATOR); 1507141cc406Sopenharmony_ci if ( p == NULL ) 1508141cc406Sopenharmony_ci continue; 1509141cc406Sopenharmony_ci *p = '\0'; 1510141cc406Sopenharmony_ci device = linep; 1511141cc406Sopenharmony_ci if ( strcmp( device, resource) != 0 ) /* not a matching entry */ 1512141cc406Sopenharmony_ci continue; 1513141cc406Sopenharmony_ci 1514141cc406Sopenharmony_ci linep = ++p; 1515141cc406Sopenharmony_ci p = index(linep, SEPARATOR); 1516141cc406Sopenharmony_ci if ( p == NULL ) 1517141cc406Sopenharmony_ci continue; 1518141cc406Sopenharmony_ci 1519141cc406Sopenharmony_ci *p = '\0'; 1520141cc406Sopenharmony_ci user = linep; 1521141cc406Sopenharmony_ci if ( strncmp(user, username, SANE_MAX_USERNAME_LEN) != 0 ) 1522141cc406Sopenharmony_ci continue; /* username doesn't match */ 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci linep = ++p; 1525141cc406Sopenharmony_ci /* rest of the line is considered to be the password */ 1526141cc406Sopenharmony_ci passwd = linep; 1527141cc406Sopenharmony_ci /* remove newline */ 1528141cc406Sopenharmony_ci *(passwd + strlen(passwd) - 1) = '\0'; 1529141cc406Sopenharmony_ci p = crypt(password, SALT); 1530141cc406Sopenharmony_ci if ( strcmp(p, passwd) == 0 ) 1531141cc406Sopenharmony_ci { 1532141cc406Sopenharmony_ci /* authentication ok */ 1533141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 1534141cc406Sopenharmony_ci break; 1535141cc406Sopenharmony_ci } 1536141cc406Sopenharmony_ci else 1537141cc406Sopenharmony_ci continue; 1538141cc406Sopenharmony_ci } 1539141cc406Sopenharmony_ci } while ( ! ferror(fp) && ! feof(fp) ); 1540141cc406Sopenharmony_ci fclose(fp); 1541141cc406Sopenharmony_ci 1542141cc406Sopenharmony_ci return status; 1543141cc406Sopenharmony_ci} 1544141cc406Sopenharmony_ci#endif 1545141cc406Sopenharmony_ci 1546141cc406Sopenharmony_ci/*---------- dump_area() -----------------------------------------------------*/ 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_cistatic SANE_Status 1549141cc406Sopenharmony_cidump_area(uint8_t *area, int len, char *info) 1550141cc406Sopenharmony_ci{ 1551141cc406Sopenharmony_ci /* this function dumps control or information blocks */ 1552141cc406Sopenharmony_ci 1553141cc406Sopenharmony_ci#define BPL 16 /* bytes per line to print */ 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci int i; 1556141cc406Sopenharmony_ci int o; 1557141cc406Sopenharmony_ci int o_limit; 1558141cc406Sopenharmony_ci char outputline[100]; 1559141cc406Sopenharmony_ci char *outbuf; 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci if ( ! info[0] ) 1562141cc406Sopenharmony_ci info = "No additional info available"; 1563141cc406Sopenharmony_ci 1564141cc406Sopenharmony_ci DBG(30, "dump_area: %s\n", info); 1565141cc406Sopenharmony_ci 1566141cc406Sopenharmony_ci outbuf = outputline; 1567141cc406Sopenharmony_ci o_limit = (len + BPL - 1) / BPL; 1568141cc406Sopenharmony_ci for ( o = 0; o < o_limit; o++) 1569141cc406Sopenharmony_ci { 1570141cc406Sopenharmony_ci sprintf(outbuf, " %4d: ", o * BPL); 1571141cc406Sopenharmony_ci outbuf += 8; 1572141cc406Sopenharmony_ci for ( i=0; i < BPL && (o * BPL + i ) < len; i++) 1573141cc406Sopenharmony_ci { 1574141cc406Sopenharmony_ci if ( i == BPL / 2 ) 1575141cc406Sopenharmony_ci { 1576141cc406Sopenharmony_ci sprintf(outbuf, " "); 1577141cc406Sopenharmony_ci outbuf +=1; 1578141cc406Sopenharmony_ci } 1579141cc406Sopenharmony_ci sprintf(outbuf, "%02x", area[o * BPL + i]); 1580141cc406Sopenharmony_ci outbuf += 2; 1581141cc406Sopenharmony_ci } 1582141cc406Sopenharmony_ci 1583141cc406Sopenharmony_ci sprintf(outbuf, "%*s", 2 * ( 2 + BPL - i), " " ); 1584141cc406Sopenharmony_ci outbuf += (2 * ( 2 + BPL - i)); 1585141cc406Sopenharmony_ci sprintf(outbuf, "%s", (i == BPL / 2) ? " " : ""); 1586141cc406Sopenharmony_ci outbuf += ((i == BPL / 2) ? 1 : 0); 1587141cc406Sopenharmony_ci 1588141cc406Sopenharmony_ci for ( i = 0; i < BPL && (o * BPL + i ) < len; i++) 1589141cc406Sopenharmony_ci { 1590141cc406Sopenharmony_ci if ( i == BPL / 2 ) 1591141cc406Sopenharmony_ci { 1592141cc406Sopenharmony_ci sprintf(outbuf, " "); 1593141cc406Sopenharmony_ci outbuf += 1; 1594141cc406Sopenharmony_ci } 1595141cc406Sopenharmony_ci sprintf(outbuf, "%c", isprint(area[o * BPL + i]) 1596141cc406Sopenharmony_ci ? area[o * BPL + i] 1597141cc406Sopenharmony_ci : '.'); 1598141cc406Sopenharmony_ci outbuf += 1; 1599141cc406Sopenharmony_ci } 1600141cc406Sopenharmony_ci outbuf = outputline; 1601141cc406Sopenharmony_ci DBG(1, "%s\n", outbuf); 1602141cc406Sopenharmony_ci } 1603141cc406Sopenharmony_ci 1604141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1605141cc406Sopenharmony_ci} 1606141cc406Sopenharmony_ci 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci/*---------- dump_area2() ----------------------------------------------------*/ 1609141cc406Sopenharmony_ci 1610141cc406Sopenharmony_cistatic SANE_Status 1611141cc406Sopenharmony_cidump_area2(uint8_t *area, int len, char *info) 1612141cc406Sopenharmony_ci{ 1613141cc406Sopenharmony_ci 1614141cc406Sopenharmony_ci#define BPL 16 /* bytes per line to print */ 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci int i; 1617141cc406Sopenharmony_ci char outputline[100]; 1618141cc406Sopenharmony_ci char *outbuf; 1619141cc406Sopenharmony_ci 1620141cc406Sopenharmony_ci if ( ! info[0] ) 1621141cc406Sopenharmony_ci info = "No additional info available"; 1622141cc406Sopenharmony_ci 1623141cc406Sopenharmony_ci DBG(1, "[%s]\n", info); 1624141cc406Sopenharmony_ci 1625141cc406Sopenharmony_ci outbuf = outputline; 1626141cc406Sopenharmony_ci for ( i = 0; i < len; i++) 1627141cc406Sopenharmony_ci { 1628141cc406Sopenharmony_ci sprintf(outbuf, "%02x,", *(area + i)); 1629141cc406Sopenharmony_ci outbuf += 3; 1630141cc406Sopenharmony_ci if ( ((i+1)%BPL == 0) || (i == len-1) ) 1631141cc406Sopenharmony_ci { 1632141cc406Sopenharmony_ci outbuf = outputline; 1633141cc406Sopenharmony_ci DBG(1, "%s\n", outbuf); 1634141cc406Sopenharmony_ci } 1635141cc406Sopenharmony_ci } 1636141cc406Sopenharmony_ci 1637141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1638141cc406Sopenharmony_ci} 1639141cc406Sopenharmony_ci 1640141cc406Sopenharmony_ci/*---------- dump_to_file() --------------------------------------------------*/ 1641141cc406Sopenharmony_ci/*--- only for debugging, currently not used -----*/ 1642141cc406Sopenharmony_ci#if 0 1643141cc406Sopenharmony_cistatic SANE_Status 1644141cc406Sopenharmony_cidump_to_file(uint8_t *area, int len, char *filename, char *mode) 1645141cc406Sopenharmony_ci{ 1646141cc406Sopenharmony_ciFILE *out; 1647141cc406Sopenharmony_ciint i; 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci out = fopen(filename, mode); 1650141cc406Sopenharmony_ci 1651141cc406Sopenharmony_ci for ( i = 0; i < len; i++) 1652141cc406Sopenharmony_ci fputc( *(area + i ), out); 1653141cc406Sopenharmony_ci 1654141cc406Sopenharmony_ci fclose(out); 1655141cc406Sopenharmony_ci 1656141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1657141cc406Sopenharmony_ci} 1658141cc406Sopenharmony_ci#endif 1659141cc406Sopenharmony_ci 1660141cc406Sopenharmony_ci/*---------- dump_attributes() -----------------------------------------------*/ 1661141cc406Sopenharmony_ci 1662141cc406Sopenharmony_cistatic SANE_Status 1663141cc406Sopenharmony_cidump_attributes(Microtek2_Info *mi) 1664141cc406Sopenharmony_ci{ 1665141cc406Sopenharmony_ci /* dump all we know about the scanner */ 1666141cc406Sopenharmony_ci 1667141cc406Sopenharmony_ci int i; 1668141cc406Sopenharmony_ci 1669141cc406Sopenharmony_ci DBG(30, "dump_attributes: mi=%p\n", (void *) mi); 1670141cc406Sopenharmony_ci DBG(1, "\n"); 1671141cc406Sopenharmony_ci DBG(1, "Scanner attributes from device structure\n"); 1672141cc406Sopenharmony_ci DBG(1, "========================================\n"); 1673141cc406Sopenharmony_ci DBG(1, "Scanner ID...\n"); 1674141cc406Sopenharmony_ci DBG(1, "~~~~~~~~~~~~~\n"); 1675141cc406Sopenharmony_ci DBG(1, " Vendor Name%15s: '%s'\n", " ", mi->vendor); 1676141cc406Sopenharmony_ci DBG(1, " Model Name%16s: '%s'\n", " ", mi->model); 1677141cc406Sopenharmony_ci DBG(1, " Revision%18s: '%s'\n", " ", mi->revision); 1678141cc406Sopenharmony_ci DBG(1, " Model Code%16s: 0x%02x\n"," ", mi->model_code); 1679141cc406Sopenharmony_ci switch(mi->model_code) 1680141cc406Sopenharmony_ci { 1681141cc406Sopenharmony_ci case 0x80: DBG(1, "Redondo 2000XL / ArtixScan 2020\n"); break; 1682141cc406Sopenharmony_ci case 0x81: DBG(1, "ScanMaker 4 / Aruba\n"); break; 1683141cc406Sopenharmony_ci case 0x82: DBG(1, "Bali\n"); break; 1684141cc406Sopenharmony_ci case 0x83: DBG(1, "Washington\n"); break; 1685141cc406Sopenharmony_ci case 0x84: DBG(1, "Manhattan\n"); break; 1686141cc406Sopenharmony_ci case 0x85: DBG(1, "ScanMaker V300 / Phantom parallel / TR3\n"); break; 1687141cc406Sopenharmony_ci case 0x86: DBG(1, "CCP\n"); break; 1688141cc406Sopenharmony_ci case 0x87: DBG(1, "Scanmaker V\n"); break; 1689141cc406Sopenharmony_ci case 0x88: DBG(1, "Scanmaker VI\n"); break; 1690141cc406Sopenharmony_ci case 0x89: DBG(1, "ScanMaker 6400XL / A3-400\n"); break; 1691141cc406Sopenharmony_ci case 0x8a: DBG(1, "ScanMaker 9600XL / A3-600\n"); break; 1692141cc406Sopenharmony_ci case 0x8b: DBG(1, "Watt\n"); break; 1693141cc406Sopenharmony_ci case 0x8c: DBG(1, "ScanMaker V600 / TR6\n"); break; 1694141cc406Sopenharmony_ci case 0x8d: DBG(1, "ScanMaker V310 / Tr3 10-bit\n"); break; 1695141cc406Sopenharmony_ci case 0x8e: DBG(1, "CCB\n"); break; 1696141cc406Sopenharmony_ci case 0x8f: DBG(1, "Sun Rise\n"); break; 1697141cc406Sopenharmony_ci case 0x90: DBG(1, "ScanMaker E3+ 10-bit\n"); break; 1698141cc406Sopenharmony_ci case 0x91: DBG(1, "ScanMaker X6 / Phantom 636\n"); break; 1699141cc406Sopenharmony_ci case 0x92: DBG(1, "ScanMaker E3+ / Vobis Highscan\n"); break; 1700141cc406Sopenharmony_ci case 0x93: DBG(1, "ScanMaker V310\n"); break; 1701141cc406Sopenharmony_ci case 0x94: DBG(1, "SlimScan C3 / Phantom 330cx / 336cx\n"); break; 1702141cc406Sopenharmony_ci case 0x95: DBG(1, "ArtixScan 1010\n"); break; 1703141cc406Sopenharmony_ci case 0x97: DBG(1, "ScanMaker V636\n"); break; 1704141cc406Sopenharmony_ci case 0x98: DBG(1, "ScanMaker X6EL\n"); break; 1705141cc406Sopenharmony_ci case 0x99: DBG(1, "ScanMaker X6 / X6USB\n"); break; 1706141cc406Sopenharmony_ci case 0x9a: DBG(1, "SlimScan C6 / Phantom 636cx\n"); break; 1707141cc406Sopenharmony_ci case 0x9d: DBG(1, "AGFA DuoScan T1200\n"); break; 1708141cc406Sopenharmony_ci case 0xa0: DBG(1, "SlimScan C3 / Phantom 336cx\n"); break; 1709141cc406Sopenharmony_ci case 0xac: DBG(1, "ScanMaker V6UL\n"); break; 1710141cc406Sopenharmony_ci case 0xa3: DBG(1, "ScanMaker V6USL\n"); break; 1711141cc406Sopenharmony_ci case 0xaf: DBG(1, "SlimScan C3 / Phantom 336cx\n"); break; 1712141cc406Sopenharmony_ci case 0xb0: DBG(1, "ScanMaker X12USL\n"); break; 1713141cc406Sopenharmony_ci case 0xb3: DBG(1, "ScanMaker 3600\n"); break; 1714141cc406Sopenharmony_ci case 0xb4: DBG(1, "ScanMaker 4700\n"); break; 1715141cc406Sopenharmony_ci case 0xb6: DBG(1, "ScanMaker V6UPL\n"); break; 1716141cc406Sopenharmony_ci case 0xb8: DBG(1, "ScanMaker 3700\n"); break; 1717141cc406Sopenharmony_ci case 0xde: DBG(1, "ScanMaker 9800XL\n"); break; 1718141cc406Sopenharmony_ci default: DBG(1, "Unknown\n"); break; 1719141cc406Sopenharmony_ci } 1720141cc406Sopenharmony_ci DBG(1, " Device Type Code%10s: 0x%02x (%s),\n", " ", 1721141cc406Sopenharmony_ci mi->device_type, 1722141cc406Sopenharmony_ci mi->device_type & MI_DEVTYPE_SCANNER ? 1723141cc406Sopenharmony_ci "Scanner" : "Unknown type"); 1724141cc406Sopenharmony_ci 1725141cc406Sopenharmony_ci switch (mi->scanner_type) 1726141cc406Sopenharmony_ci { 1727141cc406Sopenharmony_ci case MI_TYPE_FLATBED: 1728141cc406Sopenharmony_ci DBG(1, " Scanner type%14s:%s", " ", " Flatbed scanner\n"); 1729141cc406Sopenharmony_ci break; 1730141cc406Sopenharmony_ci case MI_TYPE_TRANSPARENCY: 1731141cc406Sopenharmony_ci DBG(1, " Scanner type%14s:%s", " ", " Transparency scanner\n"); 1732141cc406Sopenharmony_ci break; 1733141cc406Sopenharmony_ci case MI_TYPE_SHEEDFEED: 1734141cc406Sopenharmony_ci DBG(1, " Scanner type%14s:%s", " ", " Sheet feed scanner\n"); 1735141cc406Sopenharmony_ci break; 1736141cc406Sopenharmony_ci default: 1737141cc406Sopenharmony_ci DBG(1, " Scanner type%14s:%s", " ", " Unknown\n"); 1738141cc406Sopenharmony_ci break; 1739141cc406Sopenharmony_ci } 1740141cc406Sopenharmony_ci 1741141cc406Sopenharmony_ci DBG(1, " Supported options%9s: Automatic document feeder: %s\n", 1742141cc406Sopenharmony_ci " ", mi->option_device & MI_OPTDEV_ADF ? "Yes" : "No"); 1743141cc406Sopenharmony_ci DBG(1, "%30sTransparency media adapter: %s\n", 1744141cc406Sopenharmony_ci " ", mi->option_device & MI_OPTDEV_TMA ? "Yes" : "No"); 1745141cc406Sopenharmony_ci DBG(1, "%30sAuto paper detecting: %s\n", 1746141cc406Sopenharmony_ci " ", mi->option_device & MI_OPTDEV_ADP ? "Yes" : "No"); 1747141cc406Sopenharmony_ci DBG(1, "%30sAdvanced picture system: %s\n", 1748141cc406Sopenharmony_ci " ", mi->option_device & MI_OPTDEV_APS ? "Yes" : "No"); 1749141cc406Sopenharmony_ci DBG(1, "%30sStripes: %s\n", 1750141cc406Sopenharmony_ci " ", mi->option_device & MI_OPTDEV_STRIPE ? "Yes" : "No"); 1751141cc406Sopenharmony_ci DBG(1, "%30sSlides: %s\n", 1752141cc406Sopenharmony_ci " ", mi->option_device & MI_OPTDEV_SLIDE ? "Yes" : "No"); 1753141cc406Sopenharmony_ci DBG(1, " Scan button%15s: %s\n", " ", mi->scnbuttn ? "Yes" : "No"); 1754141cc406Sopenharmony_ci 1755141cc406Sopenharmony_ci DBG(1, "\n"); 1756141cc406Sopenharmony_ci DBG(1, " Imaging Capabilities...\n"); 1757141cc406Sopenharmony_ci DBG(1, " ~~~~~~~~~~~~~~~~~~~~~~~\n"); 1758141cc406Sopenharmony_ci DBG(1, " Color scanner%6s: %s\n", " ", (mi->color) ? "Yes" : "No"); 1759141cc406Sopenharmony_ci DBG(1, " Number passes%6s: %d pass%s\n", " ", 1760141cc406Sopenharmony_ci (mi->onepass) ? 1 : 3, 1761141cc406Sopenharmony_ci (mi->onepass) ? "" : "es"); 1762141cc406Sopenharmony_ci DBG(1, " Resolution%9s: X-max: %5d dpi\n%35sY-max: %5d dpi\n", 1763141cc406Sopenharmony_ci " ", mi->max_xresolution, " ",mi->max_yresolution); 1764141cc406Sopenharmony_ci DBG(1, " Geometry%11s: Geometric width: %5d pts (%2.2f'')\n", " ", 1765141cc406Sopenharmony_ci mi->geo_width, (float) mi->geo_width / (float) mi->opt_resolution); 1766141cc406Sopenharmony_ci DBG(1, "%23sGeometric height:%5d pts (%2.2f'')\n", " ", 1767141cc406Sopenharmony_ci mi->geo_height, (float) mi->geo_height / (float) mi->opt_resolution); 1768141cc406Sopenharmony_ci DBG(1, " Optical resolution%1s: %d\n", " ", mi->opt_resolution); 1769141cc406Sopenharmony_ci 1770141cc406Sopenharmony_ci DBG(1, " Modes%14s: Lineart: %s\n%35sHalftone: %s\n", " ", 1771141cc406Sopenharmony_ci (mi->scanmode & MI_HASMODE_LINEART) ? " Yes" : " No", " ", 1772141cc406Sopenharmony_ci (mi->scanmode & MI_HASMODE_HALFTONE) ? "Yes" : "No"); 1773141cc406Sopenharmony_ci 1774141cc406Sopenharmony_ci DBG(1, "%23sGray: %s\n%35sColor: %s\n", " ", 1775141cc406Sopenharmony_ci (mi->scanmode & MI_HASMODE_GRAY) ? " Yes" : " No", " ", 1776141cc406Sopenharmony_ci (mi->scanmode & MI_HASMODE_COLOR) ? " Yes" : " No"); 1777141cc406Sopenharmony_ci 1778141cc406Sopenharmony_ci DBG(1, " Depths%14s: Nibble Gray: %s\n", 1779141cc406Sopenharmony_ci " ", (mi->depth & MI_HASDEPTH_NIBBLE) ? "Yes" : "No"); 1780141cc406Sopenharmony_ci DBG(1, "%23s10-bit-color: %s\n", 1781141cc406Sopenharmony_ci " ", (mi->depth & MI_HASDEPTH_10) ? "Yes" : "No"); 1782141cc406Sopenharmony_ci DBG(1, "%23s12-bit-color: %s\n", " ", 1783141cc406Sopenharmony_ci (mi->depth & MI_HASDEPTH_12) ? "Yes" : "No"); 1784141cc406Sopenharmony_ci DBG(1, "%23s14-bit-color: %s\n", " ", 1785141cc406Sopenharmony_ci (mi->depth & MI_HASDEPTH_14) ? "Yes" : "No"); 1786141cc406Sopenharmony_ci DBG(1, "%23s16-bit-color: %s\n", " ", 1787141cc406Sopenharmony_ci (mi->depth & MI_HASDEPTH_16) ? "Yes" : "No"); 1788141cc406Sopenharmony_ci DBG(1, " d/l of HT pattern%2s: %s\n", 1789141cc406Sopenharmony_ci " ", (mi->has_dnldptrn) ? "Yes" : "No"); 1790141cc406Sopenharmony_ci DBG(1, " Builtin HT pattern%1s: %d\n", " ", mi->grain_slct); 1791141cc406Sopenharmony_ci 1792141cc406Sopenharmony_ci if ( MI_LUTCAP_NONE(mi->lut_cap) ) 1793141cc406Sopenharmony_ci DBG(1, " LUT capabilities : None\n"); 1794141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_256B ) 1795141cc406Sopenharmony_ci DBG(1, " LUT capabilities : 256 bytes\n"); 1796141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_1024B ) 1797141cc406Sopenharmony_ci DBG(1, " LUT capabilities : 1024 bytes\n"); 1798141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_1024W ) 1799141cc406Sopenharmony_ci DBG(1, " LUT capabilities : 1024 words\n"); 1800141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_4096B ) 1801141cc406Sopenharmony_ci DBG(1, " LUT capabilities : 4096 bytes\n"); 1802141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_4096W ) 1803141cc406Sopenharmony_ci DBG(1, " LUT capabilities : 4096 words\n"); 1804141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_64k_W ) 1805141cc406Sopenharmony_ci DBG(1, " LUT capabilities : 64k words\n"); 1806141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_16k_W ) 1807141cc406Sopenharmony_ci DBG(1, " LUT capabilities : 16k words\n"); 1808141cc406Sopenharmony_ci DBG(1, "\n"); 1809141cc406Sopenharmony_ci DBG(1, " Miscellaneous capabilities...\n"); 1810141cc406Sopenharmony_ci DBG(1, " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); 1811141cc406Sopenharmony_ci if ( mi->onepass) 1812141cc406Sopenharmony_ci { 1813141cc406Sopenharmony_ci switch(mi->data_format) 1814141cc406Sopenharmony_ci { 1815141cc406Sopenharmony_ci case MI_DATAFMT_CHUNKY: 1816141cc406Sopenharmony_ci DBG(1, " Data format :%s", 1817141cc406Sopenharmony_ci " Chunky data, R, G & B in one pixel\n"); 1818141cc406Sopenharmony_ci break; 1819141cc406Sopenharmony_ci case MI_DATAFMT_LPLCONCAT: 1820141cc406Sopenharmony_ci DBG(1, " Data format :%s", 1821141cc406Sopenharmony_ci " Line by line in concatenated sequence,\n"); 1822141cc406Sopenharmony_ci DBG(1, "%23swithout color indicator\n", " "); 1823141cc406Sopenharmony_ci break; 1824141cc406Sopenharmony_ci case MI_DATAFMT_LPLSEGREG: 1825141cc406Sopenharmony_ci DBG(1, " Data format :%s", 1826141cc406Sopenharmony_ci " Line by line in segregated sequence,\n"); 1827141cc406Sopenharmony_ci DBG(1, "%23swith color indicator\n", " "); 1828141cc406Sopenharmony_ci break; 1829141cc406Sopenharmony_ci case MI_DATAFMT_WORDCHUNKY: 1830141cc406Sopenharmony_ci DBG(1, " Data format : Word chunky data\n"); 1831141cc406Sopenharmony_ci break; 1832141cc406Sopenharmony_ci default: 1833141cc406Sopenharmony_ci DBG(1, " Data format : Unknown\n"); 1834141cc406Sopenharmony_ci break; 1835141cc406Sopenharmony_ci } 1836141cc406Sopenharmony_ci } 1837141cc406Sopenharmony_ci else 1838141cc406Sopenharmony_ci DBG(1, "No information with 3-pass scanners\n"); 1839141cc406Sopenharmony_ci 1840141cc406Sopenharmony_ci DBG(1, " Color Sequence%17s: \n", " "); 1841141cc406Sopenharmony_ci for ( i = 0; i < RSA_COLORSEQUENCE_L; i++) 1842141cc406Sopenharmony_ci { 1843141cc406Sopenharmony_ci switch(mi->color_sequence[i]) 1844141cc406Sopenharmony_ci { 1845141cc406Sopenharmony_ci case MI_COLSEQ_RED: DBG(1,"%34s%s\n", " ","R"); break; 1846141cc406Sopenharmony_ci case MI_COLSEQ_GREEN: DBG(1,"%34s%s\n", " ","G"); break; 1847141cc406Sopenharmony_ci case MI_COLSEQ_BLUE: DBG(1,"%34s%s\n", " ","B"); break; 1848141cc406Sopenharmony_ci } 1849141cc406Sopenharmony_ci } 1850141cc406Sopenharmony_ci if ( mi->new_image_status == SANE_TRUE ) 1851141cc406Sopenharmony_ci DBG(1, " Using new ReadImageStatus format\n"); 1852141cc406Sopenharmony_ci else 1853141cc406Sopenharmony_ci DBG(1, " Using old ReadImageStatus format\n"); 1854141cc406Sopenharmony_ci if ( mi->direction & MI_DATSEQ_RTOL ) 1855141cc406Sopenharmony_ci DBG(1, " Scanning direction : right to left\n"); 1856141cc406Sopenharmony_ci else 1857141cc406Sopenharmony_ci DBG(1, " Scanning direction : left to right\n"); 1858141cc406Sopenharmony_ci DBG(1, " CCD gap%24s: %d lines\n", " ", mi->ccd_gap); 1859141cc406Sopenharmony_ci DBG(1, " CCD pixels%21s: %d\n", " ", mi->ccd_pixels); 1860141cc406Sopenharmony_ci DBG(1, " Calib white stripe location%4s: %d\n", 1861141cc406Sopenharmony_ci " ", mi->calib_white); 1862141cc406Sopenharmony_ci DBG(1, " Max calib space%16s: %d\n", " ", mi->calib_space); 1863141cc406Sopenharmony_ci DBG(1, " Number of lens%17s: %d\n", " ", mi->nlens); 1864141cc406Sopenharmony_ci DBG(1, " Max number of windows%10s: %d\n", " ", mi->nwindows); 1865141cc406Sopenharmony_ci DBG(1, " Shading transfer function%6s: 0x%02x\n", " ",mi->shtrnsferequ); 1866141cc406Sopenharmony_ci DBG(1, " Red balance%20s: %d\n", " ", mi->balance[0]); 1867141cc406Sopenharmony_ci DBG(1, " Green balance%18s: %d\n", " ", mi->balance[1]); 1868141cc406Sopenharmony_ci DBG(1, " Blue balance%19s: %d\n", " " , mi->balance[2]); 1869141cc406Sopenharmony_ci DBG(1, " Buffer type%20s: %s\n", 1870141cc406Sopenharmony_ci " ", mi->buftype ? "Ping-Pong" : "Ring"); 1871141cc406Sopenharmony_ci DBG(1, " FEPROM%25s: %s\n", " ", mi->feprom ? "Yes" : "No"); 1872141cc406Sopenharmony_ci 1873141cc406Sopenharmony_ci md_dump_clear = 0; 1874141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1875141cc406Sopenharmony_ci} 1876141cc406Sopenharmony_ci 1877141cc406Sopenharmony_ci/*---------- max_string_size() -----------------------------------------------*/ 1878141cc406Sopenharmony_ci 1879141cc406Sopenharmony_cistatic size_t 1880141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 1881141cc406Sopenharmony_ci{ 1882141cc406Sopenharmony_ci size_t size; 1883141cc406Sopenharmony_ci size_t max_size = 0; 1884141cc406Sopenharmony_ci int i; 1885141cc406Sopenharmony_ci 1886141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) { 1887141cc406Sopenharmony_ci size = strlen(strings[i]) + 1; /* +1 because NUL counts as part of string */ 1888141cc406Sopenharmony_ci if (size > max_size) max_size = size; 1889141cc406Sopenharmony_ci } 1890141cc406Sopenharmony_ci return max_size; 1891141cc406Sopenharmony_ci} 1892141cc406Sopenharmony_ci 1893141cc406Sopenharmony_ci/*---------- parse_config_file() ---------------------------------------------*/ 1894141cc406Sopenharmony_ci 1895141cc406Sopenharmony_cistatic void 1896141cc406Sopenharmony_ciparse_config_file(FILE *fp, Config_Temp **ct) 1897141cc406Sopenharmony_ci{ 1898141cc406Sopenharmony_ci /* builds a list of device names with associated options from the */ 1899141cc406Sopenharmony_ci /* config file for later use, when building the list of devices. */ 1900141cc406Sopenharmony_ci /* ct->device = NULL indicates global options (valid for all devices */ 1901141cc406Sopenharmony_ci 1902141cc406Sopenharmony_ci char s[PATH_MAX]; 1903141cc406Sopenharmony_ci Config_Options global_opts; 1904141cc406Sopenharmony_ci Config_Temp *hct1; 1905141cc406Sopenharmony_ci Config_Temp *hct2; 1906141cc406Sopenharmony_ci 1907141cc406Sopenharmony_ci 1908141cc406Sopenharmony_ci DBG(30, "parse_config_file: fp=%p\n", (void *) fp); 1909141cc406Sopenharmony_ci 1910141cc406Sopenharmony_ci *ct = hct1 = NULL; 1911141cc406Sopenharmony_ci 1912141cc406Sopenharmony_ci /* first read global options and store them in global_opts */ 1913141cc406Sopenharmony_ci /* initialize global_opts with default values */ 1914141cc406Sopenharmony_ci 1915141cc406Sopenharmony_ci global_opts = md_options; 1916141cc406Sopenharmony_ci 1917141cc406Sopenharmony_ci while ( sanei_config_read(s, sizeof(s), fp) ) 1918141cc406Sopenharmony_ci { 1919141cc406Sopenharmony_ci DBG(100, "parse_config_file: read line: %s\n", s); 1920141cc406Sopenharmony_ci if ( *s == '#' || *s == '\0' ) /* ignore empty lines and comments */ 1921141cc406Sopenharmony_ci continue; 1922141cc406Sopenharmony_ci 1923141cc406Sopenharmony_ci if ( strncmp( sanei_config_skip_whitespace(s), "option ", 7) == 0 1924141cc406Sopenharmony_ci || strncmp( sanei_config_skip_whitespace(s), "option\t", 7) == 0 ) 1925141cc406Sopenharmony_ci { 1926141cc406Sopenharmony_ci DBG(100, "parse_config_file: found global option %s\n", s); 1927141cc406Sopenharmony_ci check_option(s, &global_opts); 1928141cc406Sopenharmony_ci } 1929141cc406Sopenharmony_ci else /* it is considered a new device */ 1930141cc406Sopenharmony_ci break; 1931141cc406Sopenharmony_ci } 1932141cc406Sopenharmony_ci 1933141cc406Sopenharmony_ci if ( ferror(fp) || feof(fp) ) 1934141cc406Sopenharmony_ci { 1935141cc406Sopenharmony_ci if ( ferror(fp) ) 1936141cc406Sopenharmony_ci DBG(1, "parse_config_file: fread failed: errno=%d\n", errno); 1937141cc406Sopenharmony_ci 1938141cc406Sopenharmony_ci return; 1939141cc406Sopenharmony_ci } 1940141cc406Sopenharmony_ci 1941141cc406Sopenharmony_ci while ( ! feof(fp) && ! ferror(fp) ) 1942141cc406Sopenharmony_ci { 1943141cc406Sopenharmony_ci if ( *s == '#' || *s == '\0' ) /* ignore empty lines and comments */ 1944141cc406Sopenharmony_ci { 1945141cc406Sopenharmony_ci sanei_config_read(s, sizeof(s), fp); 1946141cc406Sopenharmony_ci continue; 1947141cc406Sopenharmony_ci } 1948141cc406Sopenharmony_ci 1949141cc406Sopenharmony_ci if ( strncmp( sanei_config_skip_whitespace(s), "option ", 7) == 0 1950141cc406Sopenharmony_ci || strncmp( sanei_config_skip_whitespace(s), "option\t", 7) == 0 ) 1951141cc406Sopenharmony_ci { 1952141cc406Sopenharmony_ci /* when we enter this loop for the first time we allocate */ 1953141cc406Sopenharmony_ci /* memory, because the line surely contains a device name, */ 1954141cc406Sopenharmony_ci /* so hct1 is always != NULL at this point */ 1955141cc406Sopenharmony_ci DBG(100, "parse_config_file: found device option %s\n", s); 1956141cc406Sopenharmony_ci check_option(s, &hct1->opts); 1957141cc406Sopenharmony_ci } 1958141cc406Sopenharmony_ci 1959141cc406Sopenharmony_ci 1960141cc406Sopenharmony_ci else /* it is considered a new device */ 1961141cc406Sopenharmony_ci { 1962141cc406Sopenharmony_ci DBG(100, "parse_config_file: found device %s\n", s); 1963141cc406Sopenharmony_ci hct2 = (Config_Temp *) malloc(sizeof(Config_Temp)); 1964141cc406Sopenharmony_ci if ( hct2 == NULL ) 1965141cc406Sopenharmony_ci { 1966141cc406Sopenharmony_ci DBG(1, "parse_config_file: malloc() failed\n"); 1967141cc406Sopenharmony_ci return; 1968141cc406Sopenharmony_ci } 1969141cc406Sopenharmony_ci 1970141cc406Sopenharmony_ci if ( *ct == NULL ) /* first element */ 1971141cc406Sopenharmony_ci *ct = hct1 = hct2; 1972141cc406Sopenharmony_ci 1973141cc406Sopenharmony_ci hct1->next = hct2; 1974141cc406Sopenharmony_ci hct1 = hct2; 1975141cc406Sopenharmony_ci 1976141cc406Sopenharmony_ci hct1->device = strdup(s); 1977141cc406Sopenharmony_ci hct1->opts = global_opts; 1978141cc406Sopenharmony_ci hct1->next = NULL; 1979141cc406Sopenharmony_ci } 1980141cc406Sopenharmony_ci sanei_config_read(s, sizeof(s), fp); 1981141cc406Sopenharmony_ci } 1982141cc406Sopenharmony_ci /* set filepointer to the beginning of the file */ 1983141cc406Sopenharmony_ci fseek(fp, 0L, SEEK_SET); 1984141cc406Sopenharmony_ci return; 1985141cc406Sopenharmony_ci} 1986141cc406Sopenharmony_ci 1987141cc406Sopenharmony_ci 1988141cc406Sopenharmony_ci/*---------- signal_handler() ------------------------------------------------*/ 1989141cc406Sopenharmony_ci 1990141cc406Sopenharmony_cistatic void 1991141cc406Sopenharmony_cisignal_handler (int signal) 1992141cc406Sopenharmony_ci{ 1993141cc406Sopenharmony_ci if ( signal == SIGTERM ) 1994141cc406Sopenharmony_ci { 1995141cc406Sopenharmony_ci sanei_scsi_req_flush_all (); 1996141cc406Sopenharmony_ci _exit (SANE_STATUS_GOOD); 1997141cc406Sopenharmony_ci } 1998141cc406Sopenharmony_ci} 1999141cc406Sopenharmony_ci 2000141cc406Sopenharmony_ci/*---------- init_options() --------------------------------------------------*/ 2001141cc406Sopenharmony_ci 2002141cc406Sopenharmony_cistatic SANE_Status 2003141cc406Sopenharmony_ciinit_options(Microtek2_Scanner *ms, uint8_t current_scan_source) 2004141cc406Sopenharmony_ci{ 2005141cc406Sopenharmony_ci /* This function is called every time, when the scan source changes. */ 2006141cc406Sopenharmony_ci /* The option values, that possibly change, are then reinitialized, */ 2007141cc406Sopenharmony_ci /* whereas the option descriptors and option values that never */ 2008141cc406Sopenharmony_ci /* change are not */ 2009141cc406Sopenharmony_ci 2010141cc406Sopenharmony_ci SANE_Option_Descriptor *sod; 2011141cc406Sopenharmony_ci SANE_Status status; 2012141cc406Sopenharmony_ci Option_Value *val; 2013141cc406Sopenharmony_ci Microtek2_Device *md; 2014141cc406Sopenharmony_ci Microtek2_Info *mi; 2015141cc406Sopenharmony_ci int tablesize; 2016141cc406Sopenharmony_ci int option_size; 2017141cc406Sopenharmony_ci int max_gamma_value; 2018141cc406Sopenharmony_ci int color; 2019141cc406Sopenharmony_ci int i; 2020141cc406Sopenharmony_ci static int first_call = 1; /* indicates, whether option */ 2021141cc406Sopenharmony_ci /* descriptors must be initialized */ 2022141cc406Sopenharmony_ci /* cannot be used as after a sane_close the sod's must be initialized */ 2023141cc406Sopenharmony_ci 2024141cc406Sopenharmony_ci DBG(30, "init_options: handle=%p, source=%d\n", (void *) ms, 2025141cc406Sopenharmony_ci current_scan_source); 2026141cc406Sopenharmony_ci 2027141cc406Sopenharmony_ci sod = ms->sod; 2028141cc406Sopenharmony_ci val = ms->val; 2029141cc406Sopenharmony_ci md = ms->dev; 2030141cc406Sopenharmony_ci mi = &md->info[current_scan_source]; 2031141cc406Sopenharmony_ci 2032141cc406Sopenharmony_ci /* needed for gamma calculation */ 2033141cc406Sopenharmony_ci get_lut_size(mi, &md->max_lut_size, &md->lut_entry_size); 2034141cc406Sopenharmony_ci 2035141cc406Sopenharmony_ci /* calculate new values, where possibly needed */ 2036141cc406Sopenharmony_ci 2037141cc406Sopenharmony_ci /* Scan source */ 2038141cc406Sopenharmony_ci if ( val[OPT_SOURCE].s ) 2039141cc406Sopenharmony_ci free((void *) val[OPT_SOURCE].s); 2040141cc406Sopenharmony_ci i = 0; 2041141cc406Sopenharmony_ci md->scansource_list[i] = (SANE_String) MD_SOURCESTRING_FLATBED; 2042141cc406Sopenharmony_ci if ( current_scan_source == MD_SOURCE_FLATBED ) 2043141cc406Sopenharmony_ci val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); 2044141cc406Sopenharmony_ci if ( md->status.adfcnt ) 2045141cc406Sopenharmony_ci { 2046141cc406Sopenharmony_ci md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_ADF; 2047141cc406Sopenharmony_ci if ( current_scan_source == MD_SOURCE_ADF ) 2048141cc406Sopenharmony_ci val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); 2049141cc406Sopenharmony_ci } 2050141cc406Sopenharmony_ci if ( md->status.tmacnt ) 2051141cc406Sopenharmony_ci { 2052141cc406Sopenharmony_ci md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_TMA; 2053141cc406Sopenharmony_ci if ( current_scan_source == MD_SOURCE_TMA ) 2054141cc406Sopenharmony_ci val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); 2055141cc406Sopenharmony_ci } 2056141cc406Sopenharmony_ci if ( mi->option_device & MI_OPTDEV_STRIPE ) 2057141cc406Sopenharmony_ci { 2058141cc406Sopenharmony_ci md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_STRIPE; 2059141cc406Sopenharmony_ci if ( current_scan_source == MD_SOURCE_STRIPE ) 2060141cc406Sopenharmony_ci val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); 2061141cc406Sopenharmony_ci } 2062141cc406Sopenharmony_ci 2063141cc406Sopenharmony_ci /* Comment this out as long as I do not know in which bit */ 2064141cc406Sopenharmony_ci /* it is indicated, whether a slide adapter is connected */ 2065141cc406Sopenharmony_ci#if 0 2066141cc406Sopenharmony_ci if ( mi->option_device & MI_OPTDEV_SLIDE ) 2067141cc406Sopenharmony_ci { 2068141cc406Sopenharmony_ci md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_SLIDE; 2069141cc406Sopenharmony_ci if ( current_scan_source == MD_SOURCE_SLIDE ) 2070141cc406Sopenharmony_ci val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); 2071141cc406Sopenharmony_ci } 2072141cc406Sopenharmony_ci#endif 2073141cc406Sopenharmony_ci 2074141cc406Sopenharmony_ci md->scansource_list[++i] = NULL; 2075141cc406Sopenharmony_ci 2076141cc406Sopenharmony_ci /* Scan mode */ 2077141cc406Sopenharmony_ci if ( val[OPT_MODE].s ) 2078141cc406Sopenharmony_ci free((void *) val[OPT_MODE].s); 2079141cc406Sopenharmony_ci 2080141cc406Sopenharmony_ci i = 0; 2081141cc406Sopenharmony_ci if ( (mi->scanmode & MI_HASMODE_COLOR) ) 2082141cc406Sopenharmony_ci { 2083141cc406Sopenharmony_ci md->scanmode_list[i] = (SANE_String) MD_MODESTRING_COLOR; 2084141cc406Sopenharmony_ci val[OPT_MODE].s = strdup(md->scanmode_list[i]); 2085141cc406Sopenharmony_ci ++i; 2086141cc406Sopenharmony_ci } 2087141cc406Sopenharmony_ci 2088141cc406Sopenharmony_ci if ( mi->scanmode & MI_HASMODE_GRAY ) 2089141cc406Sopenharmony_ci { 2090141cc406Sopenharmony_ci md->scanmode_list[i] = (SANE_String) MD_MODESTRING_GRAY; 2091141cc406Sopenharmony_ci if ( ! (mi->scanmode & MI_HASMODE_COLOR ) ) 2092141cc406Sopenharmony_ci val[OPT_MODE].s = strdup(md->scanmode_list[i]); 2093141cc406Sopenharmony_ci ++i; 2094141cc406Sopenharmony_ci } 2095141cc406Sopenharmony_ci 2096141cc406Sopenharmony_ci if ( mi->scanmode & MI_HASMODE_HALFTONE ) 2097141cc406Sopenharmony_ci { 2098141cc406Sopenharmony_ci md->scanmode_list[i] = (SANE_String) MD_MODESTRING_HALFTONE; 2099141cc406Sopenharmony_ci if ( ! (mi->scanmode & MI_HASMODE_COLOR ) 2100141cc406Sopenharmony_ci && ! (mi->scanmode & MI_HASMODE_GRAY ) ) 2101141cc406Sopenharmony_ci val[OPT_MODE].s = strdup(md->scanmode_list[i]); 2102141cc406Sopenharmony_ci ++i; 2103141cc406Sopenharmony_ci } 2104141cc406Sopenharmony_ci 2105141cc406Sopenharmony_ci /* Always enable a lineart mode. Some models (X6, FW 1.40) say */ 2106141cc406Sopenharmony_ci /* that they have no lineart mode. In this case we will do a grayscale */ 2107141cc406Sopenharmony_ci /* scan and convert it to onebit data */ 2108141cc406Sopenharmony_ci md->scanmode_list[i] = (SANE_String) MD_MODESTRING_LINEART; 2109141cc406Sopenharmony_ci if ( ! (mi->scanmode & MI_HASMODE_COLOR ) 2110141cc406Sopenharmony_ci && ! (mi->scanmode & MI_HASMODE_GRAY ) 2111141cc406Sopenharmony_ci && ! (mi->scanmode & MI_HASMODE_HALFTONE ) ) 2112141cc406Sopenharmony_ci val[OPT_MODE].s = strdup(md->scanmode_list[i]); 2113141cc406Sopenharmony_ci ++i; 2114141cc406Sopenharmony_ci md->scanmode_list[i] = NULL; 2115141cc406Sopenharmony_ci 2116141cc406Sopenharmony_ci /* bitdepth */ 2117141cc406Sopenharmony_ci i = 0; 2118141cc406Sopenharmony_ci 2119141cc406Sopenharmony_ci#if 0 2120141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_NIBBLE ) 2121141cc406Sopenharmony_ci md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_4; 2122141cc406Sopenharmony_ci#endif 2123141cc406Sopenharmony_ci 2124141cc406Sopenharmony_ci md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_8; 2125141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_10 ) 2126141cc406Sopenharmony_ci md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_10; 2127141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_12 ) 2128141cc406Sopenharmony_ci md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_12; 2129141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_14 ) 2130141cc406Sopenharmony_ci md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_14; 2131141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 2132141cc406Sopenharmony_ci md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_16; 2133141cc406Sopenharmony_ci 2134141cc406Sopenharmony_ci md->bitdepth_list[0] = i; 2135141cc406Sopenharmony_ci if ( md->bitdepth_list[1] == (SANE_Int) MD_DEPTHVAL_8 ) 2136141cc406Sopenharmony_ci val[OPT_BITDEPTH].w = md->bitdepth_list[1]; 2137141cc406Sopenharmony_ci else 2138141cc406Sopenharmony_ci val[OPT_BITDEPTH].w = md->bitdepth_list[2]; 2139141cc406Sopenharmony_ci 2140141cc406Sopenharmony_ci /* Halftone */ 2141141cc406Sopenharmony_ci md->halftone_mode_list[0] = (SANE_String) MD_HALFTONE0; 2142141cc406Sopenharmony_ci md->halftone_mode_list[1] = (SANE_String) MD_HALFTONE1; 2143141cc406Sopenharmony_ci md->halftone_mode_list[2] = (SANE_String) MD_HALFTONE2; 2144141cc406Sopenharmony_ci md->halftone_mode_list[3] = (SANE_String) MD_HALFTONE3; 2145141cc406Sopenharmony_ci md->halftone_mode_list[4] = (SANE_String) MD_HALFTONE4; 2146141cc406Sopenharmony_ci md->halftone_mode_list[5] = (SANE_String) MD_HALFTONE5; 2147141cc406Sopenharmony_ci md->halftone_mode_list[6] = (SANE_String) MD_HALFTONE6; 2148141cc406Sopenharmony_ci md->halftone_mode_list[7] = (SANE_String) MD_HALFTONE7; 2149141cc406Sopenharmony_ci md->halftone_mode_list[8] = (SANE_String) MD_HALFTONE8; 2150141cc406Sopenharmony_ci md->halftone_mode_list[9] = (SANE_String) MD_HALFTONE9; 2151141cc406Sopenharmony_ci md->halftone_mode_list[10] = (SANE_String) MD_HALFTONE10; 2152141cc406Sopenharmony_ci md->halftone_mode_list[11] = (SANE_String) MD_HALFTONE11; 2153141cc406Sopenharmony_ci md->halftone_mode_list[12] = NULL; 2154141cc406Sopenharmony_ci if ( val[OPT_HALFTONE].s ) 2155141cc406Sopenharmony_ci free((void *) val[OPT_HALFTONE].s); 2156141cc406Sopenharmony_ci val[OPT_HALFTONE].s = strdup(md->halftone_mode_list[0]); 2157141cc406Sopenharmony_ci 2158141cc406Sopenharmony_ci /* Resolution */ 2159141cc406Sopenharmony_ci md->x_res_range_dpi.min = SANE_FIX(10.0); 2160141cc406Sopenharmony_ci md->x_res_range_dpi.max = SANE_FIX(mi->max_xresolution); 2161141cc406Sopenharmony_ci md->x_res_range_dpi.quant = SANE_FIX(1.0); 2162141cc406Sopenharmony_ci val[OPT_RESOLUTION].w = MIN(MD_RESOLUTION_DEFAULT, md->x_res_range_dpi.max); 2163141cc406Sopenharmony_ci 2164141cc406Sopenharmony_ci md->y_res_range_dpi.min = SANE_FIX(10.0); 2165141cc406Sopenharmony_ci md->y_res_range_dpi.max = SANE_FIX(mi->max_yresolution); 2166141cc406Sopenharmony_ci md->y_res_range_dpi.quant = SANE_FIX(1.0); 2167141cc406Sopenharmony_ci val[OPT_Y_RESOLUTION].w = val[OPT_RESOLUTION].w; /* bind is default */ 2168141cc406Sopenharmony_ci 2169141cc406Sopenharmony_ci /* Preview mode */ 2170141cc406Sopenharmony_ci val[OPT_PREVIEW].w = SANE_FALSE; 2171141cc406Sopenharmony_ci 2172141cc406Sopenharmony_ci /* Geometry */ 2173141cc406Sopenharmony_ci md->x_range_mm.min = SANE_FIX(0.0); 2174141cc406Sopenharmony_ci md->x_range_mm.max = SANE_FIX((double) mi->geo_width 2175141cc406Sopenharmony_ci / (double) mi->opt_resolution 2176141cc406Sopenharmony_ci * MM_PER_INCH); 2177141cc406Sopenharmony_ci md->x_range_mm.quant = SANE_FIX(0.0); 2178141cc406Sopenharmony_ci md->y_range_mm.min = SANE_FIX(0.0); 2179141cc406Sopenharmony_ci md->y_range_mm.max = SANE_FIX((double) mi->geo_height 2180141cc406Sopenharmony_ci / (double) mi->opt_resolution 2181141cc406Sopenharmony_ci * MM_PER_INCH); 2182141cc406Sopenharmony_ci md->y_range_mm.quant = SANE_FIX(0.0); 2183141cc406Sopenharmony_ci val[OPT_TL_X].w = SANE_FIX(0.0); 2184141cc406Sopenharmony_ci val[OPT_TL_Y].w = SANE_FIX(0.0); 2185141cc406Sopenharmony_ci val[OPT_BR_X].w = md->x_range_mm.max; 2186141cc406Sopenharmony_ci val[OPT_BR_Y].w = md->y_range_mm.max; 2187141cc406Sopenharmony_ci 2188141cc406Sopenharmony_ci /* Enhancement group */ 2189141cc406Sopenharmony_ci val[OPT_BRIGHTNESS].w = MD_BRIGHTNESS_DEFAULT; 2190141cc406Sopenharmony_ci val[OPT_CONTRAST].w = MD_CONTRAST_DEFAULT; 2191141cc406Sopenharmony_ci val[OPT_THRESHOLD].w = MD_THRESHOLD_DEFAULT; 2192141cc406Sopenharmony_ci 2193141cc406Sopenharmony_ci /* Gamma */ 2194141cc406Sopenharmony_ci /* linear gamma must come first */ 2195141cc406Sopenharmony_ci i = 0; 2196141cc406Sopenharmony_ci md->gammamode_list[i++] = (SANE_String) MD_GAMMAMODE_LINEAR; 2197141cc406Sopenharmony_ci md->gammamode_list[i++] = (SANE_String) MD_GAMMAMODE_SCALAR; 2198141cc406Sopenharmony_ci md->gammamode_list[i++] = (SANE_String) MD_GAMMAMODE_CUSTOM; 2199141cc406Sopenharmony_ci if ( val[OPT_GAMMA_MODE].s ) 2200141cc406Sopenharmony_ci free((void *) val[OPT_GAMMA_MODE].s); 2201141cc406Sopenharmony_ci val[OPT_GAMMA_MODE].s = strdup(md->gammamode_list[0]); 2202141cc406Sopenharmony_ci 2203141cc406Sopenharmony_ci md->gammamode_list[i] = NULL; 2204141cc406Sopenharmony_ci 2205141cc406Sopenharmony_ci /* bind gamma */ 2206141cc406Sopenharmony_ci val[OPT_GAMMA_BIND].w = SANE_TRUE; 2207141cc406Sopenharmony_ci val[OPT_GAMMA_SCALAR].w = MD_GAMMA_DEFAULT; 2208141cc406Sopenharmony_ci val[OPT_GAMMA_SCALAR_R].w = MD_GAMMA_DEFAULT; 2209141cc406Sopenharmony_ci val[OPT_GAMMA_SCALAR_G].w = MD_GAMMA_DEFAULT; 2210141cc406Sopenharmony_ci val[OPT_GAMMA_SCALAR_B].w = MD_GAMMA_DEFAULT; 2211141cc406Sopenharmony_ci 2212141cc406Sopenharmony_ci /* If the device supports gamma tables, we allocate memory according */ 2213141cc406Sopenharmony_ci /* to lookup table capabilities, otherwise we allocate 4096 elements */ 2214141cc406Sopenharmony_ci /* which is sufficient for a color depth of 12. If the device */ 2215141cc406Sopenharmony_ci /* does not support gamma tables, we fill the table according to */ 2216141cc406Sopenharmony_ci /* the actual bit depth, i.e. 256 entries with a range of 0..255 */ 2217141cc406Sopenharmony_ci /* if the actual bit depth is 8, for example. This will hopefully*/ 2218141cc406Sopenharmony_ci /* make no trouble if the bit depth is 1. */ 2219141cc406Sopenharmony_ci if ( md->model_flags & MD_NO_GAMMA ) 2220141cc406Sopenharmony_ci { 2221141cc406Sopenharmony_ci tablesize = 4096; 2222141cc406Sopenharmony_ci option_size = (int) pow(2.0, (double) val[OPT_BITDEPTH].w ); 2223141cc406Sopenharmony_ci max_gamma_value = option_size - 1; 2224141cc406Sopenharmony_ci } 2225141cc406Sopenharmony_ci else 2226141cc406Sopenharmony_ci { 2227141cc406Sopenharmony_ci tablesize = md->max_lut_size; 2228141cc406Sopenharmony_ci option_size = tablesize; 2229141cc406Sopenharmony_ci max_gamma_value = md->max_lut_size - 1; 2230141cc406Sopenharmony_ci } 2231141cc406Sopenharmony_ci 2232141cc406Sopenharmony_ci for ( color = 0; color < 4; color++ ) 2233141cc406Sopenharmony_ci { 2234141cc406Sopenharmony_ci /* index 0 is used if bind gamma == true, index 1 to 3 */ 2235141cc406Sopenharmony_ci /* if bind gamma == false */ 2236141cc406Sopenharmony_ci if ( md->custom_gamma_table[color] ) 2237141cc406Sopenharmony_ci free((void *) md->custom_gamma_table[color]); 2238141cc406Sopenharmony_ci md->custom_gamma_table[color] = 2239141cc406Sopenharmony_ci (SANE_Int *) malloc(tablesize * sizeof(SANE_Int)); 2240141cc406Sopenharmony_ci DBG(100, "init_options: md->custom_gamma_table[%d]=%p, malloc'd %lu bytes\n", 2241141cc406Sopenharmony_ci color, (void *) md->custom_gamma_table[color], (u_long) (tablesize * sizeof(SANE_Int))); 2242141cc406Sopenharmony_ci if ( md->custom_gamma_table[color] == NULL ) 2243141cc406Sopenharmony_ci { 2244141cc406Sopenharmony_ci DBG(1, "init_options: malloc for custom gamma table failed\n"); 2245141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2246141cc406Sopenharmony_ci } 2247141cc406Sopenharmony_ci 2248141cc406Sopenharmony_ci for ( i = 0; i < max_gamma_value; i++ ) 2249141cc406Sopenharmony_ci md->custom_gamma_table[color][i] = i; 2250141cc406Sopenharmony_ci } 2251141cc406Sopenharmony_ci 2252141cc406Sopenharmony_ci md->custom_gamma_range.min = 0; 2253141cc406Sopenharmony_ci md->custom_gamma_range.max = max_gamma_value; 2254141cc406Sopenharmony_ci md->custom_gamma_range.quant = 1; 2255141cc406Sopenharmony_ci 2256141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].size = option_size * sizeof (SANE_Int); 2257141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].size = option_size * sizeof (SANE_Int); 2258141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].size = option_size * sizeof (SANE_Int); 2259141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].size = option_size * sizeof (SANE_Int); 2260141cc406Sopenharmony_ci 2261141cc406Sopenharmony_ci val[OPT_GAMMA_CUSTOM].wa = &md->custom_gamma_table[0][0]; 2262141cc406Sopenharmony_ci val[OPT_GAMMA_CUSTOM_R].wa = &md->custom_gamma_table[1][0]; 2263141cc406Sopenharmony_ci val[OPT_GAMMA_CUSTOM_G].wa = &md->custom_gamma_table[2][0]; 2264141cc406Sopenharmony_ci val[OPT_GAMMA_CUSTOM_B].wa = &md->custom_gamma_table[3][0]; 2265141cc406Sopenharmony_ci 2266141cc406Sopenharmony_ci /* Shadow, midtone, highlight, exposure time */ 2267141cc406Sopenharmony_ci md->channel_list[0] = (SANE_String) MD_CHANNEL_MASTER; 2268141cc406Sopenharmony_ci md->channel_list[1] = (SANE_String) MD_CHANNEL_RED; 2269141cc406Sopenharmony_ci md->channel_list[2] = (SANE_String) MD_CHANNEL_GREEN; 2270141cc406Sopenharmony_ci md->channel_list[3] = (SANE_String) MD_CHANNEL_BLUE; 2271141cc406Sopenharmony_ci md->channel_list[4] = NULL; 2272141cc406Sopenharmony_ci if ( val[OPT_CHANNEL].s ) 2273141cc406Sopenharmony_ci free((void *) val[OPT_CHANNEL].s); 2274141cc406Sopenharmony_ci val[OPT_CHANNEL].s = strdup(md->channel_list[0]); 2275141cc406Sopenharmony_ci val[OPT_SHADOW].w = MD_SHADOW_DEFAULT; 2276141cc406Sopenharmony_ci val[OPT_SHADOW_R].w = MD_SHADOW_DEFAULT; 2277141cc406Sopenharmony_ci val[OPT_SHADOW_G].w = MD_SHADOW_DEFAULT; 2278141cc406Sopenharmony_ci val[OPT_SHADOW_B].w = MD_SHADOW_DEFAULT; 2279141cc406Sopenharmony_ci val[OPT_MIDTONE].w = MD_MIDTONE_DEFAULT; 2280141cc406Sopenharmony_ci val[OPT_MIDTONE_R].w = MD_MIDTONE_DEFAULT; 2281141cc406Sopenharmony_ci val[OPT_MIDTONE_G].w = MD_MIDTONE_DEFAULT; 2282141cc406Sopenharmony_ci val[OPT_MIDTONE_B].w = MD_MIDTONE_DEFAULT; 2283141cc406Sopenharmony_ci val[OPT_HIGHLIGHT].w = MD_HIGHLIGHT_DEFAULT; 2284141cc406Sopenharmony_ci val[OPT_HIGHLIGHT_R].w = MD_HIGHLIGHT_DEFAULT; 2285141cc406Sopenharmony_ci val[OPT_HIGHLIGHT_G].w = MD_HIGHLIGHT_DEFAULT; 2286141cc406Sopenharmony_ci val[OPT_HIGHLIGHT_B].w = MD_HIGHLIGHT_DEFAULT; 2287141cc406Sopenharmony_ci val[OPT_EXPOSURE].w = MD_EXPOSURE_DEFAULT; 2288141cc406Sopenharmony_ci val[OPT_EXPOSURE_R].w = MD_EXPOSURE_DEFAULT; 2289141cc406Sopenharmony_ci val[OPT_EXPOSURE_G].w = MD_EXPOSURE_DEFAULT; 2290141cc406Sopenharmony_ci val[OPT_EXPOSURE_B].w = MD_EXPOSURE_DEFAULT; 2291141cc406Sopenharmony_ci 2292141cc406Sopenharmony_ci /* special options */ 2293141cc406Sopenharmony_ci val[OPT_RESOLUTION_BIND].w = SANE_TRUE; 2294141cc406Sopenharmony_ci 2295141cc406Sopenharmony_ci /* enable/disable option for backtracking */ 2296141cc406Sopenharmony_ci val[OPT_DISABLE_BACKTRACK].w = md->opt_no_backtrack_default; 2297141cc406Sopenharmony_ci 2298141cc406Sopenharmony_ci /* enable/disable calibration by backend */ 2299141cc406Sopenharmony_ci val[OPT_CALIB_BACKEND].w = md->opt_backend_calib_default; 2300141cc406Sopenharmony_ci 2301141cc406Sopenharmony_ci /* turn off the lamp during a scan */ 2302141cc406Sopenharmony_ci val[OPT_LIGHTLID35].w = SANE_FALSE; 2303141cc406Sopenharmony_ci 2304141cc406Sopenharmony_ci /* auto adjustment of threshold during a lineart scan */ 2305141cc406Sopenharmony_ci val[OPT_AUTOADJUST].w = SANE_FALSE; 2306141cc406Sopenharmony_ci 2307141cc406Sopenharmony_ci /* color balance (100% means no correction) */ 2308141cc406Sopenharmony_ci val[OPT_BALANCE_R].w = SANE_FIX(100); 2309141cc406Sopenharmony_ci val[OPT_BALANCE_G].w = SANE_FIX(100); 2310141cc406Sopenharmony_ci val[OPT_BALANCE_B].w = SANE_FIX(100); 2311141cc406Sopenharmony_ci 2312141cc406Sopenharmony_ci if ( first_call ) 2313141cc406Sopenharmony_ci { 2314141cc406Sopenharmony_ci /* initialize option descriptors and ranges */ 2315141cc406Sopenharmony_ci 2316141cc406Sopenharmony_ci /* Percentage range for brightness, contrast */ 2317141cc406Sopenharmony_ci md->percentage_range.min = 0 << SANE_FIXED_SCALE_SHIFT; 2318141cc406Sopenharmony_ci md->percentage_range.max = 200 << SANE_FIXED_SCALE_SHIFT; 2319141cc406Sopenharmony_ci md->percentage_range.quant = 1 << SANE_FIXED_SCALE_SHIFT; 2320141cc406Sopenharmony_ci 2321141cc406Sopenharmony_ci md->threshold_range.min = 1; 2322141cc406Sopenharmony_ci md->threshold_range.max = 255; 2323141cc406Sopenharmony_ci md->threshold_range.quant = 1; 2324141cc406Sopenharmony_ci 2325141cc406Sopenharmony_ci md->scalar_gamma_range.min = SANE_FIX(0.1); 2326141cc406Sopenharmony_ci md->scalar_gamma_range.max = SANE_FIX(4.0); 2327141cc406Sopenharmony_ci md->scalar_gamma_range.quant = SANE_FIX(0.1); 2328141cc406Sopenharmony_ci 2329141cc406Sopenharmony_ci md->shadow_range.min = 0; 2330141cc406Sopenharmony_ci md->shadow_range.max = 253; 2331141cc406Sopenharmony_ci md->shadow_range.quant = 1; 2332141cc406Sopenharmony_ci 2333141cc406Sopenharmony_ci md->midtone_range.min = 1; 2334141cc406Sopenharmony_ci md->midtone_range.max = 254; 2335141cc406Sopenharmony_ci md->midtone_range.quant = 1; 2336141cc406Sopenharmony_ci 2337141cc406Sopenharmony_ci md->highlight_range.min = 2; 2338141cc406Sopenharmony_ci md->highlight_range.max = 255; 2339141cc406Sopenharmony_ci md->highlight_range.quant = 1; 2340141cc406Sopenharmony_ci 2341141cc406Sopenharmony_ci md->exposure_range.min = 0; 2342141cc406Sopenharmony_ci md->exposure_range.max = 510; 2343141cc406Sopenharmony_ci md->exposure_range.quant = 2; 2344141cc406Sopenharmony_ci 2345141cc406Sopenharmony_ci md->balance_range.min = 0; 2346141cc406Sopenharmony_ci md->balance_range.max = 200 << SANE_FIXED_SCALE_SHIFT; 2347141cc406Sopenharmony_ci md->balance_range.quant = 1 << SANE_FIXED_SCALE_SHIFT; 2348141cc406Sopenharmony_ci 2349141cc406Sopenharmony_ci /* default for most options */ 2350141cc406Sopenharmony_ci for ( i = 0; i < NUM_OPTIONS; i++ ) 2351141cc406Sopenharmony_ci { 2352141cc406Sopenharmony_ci sod[i].type = SANE_TYPE_FIXED; 2353141cc406Sopenharmony_ci sod[i].unit = SANE_UNIT_NONE; 2354141cc406Sopenharmony_ci sod[i].size = sizeof(SANE_Fixed); 2355141cc406Sopenharmony_ci sod[i].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 2356141cc406Sopenharmony_ci sod[i].constraint_type = SANE_CONSTRAINT_RANGE; 2357141cc406Sopenharmony_ci } 2358141cc406Sopenharmony_ci 2359141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 2360141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2361141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2362141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2363141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].size = sizeof (SANE_Int); 2364141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2365141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; 2366141cc406Sopenharmony_ci val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* NUM_OPTIONS is no option */ 2367141cc406Sopenharmony_ci DBG(255, "sod=%p\n", (void *) sod); 2368141cc406Sopenharmony_ci DBG(255, "OPT_NUM_OPTS=%d\n", OPT_NUM_OPTS); 2369141cc406Sopenharmony_ci DBG(255, "SANE_CAP_SOFT_DETECT=%d\n", SANE_CAP_SOFT_DETECT); 2370141cc406Sopenharmony_ci DBG(255, "OPT_NUM_OPTS.cap=%d\n", sod[0].cap); 2371141cc406Sopenharmony_ci 2372141cc406Sopenharmony_ci /* The Scan Mode Group */ 2373141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].title = M_TITLE_SCANMODEGRP; 2374141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 2375141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].size = 0; 2376141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].desc = ""; 2377141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].cap = 0; 2378141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2379141cc406Sopenharmony_ci 2380141cc406Sopenharmony_ci /* Scan source */ 2381141cc406Sopenharmony_ci sod[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 2382141cc406Sopenharmony_ci sod[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 2383141cc406Sopenharmony_ci sod[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 2384141cc406Sopenharmony_ci sod[OPT_SOURCE].type = SANE_TYPE_STRING; 2385141cc406Sopenharmony_ci sod[OPT_SOURCE].size = max_string_size(md->scansource_list); 2386141cc406Sopenharmony_ci /* if there is only one scan source, deactivate option */ 2387141cc406Sopenharmony_ci if ( md->scansource_list[1] == NULL ) 2388141cc406Sopenharmony_ci sod[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; 2389141cc406Sopenharmony_ci sod[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2390141cc406Sopenharmony_ci sod[OPT_SOURCE].constraint.string_list = md->scansource_list; 2391141cc406Sopenharmony_ci 2392141cc406Sopenharmony_ci /* Scan mode */ 2393141cc406Sopenharmony_ci sod[OPT_MODE].name = SANE_NAME_SCAN_MODE; 2394141cc406Sopenharmony_ci sod[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 2395141cc406Sopenharmony_ci sod[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 2396141cc406Sopenharmony_ci sod[OPT_MODE].type = SANE_TYPE_STRING; 2397141cc406Sopenharmony_ci sod[OPT_MODE].size = max_string_size(md->scanmode_list); 2398141cc406Sopenharmony_ci sod[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2399141cc406Sopenharmony_ci sod[OPT_MODE].constraint.string_list = md->scanmode_list; 2400141cc406Sopenharmony_ci 2401141cc406Sopenharmony_ci /* Bit depth */ 2402141cc406Sopenharmony_ci sod[OPT_BITDEPTH].name = SANE_NAME_BIT_DEPTH; 2403141cc406Sopenharmony_ci sod[OPT_BITDEPTH].title = SANE_TITLE_BIT_DEPTH; 2404141cc406Sopenharmony_ci sod[OPT_BITDEPTH].desc = SANE_DESC_BIT_DEPTH; 2405141cc406Sopenharmony_ci sod[OPT_BITDEPTH].type = SANE_TYPE_INT; 2406141cc406Sopenharmony_ci sod[OPT_BITDEPTH].unit = SANE_UNIT_BIT; 2407141cc406Sopenharmony_ci sod[OPT_BITDEPTH].size = sizeof(SANE_Int); 2408141cc406Sopenharmony_ci /* if we have only 8 bit color deactivate this option */ 2409141cc406Sopenharmony_ci if ( md->bitdepth_list[0] == 1 ) 2410141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; 2411141cc406Sopenharmony_ci sod[OPT_BITDEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2412141cc406Sopenharmony_ci sod[OPT_BITDEPTH].constraint.word_list = md->bitdepth_list; 2413141cc406Sopenharmony_ci 2414141cc406Sopenharmony_ci /* Halftone */ 2415141cc406Sopenharmony_ci sod[OPT_HALFTONE].name = SANE_NAME_HALFTONE; 2416141cc406Sopenharmony_ci sod[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; 2417141cc406Sopenharmony_ci sod[OPT_HALFTONE].desc = SANE_DESC_HALFTONE; 2418141cc406Sopenharmony_ci sod[OPT_HALFTONE].type = SANE_TYPE_STRING; 2419141cc406Sopenharmony_ci sod[OPT_HALFTONE].size = max_string_size(md->halftone_mode_list); 2420141cc406Sopenharmony_ci sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 2421141cc406Sopenharmony_ci sod[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2422141cc406Sopenharmony_ci sod[OPT_HALFTONE].constraint.string_list = md->halftone_mode_list; 2423141cc406Sopenharmony_ci 2424141cc406Sopenharmony_ci /* Resolution */ 2425141cc406Sopenharmony_ci sod[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 2426141cc406Sopenharmony_ci sod[OPT_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION; 2427141cc406Sopenharmony_ci sod[OPT_RESOLUTION].desc = SANE_DESC_SCAN_X_RESOLUTION; 2428141cc406Sopenharmony_ci sod[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 2429141cc406Sopenharmony_ci sod[OPT_RESOLUTION].constraint.range = &md->x_res_range_dpi; 2430141cc406Sopenharmony_ci 2431141cc406Sopenharmony_ci sod[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION; 2432141cc406Sopenharmony_ci sod[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION; 2433141cc406Sopenharmony_ci sod[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION; 2434141cc406Sopenharmony_ci sod[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; 2435141cc406Sopenharmony_ci sod[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; 2436141cc406Sopenharmony_ci sod[OPT_Y_RESOLUTION].constraint.range = &md->y_res_range_dpi; 2437141cc406Sopenharmony_ci 2438141cc406Sopenharmony_ci /* Preview */ 2439141cc406Sopenharmony_ci sod[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 2440141cc406Sopenharmony_ci sod[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 2441141cc406Sopenharmony_ci sod[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 2442141cc406Sopenharmony_ci sod[OPT_PREVIEW].type = SANE_TYPE_BOOL; 2443141cc406Sopenharmony_ci sod[OPT_PREVIEW].size = sizeof(SANE_Bool); 2444141cc406Sopenharmony_ci sod[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; 2445141cc406Sopenharmony_ci 2446141cc406Sopenharmony_ci /* Geometry group, for scan area selection */ 2447141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].title = M_TITLE_GEOMGRP; 2448141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 2449141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].size = 0; 2450141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].desc = ""; 2451141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 2452141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2453141cc406Sopenharmony_ci 2454141cc406Sopenharmony_ci sod[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 2455141cc406Sopenharmony_ci sod[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 2456141cc406Sopenharmony_ci sod[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 2457141cc406Sopenharmony_ci sod[OPT_TL_X].unit = SANE_UNIT_MM; 2458141cc406Sopenharmony_ci sod[OPT_TL_X].constraint.range = &md->x_range_mm; 2459141cc406Sopenharmony_ci 2460141cc406Sopenharmony_ci sod[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 2461141cc406Sopenharmony_ci sod[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 2462141cc406Sopenharmony_ci sod[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 2463141cc406Sopenharmony_ci sod[OPT_TL_Y].unit = SANE_UNIT_MM; 2464141cc406Sopenharmony_ci sod[OPT_TL_Y].constraint.range = &md->y_range_mm; 2465141cc406Sopenharmony_ci 2466141cc406Sopenharmony_ci sod[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 2467141cc406Sopenharmony_ci sod[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 2468141cc406Sopenharmony_ci sod[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 2469141cc406Sopenharmony_ci sod[OPT_BR_X].unit = SANE_UNIT_MM; 2470141cc406Sopenharmony_ci sod[OPT_BR_X].constraint.range = &md->x_range_mm; 2471141cc406Sopenharmony_ci 2472141cc406Sopenharmony_ci sod[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 2473141cc406Sopenharmony_ci sod[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 2474141cc406Sopenharmony_ci sod[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 2475141cc406Sopenharmony_ci sod[OPT_BR_Y].unit = SANE_UNIT_MM; 2476141cc406Sopenharmony_ci sod[OPT_BR_Y].constraint.range = &md->y_range_mm; 2477141cc406Sopenharmony_ci 2478141cc406Sopenharmony_ci /* Enhancement group */ 2479141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].title = M_TITLE_ENHANCEGRP; 2480141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 2481141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].desc = ""; 2482141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].size = 0; 2483141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].cap = 0; 2484141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2485141cc406Sopenharmony_ci 2486141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 2487141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 2488141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 2489141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; 2490141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].constraint.range = &md->percentage_range; 2491141cc406Sopenharmony_ci 2492141cc406Sopenharmony_ci sod[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 2493141cc406Sopenharmony_ci sod[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 2494141cc406Sopenharmony_ci sod[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 2495141cc406Sopenharmony_ci sod[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; 2496141cc406Sopenharmony_ci sod[OPT_CONTRAST].constraint.range = &md->percentage_range; 2497141cc406Sopenharmony_ci 2498141cc406Sopenharmony_ci sod[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 2499141cc406Sopenharmony_ci sod[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 2500141cc406Sopenharmony_ci sod[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 2501141cc406Sopenharmony_ci sod[OPT_THRESHOLD].type = SANE_TYPE_INT; 2502141cc406Sopenharmony_ci sod[OPT_THRESHOLD].size = sizeof(SANE_Int); 2503141cc406Sopenharmony_ci sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2504141cc406Sopenharmony_ci sod[OPT_THRESHOLD].constraint.range = &md->threshold_range; 2505141cc406Sopenharmony_ci 2506141cc406Sopenharmony_ci /* automatically adjust threshold for a lineart scan */ 2507141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].name = M_NAME_AUTOADJUST; 2508141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].title = M_TITLE_AUTOADJUST; 2509141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].desc = M_DESC_AUTOADJUST; 2510141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].type = SANE_TYPE_BOOL; 2511141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].size = sizeof(SANE_Bool); 2512141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].constraint_type = SANE_CONSTRAINT_NONE; 2513141cc406Sopenharmony_ci if ( strncmp(md->opts.auto_adjust, "off", 3) == 0 ) 2514141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; 2515141cc406Sopenharmony_ci 2516141cc406Sopenharmony_ci /* Gamma */ 2517141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].title = "Gamma"; 2518141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].desc = ""; 2519141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].type = SANE_TYPE_GROUP; 2520141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].size = 0; 2521141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].cap = 0; 2522141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2523141cc406Sopenharmony_ci 2524141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].name = M_NAME_GAMMA_MODE; 2525141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].title = M_TITLE_GAMMA_MODE; 2526141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].desc = M_DESC_GAMMA_MODE; 2527141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].type = SANE_TYPE_STRING; 2528141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].size = max_string_size(md->gammamode_list); 2529141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2530141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].constraint.string_list = md->gammamode_list; 2531141cc406Sopenharmony_ci 2532141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].name = M_NAME_GAMMA_BIND; 2533141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].title = M_TITLE_GAMMA_BIND; 2534141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].desc = M_DESC_GAMMA_BIND; 2535141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL; 2536141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].size = sizeof(SANE_Bool); 2537141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].constraint_type = SANE_CONSTRAINT_NONE; 2538141cc406Sopenharmony_ci 2539141cc406Sopenharmony_ci /* this is active if gamma_bind == true and gammamode == scalar */ 2540141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].name = M_NAME_GAMMA_SCALAR; 2541141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].title = M_TITLE_GAMMA_SCALAR; 2542141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].desc = M_DESC_GAMMA_SCALAR; 2543141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 2544141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].constraint.range = &md->scalar_gamma_range; 2545141cc406Sopenharmony_ci 2546141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].name = M_NAME_GAMMA_SCALAR_R; 2547141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].title = M_TITLE_GAMMA_SCALAR_R; 2548141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].desc = M_DESC_GAMMA_SCALAR_R; 2549141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; 2550141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].constraint.range = &md->scalar_gamma_range; 2551141cc406Sopenharmony_ci 2552141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].name = M_NAME_GAMMA_SCALAR_G; 2553141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].title = M_TITLE_GAMMA_SCALAR_G; 2554141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].desc = M_DESC_GAMMA_SCALAR_G; 2555141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; 2556141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].constraint.range = &md->scalar_gamma_range; 2557141cc406Sopenharmony_ci 2558141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].name = M_NAME_GAMMA_SCALAR_B; 2559141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].title = M_TITLE_GAMMA_SCALAR_B; 2560141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].desc = M_DESC_GAMMA_SCALAR_B; 2561141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; 2562141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].constraint.range = &md->scalar_gamma_range; 2563141cc406Sopenharmony_ci 2564141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].name = SANE_NAME_GAMMA_VECTOR; 2565141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].title = SANE_TITLE_GAMMA_VECTOR; 2566141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].desc = SANE_DESC_GAMMA_VECTOR; 2567141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].type = SANE_TYPE_INT; 2568141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 2569141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].size = option_size * sizeof (SANE_Int); 2570141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].constraint.range = &md->custom_gamma_range; 2571141cc406Sopenharmony_ci 2572141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].name = SANE_NAME_GAMMA_VECTOR_R; 2573141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].title = SANE_TITLE_GAMMA_VECTOR_R; 2574141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].desc = SANE_DESC_GAMMA_VECTOR_R; 2575141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].type = SANE_TYPE_INT; 2576141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; 2577141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].size = option_size * sizeof (SANE_Int); 2578141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].constraint.range = &md->custom_gamma_range; 2579141cc406Sopenharmony_ci 2580141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].name = SANE_NAME_GAMMA_VECTOR_G; 2581141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].title = SANE_TITLE_GAMMA_VECTOR_G; 2582141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].desc = SANE_DESC_GAMMA_VECTOR_G; 2583141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].type = SANE_TYPE_INT; 2584141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; 2585141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].size = option_size * sizeof (SANE_Int); 2586141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].constraint.range = &md->custom_gamma_range; 2587141cc406Sopenharmony_ci 2588141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].name = SANE_NAME_GAMMA_VECTOR_B; 2589141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].title = SANE_TITLE_GAMMA_VECTOR_B; 2590141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].desc = SANE_DESC_GAMMA_VECTOR_B; 2591141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].type = SANE_TYPE_INT; 2592141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; 2593141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].size = option_size * sizeof (SANE_Int); 2594141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].constraint.range = &md->custom_gamma_range; 2595141cc406Sopenharmony_ci 2596141cc406Sopenharmony_ci /* Shadow, midtone, highlight */ 2597141cc406Sopenharmony_ci sod[OPT_SMH_GROUP].title = M_TITLE_SMHGRP; 2598141cc406Sopenharmony_ci sod[OPT_SMH_GROUP].desc = ""; 2599141cc406Sopenharmony_ci sod[OPT_SMH_GROUP].type = SANE_TYPE_GROUP; 2600141cc406Sopenharmony_ci sod[OPT_SMH_GROUP].size = 0; 2601141cc406Sopenharmony_ci sod[OPT_SMH_GROUP].cap = 0; 2602141cc406Sopenharmony_ci sod[OPT_SMH_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2603141cc406Sopenharmony_ci 2604141cc406Sopenharmony_ci sod[OPT_CHANNEL].name = M_NAME_CHANNEL; 2605141cc406Sopenharmony_ci sod[OPT_CHANNEL].title = M_TITLE_CHANNEL; 2606141cc406Sopenharmony_ci sod[OPT_CHANNEL].desc = M_DESC_CHANNEL; 2607141cc406Sopenharmony_ci sod[OPT_CHANNEL].type = SANE_TYPE_STRING; 2608141cc406Sopenharmony_ci sod[OPT_CHANNEL].size = max_string_size(md->channel_list); 2609141cc406Sopenharmony_ci sod[OPT_CHANNEL].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2610141cc406Sopenharmony_ci sod[OPT_CHANNEL].constraint.string_list = md->channel_list; 2611141cc406Sopenharmony_ci 2612141cc406Sopenharmony_ci sod[OPT_SHADOW].name = SANE_NAME_SHADOW; 2613141cc406Sopenharmony_ci sod[OPT_SHADOW].title = SANE_TITLE_SHADOW; 2614141cc406Sopenharmony_ci sod[OPT_SHADOW].desc = SANE_DESC_SHADOW; 2615141cc406Sopenharmony_ci sod[OPT_SHADOW].type = SANE_TYPE_INT; 2616141cc406Sopenharmony_ci sod[OPT_SHADOW].size = sizeof(SANE_Int); 2617141cc406Sopenharmony_ci sod[OPT_SHADOW].constraint.range = &md->shadow_range; 2618141cc406Sopenharmony_ci 2619141cc406Sopenharmony_ci sod[OPT_SHADOW_R].name = SANE_NAME_SHADOW_R; 2620141cc406Sopenharmony_ci sod[OPT_SHADOW_R].title = SANE_TITLE_SHADOW_R; 2621141cc406Sopenharmony_ci sod[OPT_SHADOW_R].desc = SANE_DESC_SHADOW_R; 2622141cc406Sopenharmony_ci sod[OPT_SHADOW_R].type = SANE_TYPE_INT; 2623141cc406Sopenharmony_ci sod[OPT_SHADOW_R].size = sizeof(SANE_Int); 2624141cc406Sopenharmony_ci sod[OPT_SHADOW_R].constraint.range = &md->shadow_range; 2625141cc406Sopenharmony_ci 2626141cc406Sopenharmony_ci sod[OPT_SHADOW_G].name = SANE_NAME_SHADOW_G; 2627141cc406Sopenharmony_ci sod[OPT_SHADOW_G].title = SANE_TITLE_SHADOW_G; 2628141cc406Sopenharmony_ci sod[OPT_SHADOW_G].desc = SANE_DESC_SHADOW_G; 2629141cc406Sopenharmony_ci sod[OPT_SHADOW_G].type = SANE_TYPE_INT; 2630141cc406Sopenharmony_ci sod[OPT_SHADOW_G].size = sizeof(SANE_Int); 2631141cc406Sopenharmony_ci sod[OPT_SHADOW_G].constraint.range = &md->shadow_range; 2632141cc406Sopenharmony_ci 2633141cc406Sopenharmony_ci sod[OPT_SHADOW_B].name = SANE_NAME_SHADOW_B; 2634141cc406Sopenharmony_ci sod[OPT_SHADOW_B].title = SANE_TITLE_SHADOW_B; 2635141cc406Sopenharmony_ci sod[OPT_SHADOW_B].desc = SANE_DESC_SHADOW_B; 2636141cc406Sopenharmony_ci sod[OPT_SHADOW_B].type = SANE_TYPE_INT; 2637141cc406Sopenharmony_ci sod[OPT_SHADOW_B].size = sizeof(SANE_Int); 2638141cc406Sopenharmony_ci sod[OPT_SHADOW_B].constraint.range = &md->shadow_range; 2639141cc406Sopenharmony_ci 2640141cc406Sopenharmony_ci sod[OPT_MIDTONE].name = M_NAME_MIDTONE; 2641141cc406Sopenharmony_ci sod[OPT_MIDTONE].title = M_TITLE_MIDTONE; 2642141cc406Sopenharmony_ci sod[OPT_MIDTONE].desc = M_DESC_MIDTONE; 2643141cc406Sopenharmony_ci sod[OPT_MIDTONE].type = SANE_TYPE_INT; 2644141cc406Sopenharmony_ci sod[OPT_MIDTONE].size = sizeof(SANE_Int); 2645141cc406Sopenharmony_ci sod[OPT_MIDTONE].constraint.range = &md->midtone_range; 2646141cc406Sopenharmony_ci 2647141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].name = M_NAME_MIDTONE_R; 2648141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].title = M_TITLE_MIDTONE_R; 2649141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].desc = M_DESC_MIDTONE_R; 2650141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].type = SANE_TYPE_INT; 2651141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].size = sizeof(SANE_Int); 2652141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].constraint.range = &md->midtone_range; 2653141cc406Sopenharmony_ci 2654141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].name = M_NAME_MIDTONE_G; 2655141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].title = M_TITLE_MIDTONE_G; 2656141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].desc = M_DESC_MIDTONE_G; 2657141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].type = SANE_TYPE_INT; 2658141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].size = sizeof(SANE_Int); 2659141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].constraint.range = &md->midtone_range; 2660141cc406Sopenharmony_ci 2661141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].name = M_NAME_MIDTONE_B; 2662141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].title = M_TITLE_MIDTONE_B; 2663141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].desc = M_DESC_MIDTONE_B; 2664141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].type = SANE_TYPE_INT; 2665141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].size = sizeof(SANE_Int); 2666141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].constraint.range = &md->midtone_range; 2667141cc406Sopenharmony_ci 2668141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].name = SANE_NAME_HIGHLIGHT; 2669141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].title = SANE_TITLE_HIGHLIGHT; 2670141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].desc = SANE_DESC_HIGHLIGHT; 2671141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].type = SANE_TYPE_INT; 2672141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].size = sizeof(SANE_Int); 2673141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].constraint.range = &md->highlight_range; 2674141cc406Sopenharmony_ci 2675141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].name = SANE_NAME_HIGHLIGHT_R; 2676141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].title = SANE_TITLE_HIGHLIGHT_R; 2677141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].desc = SANE_DESC_HIGHLIGHT_R; 2678141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].type = SANE_TYPE_INT; 2679141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].size = sizeof(SANE_Int); 2680141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].constraint.range = &md->highlight_range; 2681141cc406Sopenharmony_ci 2682141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].name = SANE_NAME_HIGHLIGHT_G; 2683141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].title = SANE_TITLE_HIGHLIGHT_G; 2684141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].desc = SANE_DESC_HIGHLIGHT_G; 2685141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].type = SANE_TYPE_INT; 2686141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].size = sizeof(SANE_Int); 2687141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].constraint.range = &md->highlight_range; 2688141cc406Sopenharmony_ci 2689141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].name = SANE_NAME_HIGHLIGHT_B; 2690141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].title = SANE_TITLE_HIGHLIGHT_B; 2691141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].desc = SANE_DESC_HIGHLIGHT_B; 2692141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].type = SANE_TYPE_INT; 2693141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].size = sizeof(SANE_Int); 2694141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].constraint.range = &md->highlight_range; 2695141cc406Sopenharmony_ci 2696141cc406Sopenharmony_ci sod[OPT_EXPOSURE].name = SANE_NAME_SCAN_EXPOS_TIME; 2697141cc406Sopenharmony_ci sod[OPT_EXPOSURE].title = SANE_TITLE_SCAN_EXPOS_TIME; 2698141cc406Sopenharmony_ci sod[OPT_EXPOSURE].desc = SANE_DESC_SCAN_EXPOS_TIME; 2699141cc406Sopenharmony_ci sod[OPT_EXPOSURE].type = SANE_TYPE_INT; 2700141cc406Sopenharmony_ci sod[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; 2701141cc406Sopenharmony_ci sod[OPT_EXPOSURE].size = sizeof(SANE_Int); 2702141cc406Sopenharmony_ci sod[OPT_EXPOSURE].constraint.range = &md->exposure_range; 2703141cc406Sopenharmony_ci 2704141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].name = SANE_NAME_SCAN_EXPOS_TIME_R; 2705141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].title = SANE_TITLE_SCAN_EXPOS_TIME_R; 2706141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].desc = SANE_DESC_SCAN_EXPOS_TIME_R; 2707141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].type = SANE_TYPE_INT; 2708141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].unit = SANE_UNIT_PERCENT; 2709141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].size = sizeof(SANE_Int); 2710141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].constraint.range = &md->exposure_range; 2711141cc406Sopenharmony_ci 2712141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].name = SANE_NAME_SCAN_EXPOS_TIME_G; 2713141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].title = SANE_TITLE_SCAN_EXPOS_TIME_G; 2714141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].desc = SANE_DESC_SCAN_EXPOS_TIME_G; 2715141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].type = SANE_TYPE_INT; 2716141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].unit = SANE_UNIT_PERCENT; 2717141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].size = sizeof(SANE_Int); 2718141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].constraint.range = &md->exposure_range; 2719141cc406Sopenharmony_ci 2720141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].name = SANE_NAME_SCAN_EXPOS_TIME_B; 2721141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].title = SANE_TITLE_SCAN_EXPOS_TIME_B; 2722141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].desc = SANE_DESC_SCAN_EXPOS_TIME_B; 2723141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].type = SANE_TYPE_INT; 2724141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].unit = SANE_UNIT_PERCENT; 2725141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].size = sizeof(SANE_Int); 2726141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].constraint.range = &md->exposure_range; 2727141cc406Sopenharmony_ci 2728141cc406Sopenharmony_ci /* The Special Options Group */ 2729141cc406Sopenharmony_ci sod[OPT_SPECIAL].title = M_TITLE_SPECIALGRP; 2730141cc406Sopenharmony_ci sod[OPT_SPECIAL].type = SANE_TYPE_GROUP; 2731141cc406Sopenharmony_ci sod[OPT_SPECIAL].size = 0; 2732141cc406Sopenharmony_ci sod[OPT_SPECIAL].desc = ""; 2733141cc406Sopenharmony_ci sod[OPT_SPECIAL].cap = SANE_CAP_ADVANCED; 2734141cc406Sopenharmony_ci sod[OPT_SPECIAL].constraint_type = SANE_CONSTRAINT_NONE; 2735141cc406Sopenharmony_ci 2736141cc406Sopenharmony_ci sod[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND; 2737141cc406Sopenharmony_ci sod[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND; 2738141cc406Sopenharmony_ci sod[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND; 2739141cc406Sopenharmony_ci sod[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL; 2740141cc406Sopenharmony_ci sod[OPT_RESOLUTION_BIND].size = sizeof(SANE_Bool); 2741141cc406Sopenharmony_ci sod[OPT_RESOLUTION_BIND].cap |= SANE_CAP_ADVANCED; 2742141cc406Sopenharmony_ci sod[OPT_RESOLUTION_BIND].constraint_type = SANE_CONSTRAINT_NONE; 2743141cc406Sopenharmony_ci 2744141cc406Sopenharmony_ci /* enable/disable option for backtracking */ 2745141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].name = M_NAME_NOBACKTRACK; 2746141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].title = M_TITLE_NOBACKTRACK; 2747141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].desc = M_DESC_NOBACKTRACK; 2748141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].type = SANE_TYPE_BOOL; 2749141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].size = sizeof(SANE_Bool); 2750141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].cap |= SANE_CAP_ADVANCED; 2751141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].constraint_type = SANE_CONSTRAINT_NONE; 2752141cc406Sopenharmony_ci if ( strncmp(md->opts.no_backtracking, "off", 3) == 0 ) 2753141cc406Sopenharmony_ci sod[OPT_DISABLE_BACKTRACK].cap |= SANE_CAP_INACTIVE; 2754141cc406Sopenharmony_ci 2755141cc406Sopenharmony_ci /* calibration by driver */ 2756141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].name = M_NAME_CALIBBACKEND; 2757141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].title = M_TITLE_CALIBBACKEND; 2758141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].desc = M_DESC_CALIBBACKEND; 2759141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].type = SANE_TYPE_BOOL; 2760141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].size = sizeof(SANE_Bool); 2761141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].cap |= SANE_CAP_ADVANCED; 2762141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].constraint_type = SANE_CONSTRAINT_NONE; 2763141cc406Sopenharmony_ci if ( strncmp(md->opts.backend_calibration, "off", 3) == 0 ) 2764141cc406Sopenharmony_ci sod[OPT_CALIB_BACKEND].cap |= SANE_CAP_INACTIVE; 2765141cc406Sopenharmony_ci 2766141cc406Sopenharmony_ci /* turn off the lamp of the flatbed during a scan */ 2767141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].name = M_NAME_LIGHTLID35; 2768141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].title = M_TITLE_LIGHTLID35; 2769141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].desc = M_DESC_LIGHTLID35; 2770141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].type = SANE_TYPE_BOOL; 2771141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].size = sizeof(SANE_Bool); 2772141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].cap |= SANE_CAP_ADVANCED; 2773141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].constraint_type = SANE_CONSTRAINT_NONE; 2774141cc406Sopenharmony_ci if ( strncmp(md->opts.lightlid35, "off", 3) == 0 ) 2775141cc406Sopenharmony_ci sod[OPT_LIGHTLID35].cap |= SANE_CAP_INACTIVE; 2776141cc406Sopenharmony_ci 2777141cc406Sopenharmony_ci /* toggle the lamp of the flatbed */ 2778141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].name = M_NAME_TOGGLELAMP; 2779141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].title = M_TITLE_TOGGLELAMP; 2780141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].desc = M_DESC_TOGGLELAMP; 2781141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].type = SANE_TYPE_BUTTON; 2782141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].size = 0; 2783141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].cap |= SANE_CAP_ADVANCED; 2784141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].constraint_type = SANE_CONSTRAINT_NONE; 2785141cc406Sopenharmony_ci if ( strncmp(md->opts.toggle_lamp, "off", 3) == 0 ) 2786141cc406Sopenharmony_ci sod[OPT_TOGGLELAMP].cap |= SANE_CAP_INACTIVE; 2787141cc406Sopenharmony_ci 2788141cc406Sopenharmony_ci /* color balance */ 2789141cc406Sopenharmony_ci sod[OPT_COLORBALANCE].title = M_TITLE_COLBALANCEGRP; 2790141cc406Sopenharmony_ci sod[OPT_COLORBALANCE].type = SANE_TYPE_GROUP; 2791141cc406Sopenharmony_ci sod[OPT_COLORBALANCE].size = 0; 2792141cc406Sopenharmony_ci sod[OPT_COLORBALANCE].desc = ""; 2793141cc406Sopenharmony_ci sod[OPT_COLORBALANCE].cap = SANE_CAP_ADVANCED; 2794141cc406Sopenharmony_ci sod[OPT_COLORBALANCE].constraint_type = SANE_CONSTRAINT_NONE; 2795141cc406Sopenharmony_ci 2796141cc406Sopenharmony_ci sod[OPT_BALANCE_R].name = M_NAME_BALANCE_R; 2797141cc406Sopenharmony_ci sod[OPT_BALANCE_R].title = M_TITLE_BALANCE_R; 2798141cc406Sopenharmony_ci sod[OPT_BALANCE_R].desc = M_DESC_BALANCE_R; 2799141cc406Sopenharmony_ci sod[OPT_BALANCE_R].unit = SANE_UNIT_PERCENT; 2800141cc406Sopenharmony_ci sod[OPT_BALANCE_R].cap |= SANE_CAP_ADVANCED; 2801141cc406Sopenharmony_ci sod[OPT_BALANCE_R].constraint.range = &md->balance_range; 2802141cc406Sopenharmony_ci if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) 2803141cc406Sopenharmony_ci sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; 2804141cc406Sopenharmony_ci 2805141cc406Sopenharmony_ci sod[OPT_BALANCE_G].name = M_NAME_BALANCE_G; 2806141cc406Sopenharmony_ci sod[OPT_BALANCE_G].title = M_TITLE_BALANCE_G; 2807141cc406Sopenharmony_ci sod[OPT_BALANCE_G].desc = M_DESC_BALANCE_G; 2808141cc406Sopenharmony_ci sod[OPT_BALANCE_G].unit = SANE_UNIT_PERCENT; 2809141cc406Sopenharmony_ci sod[OPT_BALANCE_G].cap |= SANE_CAP_ADVANCED; 2810141cc406Sopenharmony_ci sod[OPT_BALANCE_G].constraint.range = &md->balance_range; 2811141cc406Sopenharmony_ci if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) 2812141cc406Sopenharmony_ci sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; 2813141cc406Sopenharmony_ci 2814141cc406Sopenharmony_ci sod[OPT_BALANCE_B].name = M_NAME_BALANCE_B; 2815141cc406Sopenharmony_ci sod[OPT_BALANCE_B].title = M_TITLE_BALANCE_B; 2816141cc406Sopenharmony_ci sod[OPT_BALANCE_B].desc = M_DESC_BALANCE_B; 2817141cc406Sopenharmony_ci sod[OPT_BALANCE_B].unit = SANE_UNIT_PERCENT; 2818141cc406Sopenharmony_ci sod[OPT_BALANCE_B].cap |= SANE_CAP_ADVANCED; 2819141cc406Sopenharmony_ci sod[OPT_BALANCE_B].constraint.range = &md->balance_range; 2820141cc406Sopenharmony_ci if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) 2821141cc406Sopenharmony_ci sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; 2822141cc406Sopenharmony_ci 2823141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].name = M_NAME_BALANCE_FW; 2824141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].title = M_TITLE_BALANCE_FW; 2825141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].desc = M_DESC_BALANCE_FW; 2826141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].type = SANE_TYPE_BUTTON; 2827141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].size = 0; 2828141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].cap |= SANE_CAP_ADVANCED; 2829141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].constraint_type = SANE_CONSTRAINT_NONE; 2830141cc406Sopenharmony_ci if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) 2831141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; 2832141cc406Sopenharmony_ci } 2833141cc406Sopenharmony_ci 2834141cc406Sopenharmony_ci status = set_option_dependencies(ms, sod, val); 2835141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 2836141cc406Sopenharmony_ci return status; 2837141cc406Sopenharmony_ci 2838141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2839141cc406Sopenharmony_ci} 2840141cc406Sopenharmony_ci 2841141cc406Sopenharmony_ci/*---------- set_option_dependencies() ---------------------------------------*/ 2842141cc406Sopenharmony_ci 2843141cc406Sopenharmony_cistatic SANE_Status 2844141cc406Sopenharmony_ciset_option_dependencies(Microtek2_Scanner *ms, SANE_Option_Descriptor *sod, 2845141cc406Sopenharmony_ci Option_Value *val) 2846141cc406Sopenharmony_ci{ 2847141cc406Sopenharmony_ci 2848141cc406Sopenharmony_ci Microtek2_Device *md; 2849141cc406Sopenharmony_ci md = ms->dev; 2850141cc406Sopenharmony_ci 2851141cc406Sopenharmony_ci DBG(40, "set_option_dependencies: val=%p, sod=%p, mode=%s\n", 2852141cc406Sopenharmony_ci (void *) val, (void *) sod, val[OPT_MODE].s); 2853141cc406Sopenharmony_ci 2854141cc406Sopenharmony_ci if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 ) 2855141cc406Sopenharmony_ci { 2856141cc406Sopenharmony_ci /* activate brightness,..., deactivate halftone pattern */ 2857141cc406Sopenharmony_ci /* and threshold */ 2858141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 2859141cc406Sopenharmony_ci sod[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 2860141cc406Sopenharmony_ci sod[OPT_CHANNEL].cap &= ~SANE_CAP_INACTIVE; 2861141cc406Sopenharmony_ci sod[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; 2862141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap &= ~SANE_CAP_INACTIVE; 2863141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; 2864141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 2865141cc406Sopenharmony_ci sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 2866141cc406Sopenharmony_ci sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2867141cc406Sopenharmony_ci if ( md->bitdepth_list[0] != 1 ) 2868141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap &= ~SANE_CAP_INACTIVE; 2869141cc406Sopenharmony_ci else 2870141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; 2871141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; 2872141cc406Sopenharmony_ci if ( ! ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) ) 2873141cc406Sopenharmony_ci { 2874141cc406Sopenharmony_ci sod[OPT_BALANCE_R].cap &= ~SANE_CAP_INACTIVE; 2875141cc406Sopenharmony_ci sod[OPT_BALANCE_G].cap &= ~SANE_CAP_INACTIVE; 2876141cc406Sopenharmony_ci sod[OPT_BALANCE_B].cap &= ~SANE_CAP_INACTIVE; 2877141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].cap &= ~SANE_CAP_INACTIVE; 2878141cc406Sopenharmony_ci } 2879141cc406Sopenharmony_ci /* reset options values that are inactive to their default */ 2880141cc406Sopenharmony_ci val[OPT_THRESHOLD].w = MD_THRESHOLD_DEFAULT; 2881141cc406Sopenharmony_ci } 2882141cc406Sopenharmony_ci 2883141cc406Sopenharmony_ci else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) 2884141cc406Sopenharmony_ci { 2885141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; 2886141cc406Sopenharmony_ci sod[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; 2887141cc406Sopenharmony_ci sod[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE; 2888141cc406Sopenharmony_ci sod[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; 2889141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap &= ~SANE_CAP_INACTIVE; 2890141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; 2891141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 2892141cc406Sopenharmony_ci sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 2893141cc406Sopenharmony_ci sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2894141cc406Sopenharmony_ci if ( md->bitdepth_list[0] != 1 ) 2895141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap &= ~SANE_CAP_INACTIVE; 2896141cc406Sopenharmony_ci else 2897141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; 2898141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; 2899141cc406Sopenharmony_ci sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; 2900141cc406Sopenharmony_ci sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; 2901141cc406Sopenharmony_ci sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; 2902141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; 2903141cc406Sopenharmony_ci 2904141cc406Sopenharmony_ci /* reset options values that are inactive to their default */ 2905141cc406Sopenharmony_ci if ( val[OPT_CHANNEL].s ) 2906141cc406Sopenharmony_ci free((void *) val[OPT_CHANNEL].s); 2907141cc406Sopenharmony_ci val[OPT_CHANNEL].s = strdup((SANE_String) MD_CHANNEL_MASTER); 2908141cc406Sopenharmony_ci } 2909141cc406Sopenharmony_ci 2910141cc406Sopenharmony_ci else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0 ) 2911141cc406Sopenharmony_ci { 2912141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2913141cc406Sopenharmony_ci sod[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 2914141cc406Sopenharmony_ci sod[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE; 2915141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; 2916141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; 2917141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; 2918141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 2919141cc406Sopenharmony_ci sod[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; 2920141cc406Sopenharmony_ci sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2921141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; 2922141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; 2923141cc406Sopenharmony_ci sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; 2924141cc406Sopenharmony_ci sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; 2925141cc406Sopenharmony_ci sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; 2926141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; 2927141cc406Sopenharmony_ci 2928141cc406Sopenharmony_ci /* reset options values that are inactive to their default */ 2929141cc406Sopenharmony_ci val[OPT_BRIGHTNESS].w = MD_BRIGHTNESS_DEFAULT; 2930141cc406Sopenharmony_ci val[OPT_CONTRAST].w = MD_CONTRAST_DEFAULT; 2931141cc406Sopenharmony_ci if ( val[OPT_CHANNEL].s ) 2932141cc406Sopenharmony_ci free((void *) val[OPT_CHANNEL].s); 2933141cc406Sopenharmony_ci val[OPT_CHANNEL].s = strdup((SANE_String) MD_CHANNEL_MASTER); 2934141cc406Sopenharmony_ci val[OPT_SHADOW].w = MD_SHADOW_DEFAULT; 2935141cc406Sopenharmony_ci val[OPT_MIDTONE].w = MD_MIDTONE_DEFAULT; 2936141cc406Sopenharmony_ci val[OPT_HIGHLIGHT].w = MD_HIGHLIGHT_DEFAULT; 2937141cc406Sopenharmony_ci val[OPT_EXPOSURE].w = MD_EXPOSURE_DEFAULT; 2938141cc406Sopenharmony_ci val[OPT_THRESHOLD].w = MD_THRESHOLD_DEFAULT; 2939141cc406Sopenharmony_ci } 2940141cc406Sopenharmony_ci 2941141cc406Sopenharmony_ci else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_LINEART) == 0 ) 2942141cc406Sopenharmony_ci { 2943141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; 2944141cc406Sopenharmony_ci sod[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 2945141cc406Sopenharmony_ci sod[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE; 2946141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; 2947141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; 2948141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; 2949141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 2950141cc406Sopenharmony_ci sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; 2951141cc406Sopenharmony_ci if ( val[OPT_AUTOADJUST].w == SANE_FALSE ) 2952141cc406Sopenharmony_ci sod[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 2953141cc406Sopenharmony_ci else 2954141cc406Sopenharmony_ci sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2955141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; 2956141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].cap &= ~SANE_CAP_INACTIVE; 2957141cc406Sopenharmony_ci sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; 2958141cc406Sopenharmony_ci sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; 2959141cc406Sopenharmony_ci sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; 2960141cc406Sopenharmony_ci sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; 2961141cc406Sopenharmony_ci 2962141cc406Sopenharmony_ci /* reset options values that are inactive to their default */ 2963141cc406Sopenharmony_ci val[OPT_BRIGHTNESS].w = MD_BRIGHTNESS_DEFAULT; 2964141cc406Sopenharmony_ci val[OPT_CONTRAST].w = MD_CONTRAST_DEFAULT; 2965141cc406Sopenharmony_ci if ( val[OPT_CHANNEL].s ) 2966141cc406Sopenharmony_ci free((void *) val[OPT_CHANNEL].s); 2967141cc406Sopenharmony_ci val[OPT_CHANNEL].s = strdup((SANE_String) MD_CHANNEL_MASTER); 2968141cc406Sopenharmony_ci val[OPT_SHADOW].w = MD_SHADOW_DEFAULT; 2969141cc406Sopenharmony_ci val[OPT_MIDTONE].w = MD_MIDTONE_DEFAULT; 2970141cc406Sopenharmony_ci val[OPT_HIGHLIGHT].w = MD_HIGHLIGHT_DEFAULT; 2971141cc406Sopenharmony_ci val[OPT_EXPOSURE].w = MD_EXPOSURE_DEFAULT; 2972141cc406Sopenharmony_ci } 2973141cc406Sopenharmony_ci 2974141cc406Sopenharmony_ci else 2975141cc406Sopenharmony_ci { 2976141cc406Sopenharmony_ci DBG(1, "set_option_dependencies: unknown mode '%s'\n", 2977141cc406Sopenharmony_ci val[OPT_MODE].s ); 2978141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2979141cc406Sopenharmony_ci } 2980141cc406Sopenharmony_ci 2981141cc406Sopenharmony_ci /* these ones are always inactive if the mode changes */ 2982141cc406Sopenharmony_ci sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; 2983141cc406Sopenharmony_ci sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; 2984141cc406Sopenharmony_ci sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; 2985141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; 2986141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; 2987141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; 2988141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; 2989141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; 2990141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; 2991141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; 2992141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; 2993141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; 2994141cc406Sopenharmony_ci 2995141cc406Sopenharmony_ci /* reset options values that are inactive to their default */ 2996141cc406Sopenharmony_ci val[OPT_SHADOW_R].w = val[OPT_SHADOW_G].w = val[OPT_SHADOW_B].w 2997141cc406Sopenharmony_ci = MD_SHADOW_DEFAULT; 2998141cc406Sopenharmony_ci val[OPT_MIDTONE_R].w = val[OPT_MIDTONE_G].w = val[OPT_MIDTONE_B].w 2999141cc406Sopenharmony_ci = MD_MIDTONE_DEFAULT; 3000141cc406Sopenharmony_ci val[OPT_HIGHLIGHT_R].w = val[OPT_HIGHLIGHT_G].w = val[OPT_HIGHLIGHT_B].w 3001141cc406Sopenharmony_ci = MD_HIGHLIGHT_DEFAULT; 3002141cc406Sopenharmony_ci val[OPT_EXPOSURE_R].w = val[OPT_EXPOSURE_G].w = val[OPT_EXPOSURE_B].w 3003141cc406Sopenharmony_ci = MD_EXPOSURE_DEFAULT; 3004141cc406Sopenharmony_ci 3005141cc406Sopenharmony_ci if ( SANE_OPTION_IS_SETTABLE(sod[OPT_GAMMA_MODE].cap) ) 3006141cc406Sopenharmony_ci { 3007141cc406Sopenharmony_ci restore_gamma_options(sod, val); 3008141cc406Sopenharmony_ci } 3009141cc406Sopenharmony_ci 3010141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3011141cc406Sopenharmony_ci} 3012141cc406Sopenharmony_ci 3013141cc406Sopenharmony_ci/*---------- sane_control_option() -------------------------------------------*/ 3014141cc406Sopenharmony_ci 3015141cc406Sopenharmony_ciSANE_Status 3016141cc406Sopenharmony_cisane_control_option(SANE_Handle handle, SANE_Int option, 3017141cc406Sopenharmony_ci SANE_Action action, void *value, SANE_Int *info) 3018141cc406Sopenharmony_ci{ 3019141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 3020141cc406Sopenharmony_ci Microtek2_Device *md; 3021141cc406Sopenharmony_ci Microtek2_Info *mi; 3022141cc406Sopenharmony_ci Option_Value *val; 3023141cc406Sopenharmony_ci SANE_Option_Descriptor *sod; 3024141cc406Sopenharmony_ci SANE_Status status; 3025141cc406Sopenharmony_ci 3026141cc406Sopenharmony_ci md = ms->dev; 3027141cc406Sopenharmony_ci val = &ms->val[0]; 3028141cc406Sopenharmony_ci sod = &ms->sod[0]; 3029141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 3030141cc406Sopenharmony_ci 3031141cc406Sopenharmony_ci if ( ms->scanning ) 3032141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 3033141cc406Sopenharmony_ci 3034141cc406Sopenharmony_ci if ( option < 0 || option >= NUM_OPTIONS ) 3035141cc406Sopenharmony_ci { 3036141cc406Sopenharmony_ci DBG(100, "sane_control_option: option %d; action %d \n", option, action); 3037141cc406Sopenharmony_ci DBG(10, "sane_control_option: option %d invalid\n", option); 3038141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3039141cc406Sopenharmony_ci } 3040141cc406Sopenharmony_ci 3041141cc406Sopenharmony_ci if ( ! SANE_OPTION_IS_ACTIVE(ms->sod[option].cap) ) 3042141cc406Sopenharmony_ci { 3043141cc406Sopenharmony_ci DBG(100, "sane_control_option: option %d; action %d \n", option, action); 3044141cc406Sopenharmony_ci DBG(10, "sane_control_option: option %d not active\n", option); 3045141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3046141cc406Sopenharmony_ci } 3047141cc406Sopenharmony_ci 3048141cc406Sopenharmony_ci if ( info ) 3049141cc406Sopenharmony_ci *info = 0; 3050141cc406Sopenharmony_ci 3051141cc406Sopenharmony_ci switch ( action ) 3052141cc406Sopenharmony_ci { 3053141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: /* read out option values */ 3054141cc406Sopenharmony_ci switch ( option ) 3055141cc406Sopenharmony_ci { 3056141cc406Sopenharmony_ci /* word options */ 3057141cc406Sopenharmony_ci case OPT_BITDEPTH: 3058141cc406Sopenharmony_ci case OPT_RESOLUTION: 3059141cc406Sopenharmony_ci case OPT_Y_RESOLUTION: 3060141cc406Sopenharmony_ci case OPT_THRESHOLD: 3061141cc406Sopenharmony_ci case OPT_TL_X: 3062141cc406Sopenharmony_ci case OPT_TL_Y: 3063141cc406Sopenharmony_ci case OPT_BR_X: 3064141cc406Sopenharmony_ci case OPT_BR_Y: 3065141cc406Sopenharmony_ci case OPT_PREVIEW: 3066141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3067141cc406Sopenharmony_ci case OPT_CONTRAST: 3068141cc406Sopenharmony_ci case OPT_SHADOW: 3069141cc406Sopenharmony_ci case OPT_SHADOW_R: 3070141cc406Sopenharmony_ci case OPT_SHADOW_G: 3071141cc406Sopenharmony_ci case OPT_SHADOW_B: 3072141cc406Sopenharmony_ci case OPT_MIDTONE: 3073141cc406Sopenharmony_ci case OPT_MIDTONE_R: 3074141cc406Sopenharmony_ci case OPT_MIDTONE_G: 3075141cc406Sopenharmony_ci case OPT_MIDTONE_B: 3076141cc406Sopenharmony_ci case OPT_HIGHLIGHT: 3077141cc406Sopenharmony_ci case OPT_HIGHLIGHT_R: 3078141cc406Sopenharmony_ci case OPT_HIGHLIGHT_G: 3079141cc406Sopenharmony_ci case OPT_HIGHLIGHT_B: 3080141cc406Sopenharmony_ci case OPT_EXPOSURE: 3081141cc406Sopenharmony_ci case OPT_EXPOSURE_R: 3082141cc406Sopenharmony_ci case OPT_EXPOSURE_G: 3083141cc406Sopenharmony_ci case OPT_EXPOSURE_B: 3084141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR: 3085141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR_R: 3086141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR_G: 3087141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR_B: 3088141cc406Sopenharmony_ci case OPT_BALANCE_R: 3089141cc406Sopenharmony_ci case OPT_BALANCE_G: 3090141cc406Sopenharmony_ci case OPT_BALANCE_B: 3091141cc406Sopenharmony_ci 3092141cc406Sopenharmony_ci *(SANE_Word *) value = val[option].w; 3093141cc406Sopenharmony_ci 3094141cc406Sopenharmony_ci if (sod[option].type == SANE_TYPE_FIXED ) 3095141cc406Sopenharmony_ci DBG(50, "sane_control_option: opt=%d, act=%d, val=%f\n", 3096141cc406Sopenharmony_ci option, action, SANE_UNFIX(val[option].w)); 3097141cc406Sopenharmony_ci else 3098141cc406Sopenharmony_ci DBG(50, "sane_control_option: opt=%d, act=%d, val=%d\n", 3099141cc406Sopenharmony_ci option, action, val[option].w); 3100141cc406Sopenharmony_ci 3101141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3102141cc406Sopenharmony_ci 3103141cc406Sopenharmony_ci /* boolean options */ 3104141cc406Sopenharmony_ci case OPT_RESOLUTION_BIND: 3105141cc406Sopenharmony_ci case OPT_DISABLE_BACKTRACK: 3106141cc406Sopenharmony_ci case OPT_CALIB_BACKEND: 3107141cc406Sopenharmony_ci case OPT_LIGHTLID35: 3108141cc406Sopenharmony_ci case OPT_GAMMA_BIND: 3109141cc406Sopenharmony_ci case OPT_AUTOADJUST: 3110141cc406Sopenharmony_ci *(SANE_Bool *) value = val[option].w; 3111141cc406Sopenharmony_ci DBG(50, "sane_control_option: opt=%d, act=%d, val=%d\n", 3112141cc406Sopenharmony_ci option, action, val[option].w); 3113141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3114141cc406Sopenharmony_ci 3115141cc406Sopenharmony_ci /* string options */ 3116141cc406Sopenharmony_ci case OPT_SOURCE: 3117141cc406Sopenharmony_ci case OPT_MODE: 3118141cc406Sopenharmony_ci case OPT_HALFTONE: 3119141cc406Sopenharmony_ci case OPT_CHANNEL: 3120141cc406Sopenharmony_ci case OPT_GAMMA_MODE: 3121141cc406Sopenharmony_ci strcpy(value, val[option].s); 3122141cc406Sopenharmony_ci DBG(50, "sane_control_option: opt=%d, act=%d, val=%s\n", 3123141cc406Sopenharmony_ci option, action, val[option].s); 3124141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3125141cc406Sopenharmony_ci 3126141cc406Sopenharmony_ci /* word array options */ 3127141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM: 3128141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM_R: 3129141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM_G: 3130141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM_B: 3131141cc406Sopenharmony_ci memcpy(value, val[option].wa, sod[option].size); 3132141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3133141cc406Sopenharmony_ci 3134141cc406Sopenharmony_ci /* button options */ 3135141cc406Sopenharmony_ci case OPT_TOGGLELAMP: 3136141cc406Sopenharmony_ci case OPT_BALANCE_FW: 3137141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3138141cc406Sopenharmony_ci 3139141cc406Sopenharmony_ci /* others */ 3140141cc406Sopenharmony_ci case OPT_NUM_OPTS: 3141141cc406Sopenharmony_ci *(SANE_Word *) value = NUM_OPTIONS; 3142141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3143141cc406Sopenharmony_ci 3144141cc406Sopenharmony_ci default: 3145141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 3146141cc406Sopenharmony_ci } 3147141cc406Sopenharmony_ci /* NOTREACHED */ 3148141cc406Sopenharmony_ci /* break; */ 3149141cc406Sopenharmony_ci 3150141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: /* set option values */ 3151141cc406Sopenharmony_ci if ( ! SANE_OPTION_IS_SETTABLE(sod[option].cap) ) 3152141cc406Sopenharmony_ci { 3153141cc406Sopenharmony_ci DBG(100, "sane_control_option: option %d; action %d \n", 3154141cc406Sopenharmony_ci option, action); 3155141cc406Sopenharmony_ci DBG(10, "sane_control_option: trying to set unsettable option\n"); 3156141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3157141cc406Sopenharmony_ci } 3158141cc406Sopenharmony_ci 3159141cc406Sopenharmony_ci /* do not check OPT_BR_Y, xscanimage sometimes tries to set */ 3160141cc406Sopenharmony_ci /* it to a too large value; bug in xscanimage ? */ 3161141cc406Sopenharmony_ci /* if ( option != OPT_BR_Y ) 3162141cc406Sopenharmony_ci { */ 3163141cc406Sopenharmony_ci status = sanei_constrain_value(ms->sod + option, value, info); 3164141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3165141cc406Sopenharmony_ci { 3166141cc406Sopenharmony_ci DBG(10, "sane_control_option: invalid option value\n"); 3167141cc406Sopenharmony_ci return status; 3168141cc406Sopenharmony_ci } 3169141cc406Sopenharmony_ci /* } */ 3170141cc406Sopenharmony_ci 3171141cc406Sopenharmony_ci switch ( sod[option].type ) 3172141cc406Sopenharmony_ci { 3173141cc406Sopenharmony_ci case SANE_TYPE_BOOL: 3174141cc406Sopenharmony_ci DBG(50, "sane_control_option: option=%d, action=%d, value=%d\n", 3175141cc406Sopenharmony_ci option, action, *(SANE_Int *) value); 3176141cc406Sopenharmony_ci if ( ! ( ( *(SANE_Bool *) value == SANE_TRUE ) 3177141cc406Sopenharmony_ci || ( *(SANE_Bool *) value == SANE_FALSE ) ) ) 3178141cc406Sopenharmony_ci { 3179141cc406Sopenharmony_ci DBG(10, "sane_control_option: invalid BOOL option value\n"); 3180141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3181141cc406Sopenharmony_ci } 3182141cc406Sopenharmony_ci if ( val[option].w == *(SANE_Bool *) value ) /* no change */ 3183141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3184141cc406Sopenharmony_ci val[option].w = *(SANE_Bool *) value; 3185141cc406Sopenharmony_ci break; 3186141cc406Sopenharmony_ci 3187141cc406Sopenharmony_ci case SANE_TYPE_INT: 3188141cc406Sopenharmony_ci if ( sod[option].size == sizeof(SANE_Int) ) 3189141cc406Sopenharmony_ci { 3190141cc406Sopenharmony_ci /* word option */ 3191141cc406Sopenharmony_ci DBG(50, "sane_control_option: option=%d, action=%d, " 3192141cc406Sopenharmony_ci "value=%d\n", option, action, *(SANE_Int *) value); 3193141cc406Sopenharmony_ci if ( val[option].w == *(SANE_Int *) value ) /* no change */ 3194141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3195141cc406Sopenharmony_ci val[option].w = *(SANE_Int *) value; 3196141cc406Sopenharmony_ci } 3197141cc406Sopenharmony_ci else 3198141cc406Sopenharmony_ci { 3199141cc406Sopenharmony_ci /* word array option */ 3200141cc406Sopenharmony_ci memcpy(val[option].wa, value, sod[option].size); 3201141cc406Sopenharmony_ci } 3202141cc406Sopenharmony_ci break; 3203141cc406Sopenharmony_ci 3204141cc406Sopenharmony_ci case SANE_TYPE_FIXED: 3205141cc406Sopenharmony_ci DBG(50, "sane_control_option: option=%d, action=%d, value=%f\n", 3206141cc406Sopenharmony_ci option, action, SANE_UNFIX( *(SANE_Fixed *) value)); 3207141cc406Sopenharmony_ci if ( val[option].w == *(SANE_Fixed *) value ) /* no change */ 3208141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3209141cc406Sopenharmony_ci val[option].w = *(SANE_Fixed *) value; 3210141cc406Sopenharmony_ci break; 3211141cc406Sopenharmony_ci 3212141cc406Sopenharmony_ci case SANE_TYPE_STRING: 3213141cc406Sopenharmony_ci DBG(50, "sane_control_option: option=%d, action=%d, value=%s\n", 3214141cc406Sopenharmony_ci option, action, (SANE_String) value); 3215141cc406Sopenharmony_ci if ( strcmp(val[option].s, (SANE_String) value) == 0 ) 3216141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 3217141cc406Sopenharmony_ci if ( val[option].s ) 3218141cc406Sopenharmony_ci free((void *) val[option].s); 3219141cc406Sopenharmony_ci val[option].s = strdup(value); 3220141cc406Sopenharmony_ci if ( val[option].s == NULL ) 3221141cc406Sopenharmony_ci { 3222141cc406Sopenharmony_ci DBG(1, "sane_control_option: strdup failed\n"); 3223141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3224141cc406Sopenharmony_ci } 3225141cc406Sopenharmony_ci break; 3226141cc406Sopenharmony_ci 3227141cc406Sopenharmony_ci case SANE_TYPE_BUTTON: 3228141cc406Sopenharmony_ci break; 3229141cc406Sopenharmony_ci 3230141cc406Sopenharmony_ci default: 3231141cc406Sopenharmony_ci DBG(1, "sane_control_option: unknown type %d\n", 3232141cc406Sopenharmony_ci sod[option].type); 3233141cc406Sopenharmony_ci break; 3234141cc406Sopenharmony_ci } 3235141cc406Sopenharmony_ci 3236141cc406Sopenharmony_ci switch ( option ) 3237141cc406Sopenharmony_ci { 3238141cc406Sopenharmony_ci case OPT_RESOLUTION: 3239141cc406Sopenharmony_ci case OPT_Y_RESOLUTION: 3240141cc406Sopenharmony_ci case OPT_TL_X: 3241141cc406Sopenharmony_ci case OPT_TL_Y: 3242141cc406Sopenharmony_ci case OPT_BR_X: 3243141cc406Sopenharmony_ci case OPT_BR_Y: 3244141cc406Sopenharmony_ci if ( info ) 3245141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3246141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3247141cc406Sopenharmony_ci case OPT_DISABLE_BACKTRACK: 3248141cc406Sopenharmony_ci case OPT_CALIB_BACKEND: 3249141cc406Sopenharmony_ci case OPT_LIGHTLID35: 3250141cc406Sopenharmony_ci case OPT_PREVIEW: 3251141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3252141cc406Sopenharmony_ci case OPT_THRESHOLD: 3253141cc406Sopenharmony_ci case OPT_CONTRAST: 3254141cc406Sopenharmony_ci case OPT_EXPOSURE: 3255141cc406Sopenharmony_ci case OPT_EXPOSURE_R: 3256141cc406Sopenharmony_ci case OPT_EXPOSURE_G: 3257141cc406Sopenharmony_ci case OPT_EXPOSURE_B: 3258141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR: 3259141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR_R: 3260141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR_G: 3261141cc406Sopenharmony_ci case OPT_GAMMA_SCALAR_B: 3262141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM: 3263141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM_R: 3264141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM_G: 3265141cc406Sopenharmony_ci case OPT_GAMMA_CUSTOM_B: 3266141cc406Sopenharmony_ci case OPT_HALFTONE: 3267141cc406Sopenharmony_ci case OPT_BALANCE_R: 3268141cc406Sopenharmony_ci case OPT_BALANCE_G: 3269141cc406Sopenharmony_ci case OPT_BALANCE_B: 3270141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3271141cc406Sopenharmony_ci 3272141cc406Sopenharmony_ci case OPT_BITDEPTH: 3273141cc406Sopenharmony_ci /* If the bitdepth has changed we must change the size of */ 3274141cc406Sopenharmony_ci /* the gamma table if the device does not support gamma */ 3275141cc406Sopenharmony_ci /* tables. This will hopefully cause no trouble if the */ 3276141cc406Sopenharmony_ci /* mode is one bit */ 3277141cc406Sopenharmony_ci 3278141cc406Sopenharmony_ci if ( md->model_flags & MD_NO_GAMMA ) 3279141cc406Sopenharmony_ci { 3280141cc406Sopenharmony_ci int max_gamma_value; 3281141cc406Sopenharmony_ci int size; 3282141cc406Sopenharmony_ci int color; 3283141cc406Sopenharmony_ci int i; 3284141cc406Sopenharmony_ci 3285141cc406Sopenharmony_ci size = (int) pow(2.0, (double) val[OPT_BITDEPTH].w) - 1; 3286141cc406Sopenharmony_ci max_gamma_value = size - 1; 3287141cc406Sopenharmony_ci for ( color = 0; color < 4; color++ ) 3288141cc406Sopenharmony_ci { 3289141cc406Sopenharmony_ci for ( i = 0; i < max_gamma_value; i++ ) 3290141cc406Sopenharmony_ci md->custom_gamma_table[color][i] = (SANE_Int) i; 3291141cc406Sopenharmony_ci } 3292141cc406Sopenharmony_ci md->custom_gamma_range.max = (SANE_Int) max_gamma_value; 3293141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].size = size * sizeof (SANE_Int); 3294141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].size = size * sizeof (SANE_Int); 3295141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].size = size * sizeof (SANE_Int); 3296141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].size = size * sizeof (SANE_Int); 3297141cc406Sopenharmony_ci 3298141cc406Sopenharmony_ci if ( info ) 3299141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3300141cc406Sopenharmony_ci 3301141cc406Sopenharmony_ci } 3302141cc406Sopenharmony_ci 3303141cc406Sopenharmony_ci if ( info ) 3304141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3305141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3306141cc406Sopenharmony_ci 3307141cc406Sopenharmony_ci case OPT_SOURCE: 3308141cc406Sopenharmony_ci if ( info ) 3309141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 3310141cc406Sopenharmony_ci if ( strcmp(val[option].s, MD_SOURCESTRING_FLATBED) == 0 ) 3311141cc406Sopenharmony_ci md->scan_source = MD_SOURCE_FLATBED; 3312141cc406Sopenharmony_ci else if ( strcmp(val[option].s, MD_SOURCESTRING_TMA) == 0 ) 3313141cc406Sopenharmony_ci md->scan_source = MD_SOURCE_TMA; 3314141cc406Sopenharmony_ci else if ( strcmp(val[option].s, MD_SOURCESTRING_ADF) == 0 ) 3315141cc406Sopenharmony_ci md->scan_source = MD_SOURCE_ADF; 3316141cc406Sopenharmony_ci else if ( strcmp(val[option].s, MD_SOURCESTRING_STRIPE) == 0 ) 3317141cc406Sopenharmony_ci md->scan_source = MD_SOURCE_STRIPE; 3318141cc406Sopenharmony_ci else if ( strcmp(val[option].s, MD_SOURCESTRING_SLIDE) == 0 ) 3319141cc406Sopenharmony_ci md->scan_source = MD_SOURCE_SLIDE; 3320141cc406Sopenharmony_ci else 3321141cc406Sopenharmony_ci { 3322141cc406Sopenharmony_ci DBG(1, "sane_control_option: unsupported option %s\n", 3323141cc406Sopenharmony_ci val[option].s); 3324141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 3325141cc406Sopenharmony_ci } 3326141cc406Sopenharmony_ci 3327141cc406Sopenharmony_ci init_options(ms, md->scan_source); 3328141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3329141cc406Sopenharmony_ci 3330141cc406Sopenharmony_ci case OPT_MODE: 3331141cc406Sopenharmony_ci if ( info ) 3332141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 3333141cc406Sopenharmony_ci 3334141cc406Sopenharmony_ci status = set_option_dependencies(ms, sod, val); 3335141cc406Sopenharmony_ci 3336141cc406Sopenharmony_ci /* Options with side effects need special treatment. They are */ 3337141cc406Sopenharmony_ci /* reset, even if they were set by set_option_dependencies(): */ 3338141cc406Sopenharmony_ci /* if we have more than one color depth activate this option */ 3339141cc406Sopenharmony_ci 3340141cc406Sopenharmony_ci if ( md->bitdepth_list[0] == 1 ) 3341141cc406Sopenharmony_ci sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; 3342141cc406Sopenharmony_ci if ( strncmp(md->opts.auto_adjust, "off", 3) == 0 ) 3343141cc406Sopenharmony_ci sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; 3344141cc406Sopenharmony_ci 3345141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 3346141cc406Sopenharmony_ci return status; 3347141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3348141cc406Sopenharmony_ci 3349141cc406Sopenharmony_ci case OPT_CHANNEL: 3350141cc406Sopenharmony_ci if ( info ) 3351141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3352141cc406Sopenharmony_ci if ( strcmp(val[option].s, MD_CHANNEL_MASTER) == 0 ) 3353141cc406Sopenharmony_ci { 3354141cc406Sopenharmony_ci sod[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; 3355141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap &= ~SANE_CAP_INACTIVE; 3356141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; 3357141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; 3358141cc406Sopenharmony_ci sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; 3359141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; 3360141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; 3361141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; 3362141cc406Sopenharmony_ci sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; 3363141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; 3364141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; 3365141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; 3366141cc406Sopenharmony_ci sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; 3367141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; 3368141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; 3369141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; 3370141cc406Sopenharmony_ci } 3371141cc406Sopenharmony_ci else if ( strcmp(val[option].s, MD_CHANNEL_RED) == 0 ) 3372141cc406Sopenharmony_ci { 3373141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; 3374141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; 3375141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; 3376141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3377141cc406Sopenharmony_ci sod[OPT_SHADOW_R].cap &= ~SANE_CAP_INACTIVE; 3378141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].cap &= ~SANE_CAP_INACTIVE; 3379141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].cap &= ~SANE_CAP_INACTIVE; 3380141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].cap &= ~SANE_CAP_INACTIVE; 3381141cc406Sopenharmony_ci sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; 3382141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; 3383141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; 3384141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; 3385141cc406Sopenharmony_ci sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; 3386141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; 3387141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; 3388141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; 3389141cc406Sopenharmony_ci } 3390141cc406Sopenharmony_ci else if ( strcmp(val[option].s, MD_CHANNEL_GREEN) == 0 ) 3391141cc406Sopenharmony_ci { 3392141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; 3393141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; 3394141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; 3395141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3396141cc406Sopenharmony_ci sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; 3397141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; 3398141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; 3399141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; 3400141cc406Sopenharmony_ci sod[OPT_SHADOW_G].cap &= ~SANE_CAP_INACTIVE; 3401141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].cap &= ~SANE_CAP_INACTIVE; 3402141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].cap &= ~SANE_CAP_INACTIVE; 3403141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].cap &= ~SANE_CAP_INACTIVE; 3404141cc406Sopenharmony_ci sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; 3405141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; 3406141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; 3407141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; 3408141cc406Sopenharmony_ci } 3409141cc406Sopenharmony_ci else if ( strcmp(val[option].s, MD_CHANNEL_BLUE) == 0 ) 3410141cc406Sopenharmony_ci { 3411141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; 3412141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; 3413141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; 3414141cc406Sopenharmony_ci sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; 3415141cc406Sopenharmony_ci sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; 3416141cc406Sopenharmony_ci sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; 3417141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; 3418141cc406Sopenharmony_ci sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; 3419141cc406Sopenharmony_ci sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; 3420141cc406Sopenharmony_ci sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; 3421141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; 3422141cc406Sopenharmony_ci sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; 3423141cc406Sopenharmony_ci sod[OPT_SHADOW_B].cap &= ~SANE_CAP_INACTIVE; 3424141cc406Sopenharmony_ci sod[OPT_MIDTONE_B].cap &= ~SANE_CAP_INACTIVE; 3425141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT_B].cap &= ~SANE_CAP_INACTIVE; 3426141cc406Sopenharmony_ci sod[OPT_EXPOSURE_B].cap &= ~SANE_CAP_INACTIVE; 3427141cc406Sopenharmony_ci } 3428141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3429141cc406Sopenharmony_ci 3430141cc406Sopenharmony_ci case OPT_GAMMA_MODE: 3431141cc406Sopenharmony_ci restore_gamma_options(sod, val); 3432141cc406Sopenharmony_ci if ( info ) 3433141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3434141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3435141cc406Sopenharmony_ci 3436141cc406Sopenharmony_ci case OPT_GAMMA_BIND: 3437141cc406Sopenharmony_ci restore_gamma_options(sod, val); 3438141cc406Sopenharmony_ci if ( info ) 3439141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3440141cc406Sopenharmony_ci 3441141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3442141cc406Sopenharmony_ci 3443141cc406Sopenharmony_ci case OPT_SHADOW: 3444141cc406Sopenharmony_ci case OPT_SHADOW_R: 3445141cc406Sopenharmony_ci case OPT_SHADOW_G: 3446141cc406Sopenharmony_ci case OPT_SHADOW_B: 3447141cc406Sopenharmony_ci if ( val[option].w >= val[option + 1].w ) 3448141cc406Sopenharmony_ci { 3449141cc406Sopenharmony_ci val[option + 1].w = val[option].w + 1; 3450141cc406Sopenharmony_ci if ( info ) 3451141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3452141cc406Sopenharmony_ci } 3453141cc406Sopenharmony_ci if ( val[option + 1].w >= val[option + 2].w ) 3454141cc406Sopenharmony_ci val[option + 2].w = val[option + 1].w + 1; 3455141cc406Sopenharmony_ci 3456141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3457141cc406Sopenharmony_ci 3458141cc406Sopenharmony_ci case OPT_MIDTONE: 3459141cc406Sopenharmony_ci case OPT_MIDTONE_R: 3460141cc406Sopenharmony_ci case OPT_MIDTONE_G: 3461141cc406Sopenharmony_ci case OPT_MIDTONE_B: 3462141cc406Sopenharmony_ci if ( val[option].w <= val[option - 1].w ) 3463141cc406Sopenharmony_ci { 3464141cc406Sopenharmony_ci val[option - 1].w = val[option].w - 1; 3465141cc406Sopenharmony_ci if ( info ) 3466141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3467141cc406Sopenharmony_ci } 3468141cc406Sopenharmony_ci if ( val[option].w >= val[option + 1].w ) 3469141cc406Sopenharmony_ci { 3470141cc406Sopenharmony_ci val[option + 1].w = val[option].w + 1; 3471141cc406Sopenharmony_ci if ( info ) 3472141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3473141cc406Sopenharmony_ci } 3474141cc406Sopenharmony_ci 3475141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3476141cc406Sopenharmony_ci 3477141cc406Sopenharmony_ci case OPT_HIGHLIGHT: 3478141cc406Sopenharmony_ci case OPT_HIGHLIGHT_R: 3479141cc406Sopenharmony_ci case OPT_HIGHLIGHT_G: 3480141cc406Sopenharmony_ci case OPT_HIGHLIGHT_B: 3481141cc406Sopenharmony_ci if ( val[option].w <= val[option - 1].w ) 3482141cc406Sopenharmony_ci { 3483141cc406Sopenharmony_ci val[option - 1].w = val[option].w - 1; 3484141cc406Sopenharmony_ci if ( info ) 3485141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3486141cc406Sopenharmony_ci } 3487141cc406Sopenharmony_ci if ( val[option - 1].w <= val[option - 2].w ) 3488141cc406Sopenharmony_ci val[option - 2].w = val[option - 1].w - 1; 3489141cc406Sopenharmony_ci 3490141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3491141cc406Sopenharmony_ci 3492141cc406Sopenharmony_ci case OPT_RESOLUTION_BIND: 3493141cc406Sopenharmony_ci if ( ms->val[option].w == SANE_FALSE ) 3494141cc406Sopenharmony_ci { 3495141cc406Sopenharmony_ci ms->sod[OPT_Y_RESOLUTION].cap &= ~SANE_CAP_INACTIVE; 3496141cc406Sopenharmony_ci } 3497141cc406Sopenharmony_ci else 3498141cc406Sopenharmony_ci { 3499141cc406Sopenharmony_ci ms->sod[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; 3500141cc406Sopenharmony_ci } 3501141cc406Sopenharmony_ci if ( info ) 3502141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3503141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3504141cc406Sopenharmony_ci 3505141cc406Sopenharmony_ci case OPT_TOGGLELAMP: 3506141cc406Sopenharmony_ci status = scsi_read_system_status(md, -1); 3507141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 3508141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 3509141cc406Sopenharmony_ci 3510141cc406Sopenharmony_ci md->status.flamp ^= 1; 3511141cc406Sopenharmony_ci status = scsi_send_system_status(md, -1); 3512141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 3513141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 3514141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3515141cc406Sopenharmony_ci 3516141cc406Sopenharmony_ci case OPT_AUTOADJUST: 3517141cc406Sopenharmony_ci if ( info ) 3518141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3519141cc406Sopenharmony_ci 3520141cc406Sopenharmony_ci if ( ms->val[option].w == SANE_FALSE ) 3521141cc406Sopenharmony_ci ms->sod[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 3522141cc406Sopenharmony_ci else 3523141cc406Sopenharmony_ci ms->sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 3524141cc406Sopenharmony_ci 3525141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3526141cc406Sopenharmony_ci 3527141cc406Sopenharmony_ci case OPT_BALANCE_FW: 3528141cc406Sopenharmony_ci val[OPT_BALANCE_R].w = 3529141cc406Sopenharmony_ci SANE_FIX((uint8_t)( (float)mi->balance[0] / 2.55 ) ); 3530141cc406Sopenharmony_ci val[OPT_BALANCE_G].w = 3531141cc406Sopenharmony_ci SANE_FIX((uint8_t)( (float)mi->balance[1] / 2.55 ) ); 3532141cc406Sopenharmony_ci val[OPT_BALANCE_B].w = 3533141cc406Sopenharmony_ci SANE_FIX((uint8_t)( (float)mi->balance[2] / 2.55 ) ); 3534141cc406Sopenharmony_ci if ( info ) 3535141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 3536141cc406Sopenharmony_ci 3537141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3538141cc406Sopenharmony_ci 3539141cc406Sopenharmony_ci 3540141cc406Sopenharmony_ci default: 3541141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 3542141cc406Sopenharmony_ci } 3543141cc406Sopenharmony_ci#if 0 3544141cc406Sopenharmony_ci break; 3545141cc406Sopenharmony_ci#endif 3546141cc406Sopenharmony_ci default: 3547141cc406Sopenharmony_ci DBG(1, "sane_control_option: Unsupported action %d\n", action); 3548141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 3549141cc406Sopenharmony_ci } 3550141cc406Sopenharmony_ci} 3551141cc406Sopenharmony_ci 3552141cc406Sopenharmony_ci/*---------- sane_get_option_descriptor() ------------------------------------*/ 3553141cc406Sopenharmony_ci 3554141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 3555141cc406Sopenharmony_cisane_get_option_descriptor(SANE_Handle handle, SANE_Int n) 3556141cc406Sopenharmony_ci{ 3557141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 3558141cc406Sopenharmony_ci 3559141cc406Sopenharmony_ci DBG(255, "sane_get_option_descriptor: handle=%p, sod=%p, opt=%d\n", 3560141cc406Sopenharmony_ci (void *) handle, (void *) ms->sod, n); 3561141cc406Sopenharmony_ci 3562141cc406Sopenharmony_ci if ( n < 0 || n >= NUM_OPTIONS ) 3563141cc406Sopenharmony_ci { 3564141cc406Sopenharmony_ci DBG(30, "sane_get_option_descriptor: invalid option %d\n", n); 3565141cc406Sopenharmony_ci return NULL; 3566141cc406Sopenharmony_ci } 3567141cc406Sopenharmony_ci 3568141cc406Sopenharmony_ci return &ms->sod[n]; 3569141cc406Sopenharmony_ci} 3570141cc406Sopenharmony_ci 3571141cc406Sopenharmony_ci/*---------- restore_gamma_options() -----------------------------------------*/ 3572141cc406Sopenharmony_ci 3573141cc406Sopenharmony_cistatic SANE_Status 3574141cc406Sopenharmony_cirestore_gamma_options(SANE_Option_Descriptor *sod, Option_Value *val) 3575141cc406Sopenharmony_ci{ 3576141cc406Sopenharmony_ci 3577141cc406Sopenharmony_ci DBG(40, "restore_gamma_options: val=%p, sod=%p\n", (void *) val, (void *) sod); 3578141cc406Sopenharmony_ci /* if we don't have a gamma table return immediately */ 3579141cc406Sopenharmony_ci if ( ! val[OPT_GAMMA_MODE].s ) 3580141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3581141cc406Sopenharmony_ci 3582141cc406Sopenharmony_ci if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 ) 3583141cc406Sopenharmony_ci { 3584141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].cap &= ~SANE_CAP_INACTIVE; 3585141cc406Sopenharmony_ci if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_LINEAR) == 0 ) 3586141cc406Sopenharmony_ci { 3587141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; 3588141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 3589141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; 3590141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; 3591141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; 3592141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 3593141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; 3594141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; 3595141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; 3596141cc406Sopenharmony_ci } 3597141cc406Sopenharmony_ci else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_SCALAR) == 0 ) 3598141cc406Sopenharmony_ci { 3599141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; 3600141cc406Sopenharmony_ci if ( val[OPT_GAMMA_BIND].w == SANE_TRUE ) 3601141cc406Sopenharmony_ci { 3602141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap &= ~SANE_CAP_INACTIVE; 3603141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; 3604141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; 3605141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; 3606141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 3607141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; 3608141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; 3609141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; 3610141cc406Sopenharmony_ci } 3611141cc406Sopenharmony_ci else 3612141cc406Sopenharmony_ci { 3613141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 3614141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap &= ~SANE_CAP_INACTIVE; 3615141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap &= ~SANE_CAP_INACTIVE; 3616141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap &= ~SANE_CAP_INACTIVE; 3617141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 3618141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; 3619141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; 3620141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; 3621141cc406Sopenharmony_ci } 3622141cc406Sopenharmony_ci } 3623141cc406Sopenharmony_ci else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_CUSTOM) == 0 ) 3624141cc406Sopenharmony_ci { 3625141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; 3626141cc406Sopenharmony_ci if ( val[OPT_GAMMA_BIND].w == SANE_TRUE ) 3627141cc406Sopenharmony_ci { 3628141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap &= ~SANE_CAP_INACTIVE; 3629141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; 3630141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; 3631141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; 3632141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 3633141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; 3634141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; 3635141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; 3636141cc406Sopenharmony_ci } 3637141cc406Sopenharmony_ci else 3638141cc406Sopenharmony_ci { 3639141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 3640141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap &= ~SANE_CAP_INACTIVE; 3641141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap &= ~SANE_CAP_INACTIVE; 3642141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap &= ~SANE_CAP_INACTIVE; 3643141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 3644141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; 3645141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; 3646141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; 3647141cc406Sopenharmony_ci } 3648141cc406Sopenharmony_ci } 3649141cc406Sopenharmony_ci } 3650141cc406Sopenharmony_ci else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) 3651141cc406Sopenharmony_ci { 3652141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].cap &= ~SANE_CAP_INACTIVE; 3653141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; 3654141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; 3655141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; 3656141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; 3657141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; 3658141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; 3659141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; 3660141cc406Sopenharmony_ci if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_LINEAR) == 0 ) 3661141cc406Sopenharmony_ci { 3662141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 3663141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 3664141cc406Sopenharmony_ci } 3665141cc406Sopenharmony_ci else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_SCALAR) == 0 ) 3666141cc406Sopenharmony_ci { 3667141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap &= ~SANE_CAP_INACTIVE; 3668141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 3669141cc406Sopenharmony_ci } 3670141cc406Sopenharmony_ci else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_CUSTOM) == 0 ) 3671141cc406Sopenharmony_ci { 3672141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap &= ~SANE_CAP_INACTIVE; 3673141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 3674141cc406Sopenharmony_ci } 3675141cc406Sopenharmony_ci } 3676141cc406Sopenharmony_ci else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0 3677141cc406Sopenharmony_ci || strcmp(val[OPT_MODE].s, MD_MODESTRING_LINEART) == 0 ) 3678141cc406Sopenharmony_ci { 3679141cc406Sopenharmony_ci /* reset gamma to default */ 3680141cc406Sopenharmony_ci if ( val[OPT_GAMMA_MODE].s ) 3681141cc406Sopenharmony_ci free((void *) val[OPT_GAMMA_MODE].s); 3682141cc406Sopenharmony_ci val[OPT_GAMMA_MODE].s = strdup(MD_GAMMAMODE_LINEAR); 3683141cc406Sopenharmony_ci sod[OPT_GAMMA_MODE].cap |= SANE_CAP_INACTIVE; 3684141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; 3685141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; 3686141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; 3687141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; 3688141cc406Sopenharmony_ci sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; 3689141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; 3690141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; 3691141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; 3692141cc406Sopenharmony_ci sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; 3693141cc406Sopenharmony_ci } 3694141cc406Sopenharmony_ci else 3695141cc406Sopenharmony_ci DBG(1, "restore_gamma_options: unknown mode %s\n", val[OPT_MODE].s); 3696141cc406Sopenharmony_ci 3697141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3698141cc406Sopenharmony_ci} 3699141cc406Sopenharmony_ci 3700141cc406Sopenharmony_ci 3701141cc406Sopenharmony_ci/*---------- calculate_sane_params() -----------------------------------------*/ 3702141cc406Sopenharmony_ci 3703141cc406Sopenharmony_cistatic SANE_Status 3704141cc406Sopenharmony_cicalculate_sane_params(Microtek2_Scanner *ms) 3705141cc406Sopenharmony_ci{ 3706141cc406Sopenharmony_ci Microtek2_Device *md; 3707141cc406Sopenharmony_ci Microtek2_Info *mi; 3708141cc406Sopenharmony_ci 3709141cc406Sopenharmony_ci 3710141cc406Sopenharmony_ci DBG(30, "calculate_sane_params: ms=%p\n", (void *) ms); 3711141cc406Sopenharmony_ci 3712141cc406Sopenharmony_ci md = ms->dev; 3713141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 3714141cc406Sopenharmony_ci 3715141cc406Sopenharmony_ci if ( ! mi->onepass && ms->mode == MS_MODE_COLOR ) 3716141cc406Sopenharmony_ci { 3717141cc406Sopenharmony_ci if ( ms->current_pass == 1 ) 3718141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_RED; 3719141cc406Sopenharmony_ci else if ( ms->current_pass == 2 ) 3720141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_GREEN; 3721141cc406Sopenharmony_ci else if ( ms->current_pass == 3 ) 3722141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_BLUE; 3723141cc406Sopenharmony_ci else 3724141cc406Sopenharmony_ci { 3725141cc406Sopenharmony_ci DBG(1, "calculate_sane_params: invalid pass number %d\n", 3726141cc406Sopenharmony_ci ms->current_pass); 3727141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 3728141cc406Sopenharmony_ci } 3729141cc406Sopenharmony_ci } 3730141cc406Sopenharmony_ci else if ( mi->onepass && ms->mode == MS_MODE_COLOR ) 3731141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_RGB; 3732141cc406Sopenharmony_ci else 3733141cc406Sopenharmony_ci ms->params.format = SANE_FRAME_GRAY; 3734141cc406Sopenharmony_ci 3735141cc406Sopenharmony_ci if ( ! mi->onepass && ms->mode == MS_MODE_COLOR && ms->current_pass < 3 ) 3736141cc406Sopenharmony_ci ms->params.last_frame = SANE_FALSE; 3737141cc406Sopenharmony_ci else 3738141cc406Sopenharmony_ci ms->params.last_frame = SANE_TRUE; 3739141cc406Sopenharmony_ci ms->params.lines = ms->src_remaining_lines; 3740141cc406Sopenharmony_ci ms->params.pixels_per_line = ms->ppl; 3741141cc406Sopenharmony_ci ms->params.bytes_per_line = ms->real_bpl; 3742141cc406Sopenharmony_ci ms->params.depth = ms->bits_per_pixel_out; 3743141cc406Sopenharmony_ci 3744141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3745141cc406Sopenharmony_ci 3746141cc406Sopenharmony_ci} 3747141cc406Sopenharmony_ci 3748141cc406Sopenharmony_ci/*---------- get_calib_params() ----------------------------------------------*/ 3749141cc406Sopenharmony_ci 3750141cc406Sopenharmony_cistatic void 3751141cc406Sopenharmony_ciget_calib_params(Microtek2_Scanner *ms) 3752141cc406Sopenharmony_ci{ 3753141cc406Sopenharmony_ci Microtek2_Device *md; 3754141cc406Sopenharmony_ci Microtek2_Info *mi; 3755141cc406Sopenharmony_ci 3756141cc406Sopenharmony_ci 3757141cc406Sopenharmony_ci DBG(30, "get_calib_params: handle=%p\n", (void *) ms); 3758141cc406Sopenharmony_ci 3759141cc406Sopenharmony_ci md = ms->dev; 3760141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 3761141cc406Sopenharmony_ci 3762141cc406Sopenharmony_ci if ( md->model_flags & MD_CALIB_DIVISOR_600 ) 3763141cc406Sopenharmony_ci { 3764141cc406Sopenharmony_ci if ( ms->x_resolution_dpi <= 600 ) 3765141cc406Sopenharmony_ci mi->calib_divisor = 2; 3766141cc406Sopenharmony_ci else 3767141cc406Sopenharmony_ci mi->calib_divisor = 1; 3768141cc406Sopenharmony_ci } 3769141cc406Sopenharmony_ci DBG(30, "Calib Divisor: %d\n", mi->calib_divisor); 3770141cc406Sopenharmony_ci 3771141cc406Sopenharmony_ci 3772141cc406Sopenharmony_ci ms->x_resolution_dpi = mi->opt_resolution / mi->calib_divisor; 3773141cc406Sopenharmony_ci ms->y_resolution_dpi = mi->opt_resolution / 5; /* ignore dust particles */ 3774141cc406Sopenharmony_ci ms->x1_dots = 0; 3775141cc406Sopenharmony_ci ms->y1_dots = mi->calib_white; 3776141cc406Sopenharmony_ci ms->width_dots = mi->geo_width; 3777141cc406Sopenharmony_ci if ( md->shading_length != 0 ) 3778141cc406Sopenharmony_ci ms->height_dots = md->shading_length; 3779141cc406Sopenharmony_ci else 3780141cc406Sopenharmony_ci ms->height_dots = mi->calib_space; 3781141cc406Sopenharmony_ci 3782141cc406Sopenharmony_ci ms->mode = MS_MODE_COLOR; 3783141cc406Sopenharmony_ci 3784141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 3785141cc406Sopenharmony_ci ms->depth = 16; 3786141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_14 ) 3787141cc406Sopenharmony_ci ms->depth = 14; 3788141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_12 ) 3789141cc406Sopenharmony_ci ms->depth = 12; 3790141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_10 ) 3791141cc406Sopenharmony_ci ms->depth = 10; 3792141cc406Sopenharmony_ci else 3793141cc406Sopenharmony_ci ms->depth = 8; 3794141cc406Sopenharmony_ci 3795141cc406Sopenharmony_ci ms->stay = 0; 3796141cc406Sopenharmony_ci if ( mi->calib_space < 10 ) 3797141cc406Sopenharmony_ci ms->stay = 1; 3798141cc406Sopenharmony_ci ms->rawdat = 1; 3799141cc406Sopenharmony_ci ms->quality = 1; 3800141cc406Sopenharmony_ci ms->fastscan = 0; 3801141cc406Sopenharmony_ci/* ms->scan_source = md->scan_source; */ 3802141cc406Sopenharmony_ci ms->scan_source = 0; 3803141cc406Sopenharmony_ci ms->brightness_m = ms->brightness_r = ms->brightness_g = 3804141cc406Sopenharmony_ci ms->brightness_b = 128; 3805141cc406Sopenharmony_ci ms->exposure_m = ms->exposure_r = ms->exposure_g = ms->exposure_b = 0; 3806141cc406Sopenharmony_ci ms->contrast_m = ms->contrast_r = ms->contrast_g = ms->contrast_b = 128; 3807141cc406Sopenharmony_ci ms->shadow_m = ms->shadow_r = ms->shadow_g = ms->shadow_b = 0; 3808141cc406Sopenharmony_ci ms->midtone_m = ms->midtone_r = ms->midtone_g = ms->midtone_b = 128; 3809141cc406Sopenharmony_ci ms->highlight_m = ms->highlight_r = ms->highlight_g = ms->highlight_b = 255; 3810141cc406Sopenharmony_ci 3811141cc406Sopenharmony_ci return; 3812141cc406Sopenharmony_ci} 3813141cc406Sopenharmony_ci 3814141cc406Sopenharmony_ci 3815141cc406Sopenharmony_ci/*---------- get_scan_parameters () ------------------------------------------*/ 3816141cc406Sopenharmony_ci 3817141cc406Sopenharmony_cistatic SANE_Status 3818141cc406Sopenharmony_ciget_scan_parameters(Microtek2_Scanner *ms) 3819141cc406Sopenharmony_ci{ 3820141cc406Sopenharmony_ci Microtek2_Device *md; 3821141cc406Sopenharmony_ci Microtek2_Info *mi; 3822141cc406Sopenharmony_ci double dpm; /* dots per millimeter */ 3823141cc406Sopenharmony_ci int x2_dots; 3824141cc406Sopenharmony_ci int y2_dots; 3825141cc406Sopenharmony_ci int i; 3826141cc406Sopenharmony_ci 3827141cc406Sopenharmony_ci 3828141cc406Sopenharmony_ci DBG(30, "get_scan_parameters: handle=%p\n", (void *) ms); 3829141cc406Sopenharmony_ci 3830141cc406Sopenharmony_ci md = ms->dev; 3831141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 3832141cc406Sopenharmony_ci 3833141cc406Sopenharmony_ci get_scan_mode_and_depth(ms, &ms->mode, &ms->depth, 3834141cc406Sopenharmony_ci &ms->bits_per_pixel_in, &ms->bits_per_pixel_out); 3835141cc406Sopenharmony_ci 3836141cc406Sopenharmony_ci /* get the scan_source */ 3837141cc406Sopenharmony_ci if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_FLATBED) == 0 ) 3838141cc406Sopenharmony_ci ms->scan_source = MS_SOURCE_FLATBED; 3839141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_ADF) == 0 ) 3840141cc406Sopenharmony_ci ms->scan_source = MS_SOURCE_ADF; 3841141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_TMA) == 0 ) 3842141cc406Sopenharmony_ci ms->scan_source = MS_SOURCE_TMA; 3843141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_STRIPE) == 0 ) 3844141cc406Sopenharmony_ci ms->scan_source = MS_SOURCE_STRIPE; 3845141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_SLIDE) == 0 ) 3846141cc406Sopenharmony_ci ms->scan_source = MS_SOURCE_SLIDE; 3847141cc406Sopenharmony_ci 3848141cc406Sopenharmony_ci /* enable/disable backtracking */ 3849141cc406Sopenharmony_ci if ( ms->val[OPT_DISABLE_BACKTRACK].w == SANE_TRUE ) 3850141cc406Sopenharmony_ci ms->no_backtracking = 1; 3851141cc406Sopenharmony_ci else 3852141cc406Sopenharmony_ci ms->no_backtracking = 0; 3853141cc406Sopenharmony_ci 3854141cc406Sopenharmony_ci /* turn off the lamp during a scan */ 3855141cc406Sopenharmony_ci if ( ms->val[OPT_LIGHTLID35].w == SANE_TRUE ) 3856141cc406Sopenharmony_ci ms->lightlid35 = 1; 3857141cc406Sopenharmony_ci else 3858141cc406Sopenharmony_ci ms->lightlid35 = 0; 3859141cc406Sopenharmony_ci 3860141cc406Sopenharmony_ci /* automatic adjustment of threshold */ 3861141cc406Sopenharmony_ci if ( ms->val[OPT_AUTOADJUST].w == SANE_TRUE) 3862141cc406Sopenharmony_ci ms->auto_adjust = 1; 3863141cc406Sopenharmony_ci else 3864141cc406Sopenharmony_ci ms->auto_adjust = 0; 3865141cc406Sopenharmony_ci 3866141cc406Sopenharmony_ci /* color calibration by backend */ 3867141cc406Sopenharmony_ci if ( ms->val[OPT_CALIB_BACKEND].w == SANE_TRUE ) 3868141cc406Sopenharmony_ci ms->calib_backend = 1; 3869141cc406Sopenharmony_ci else 3870141cc406Sopenharmony_ci ms->calib_backend = 0; 3871141cc406Sopenharmony_ci 3872141cc406Sopenharmony_ci /* if halftone mode select halftone pattern */ 3873141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_HALFTONE ) 3874141cc406Sopenharmony_ci { 3875141cc406Sopenharmony_ci i = 0; 3876141cc406Sopenharmony_ci while ( strcmp(md->halftone_mode_list[i], ms->val[OPT_HALFTONE].s) ) 3877141cc406Sopenharmony_ci ++i; 3878141cc406Sopenharmony_ci ms->internal_ht_index = i; 3879141cc406Sopenharmony_ci } 3880141cc406Sopenharmony_ci 3881141cc406Sopenharmony_ci /* if lineart get the value for threshold */ 3882141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_LINEART || ms->mode == MS_MODE_LINEARTFAKE) 3883141cc406Sopenharmony_ci ms->threshold = (uint8_t) ms->val[OPT_THRESHOLD].w; 3884141cc406Sopenharmony_ci else 3885141cc406Sopenharmony_ci ms->threshold = (uint8_t) M_THRESHOLD_DEFAULT; 3886141cc406Sopenharmony_ci 3887141cc406Sopenharmony_ci DBG(30, "get_scan_parameters: mode=%d, depth=%d, bpp_in=%d, bpp_out=%d\n", 3888141cc406Sopenharmony_ci ms->mode, ms->depth, ms->bits_per_pixel_in, 3889141cc406Sopenharmony_ci ms->bits_per_pixel_out); 3890141cc406Sopenharmony_ci 3891141cc406Sopenharmony_ci /* calculate positions, width and height in dots */ 3892141cc406Sopenharmony_ci /* check for impossible values */ 3893141cc406Sopenharmony_ci /* ensure a minimum scan area of 10 x 10 pixels */ 3894141cc406Sopenharmony_ci dpm = (double) mi->opt_resolution / MM_PER_INCH; 3895141cc406Sopenharmony_ci ms->x1_dots = (SANE_Int) ( SANE_UNFIX(ms->val[OPT_TL_X].w) * dpm + 0.5 ); 3896141cc406Sopenharmony_ci if ( ms->x1_dots > ( mi->geo_width - 10 ) ) 3897141cc406Sopenharmony_ci ms->x1_dots = ( mi->geo_width - 10 ); 3898141cc406Sopenharmony_ci ms->y1_dots = (SANE_Int) ( SANE_UNFIX(ms->val[OPT_TL_Y].w) * dpm + 0.5 ); 3899141cc406Sopenharmony_ci if ( ms->y1_dots > ( mi->geo_height - 10 ) ) 3900141cc406Sopenharmony_ci ms->y1_dots = ( mi->geo_height - 10 ); 3901141cc406Sopenharmony_ci x2_dots = (int) ( SANE_UNFIX(ms->val[OPT_BR_X].w) * dpm + 0.5 ); 3902141cc406Sopenharmony_ci if ( x2_dots >= mi->geo_width ) 3903141cc406Sopenharmony_ci x2_dots = mi->geo_width - 1; 3904141cc406Sopenharmony_ci y2_dots = (int) ( SANE_UNFIX(ms->val[OPT_BR_Y].w) * dpm + 0.5 ); 3905141cc406Sopenharmony_ci if ( y2_dots >= mi->geo_height ) 3906141cc406Sopenharmony_ci y2_dots = mi->geo_height - 1; 3907141cc406Sopenharmony_ci ms->width_dots = x2_dots - ms->x1_dots; 3908141cc406Sopenharmony_ci if ( md->model_flags & MD_OFFSET_2 ) /* this firmware has problems with */ 3909141cc406Sopenharmony_ci if ( ( ms->width_dots % 2 ) == 1 ) /* odd pixel numbers */ 3910141cc406Sopenharmony_ci ms->width_dots -= 1; 3911141cc406Sopenharmony_ci if ( ms->width_dots < 10 ) 3912141cc406Sopenharmony_ci ms->width_dots = 10; 3913141cc406Sopenharmony_ci ms->height_dots = y2_dots - ms->y1_dots; 3914141cc406Sopenharmony_ci if ( ms->height_dots < 10 ) 3915141cc406Sopenharmony_ci ms->height_dots = 10; 3916141cc406Sopenharmony_ci 3917141cc406Sopenharmony_ci/*test!!!*/ 3918141cc406Sopenharmony_ci/* ms->y1_dots -= 50;*/ 3919141cc406Sopenharmony_ci 3920141cc406Sopenharmony_ci /* take scanning direction into account */ 3921141cc406Sopenharmony_ci if ((mi->direction & MI_DATSEQ_RTOL) == 1) 3922141cc406Sopenharmony_ci ms->x1_dots = mi->geo_width - ms->x1_dots - ms->width_dots; 3923141cc406Sopenharmony_ci 3924141cc406Sopenharmony_ci if ( ms->val[OPT_RESOLUTION_BIND].w == SANE_TRUE ) 3925141cc406Sopenharmony_ci { 3926141cc406Sopenharmony_ci ms->x_resolution_dpi = 3927141cc406Sopenharmony_ci (SANE_Int) (SANE_UNFIX(ms->val[OPT_RESOLUTION].w) + 0.5); 3928141cc406Sopenharmony_ci ms->y_resolution_dpi = 3929141cc406Sopenharmony_ci (SANE_Int) (SANE_UNFIX(ms->val[OPT_RESOLUTION].w) + 0.5); 3930141cc406Sopenharmony_ci } 3931141cc406Sopenharmony_ci else 3932141cc406Sopenharmony_ci { 3933141cc406Sopenharmony_ci ms->x_resolution_dpi = 3934141cc406Sopenharmony_ci (SANE_Int) (SANE_UNFIX(ms->val[OPT_RESOLUTION].w) + 0.5); 3935141cc406Sopenharmony_ci ms->y_resolution_dpi = 3936141cc406Sopenharmony_ci (SANE_Int) (SANE_UNFIX(ms->val[OPT_Y_RESOLUTION].w) + 0.5); 3937141cc406Sopenharmony_ci } 3938141cc406Sopenharmony_ci 3939141cc406Sopenharmony_ci if ( ms->x_resolution_dpi < 10 ) 3940141cc406Sopenharmony_ci ms->x_resolution_dpi = 10; 3941141cc406Sopenharmony_ci if ( ms->y_resolution_dpi < 10 ) 3942141cc406Sopenharmony_ci ms->y_resolution_dpi = 10; 3943141cc406Sopenharmony_ci 3944141cc406Sopenharmony_ci DBG(30, "get_scan_parameters: yres=%d, x1=%d, width=%d, y1=%d, height=%d\n", 3945141cc406Sopenharmony_ci ms->y_resolution_dpi, ms->x1_dots, ms->width_dots, 3946141cc406Sopenharmony_ci ms->y1_dots, ms->height_dots); 3947141cc406Sopenharmony_ci 3948141cc406Sopenharmony_ci /* Preview mode */ 3949141cc406Sopenharmony_ci if ( ms->val[OPT_PREVIEW].w == SANE_TRUE ) 3950141cc406Sopenharmony_ci { 3951141cc406Sopenharmony_ci ms->fastscan = SANE_TRUE; 3952141cc406Sopenharmony_ci ms->quality = SANE_FALSE; 3953141cc406Sopenharmony_ci } 3954141cc406Sopenharmony_ci else 3955141cc406Sopenharmony_ci { 3956141cc406Sopenharmony_ci ms->fastscan = SANE_FALSE; 3957141cc406Sopenharmony_ci ms->quality = SANE_TRUE; 3958141cc406Sopenharmony_ci } 3959141cc406Sopenharmony_ci 3960141cc406Sopenharmony_ci ms->rawdat = 0; 3961141cc406Sopenharmony_ci 3962141cc406Sopenharmony_ci /* brightness, contrast, values 1,..,255 */ 3963141cc406Sopenharmony_ci ms->brightness_m = (uint8_t) (SANE_UNFIX(ms->val[OPT_BRIGHTNESS].w) 3964141cc406Sopenharmony_ci / SANE_UNFIX(md->percentage_range.max) * 254.0) + 1; 3965141cc406Sopenharmony_ci ms->brightness_r = ms->brightness_g = ms->brightness_b = ms->brightness_m; 3966141cc406Sopenharmony_ci 3967141cc406Sopenharmony_ci ms->contrast_m = (uint8_t) (SANE_UNFIX(ms->val[OPT_CONTRAST].w) 3968141cc406Sopenharmony_ci / SANE_UNFIX(md->percentage_range.max) * 254.0) + 1; 3969141cc406Sopenharmony_ci ms->contrast_r = ms->contrast_g = ms->contrast_b = ms->contrast_m; 3970141cc406Sopenharmony_ci 3971141cc406Sopenharmony_ci /* shadow, midtone, highlight, exposure */ 3972141cc406Sopenharmony_ci ms->shadow_m = (uint8_t) ms->val[OPT_SHADOW].w; 3973141cc406Sopenharmony_ci ms->shadow_r = (uint8_t) ms->val[OPT_SHADOW_R].w; 3974141cc406Sopenharmony_ci ms->shadow_g = (uint8_t) ms->val[OPT_SHADOW_G].w; 3975141cc406Sopenharmony_ci ms->shadow_b = (uint8_t) ms->val[OPT_SHADOW_B].w; 3976141cc406Sopenharmony_ci ms->midtone_m = (uint8_t) ms->val[OPT_MIDTONE].w; 3977141cc406Sopenharmony_ci ms->midtone_r = (uint8_t) ms->val[OPT_MIDTONE_R].w; 3978141cc406Sopenharmony_ci ms->midtone_g = (uint8_t) ms->val[OPT_MIDTONE_G].w; 3979141cc406Sopenharmony_ci ms->midtone_b = (uint8_t) ms->val[OPT_MIDTONE_B].w; 3980141cc406Sopenharmony_ci ms->highlight_m = (uint8_t) ms->val[OPT_HIGHLIGHT].w; 3981141cc406Sopenharmony_ci ms->highlight_r = (uint8_t) ms->val[OPT_HIGHLIGHT_R].w; 3982141cc406Sopenharmony_ci ms->highlight_g = (uint8_t) ms->val[OPT_HIGHLIGHT_G].w; 3983141cc406Sopenharmony_ci ms->highlight_b = (uint8_t) ms->val[OPT_HIGHLIGHT_B].w; 3984141cc406Sopenharmony_ci ms->exposure_m = (uint8_t) (ms->val[OPT_EXPOSURE].w / 2); 3985141cc406Sopenharmony_ci ms->exposure_r = (uint8_t) (ms->val[OPT_EXPOSURE_R].w / 2); 3986141cc406Sopenharmony_ci ms->exposure_g = (uint8_t) (ms->val[OPT_EXPOSURE_G].w / 2); 3987141cc406Sopenharmony_ci ms->exposure_b = (uint8_t) (ms->val[OPT_EXPOSURE_B].w / 2); 3988141cc406Sopenharmony_ci 3989141cc406Sopenharmony_ci ms->gamma_mode = strdup( (char *) ms->val[OPT_GAMMA_MODE].s); 3990141cc406Sopenharmony_ci 3991141cc406Sopenharmony_ci ms->balance[0] = (uint8_t) (SANE_UNFIX(ms->val[OPT_BALANCE_R].w)); 3992141cc406Sopenharmony_ci ms->balance[1] = (uint8_t) (SANE_UNFIX(ms->val[OPT_BALANCE_G].w)); 3993141cc406Sopenharmony_ci ms->balance[2] = (uint8_t) (SANE_UNFIX(ms->val[OPT_BALANCE_B].w)); 3994141cc406Sopenharmony_ci DBG(255, "get_scan_parameters:ms->balance[0]=%d,[1]=%d,[2]=%d\n", 3995141cc406Sopenharmony_ci ms->balance[0], ms->balance[1], ms->balance[2]); 3996141cc406Sopenharmony_ci 3997141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3998141cc406Sopenharmony_ci} 3999141cc406Sopenharmony_ci 4000141cc406Sopenharmony_ci/*---------- get_scan_mode_and_depth() ---------------------------------------*/ 4001141cc406Sopenharmony_ci 4002141cc406Sopenharmony_cistatic SANE_Status 4003141cc406Sopenharmony_ciget_scan_mode_and_depth(Microtek2_Scanner *ms, 4004141cc406Sopenharmony_ci int *mode, 4005141cc406Sopenharmony_ci int *depth, 4006141cc406Sopenharmony_ci int *bits_per_pixel_in, 4007141cc406Sopenharmony_ci int *bits_per_pixel_out) 4008141cc406Sopenharmony_ci{ 4009141cc406Sopenharmony_ci /* This function translates the strings for the possible modes and */ 4010141cc406Sopenharmony_ci /* bitdepth into a more conveniant format as needed for SET WINDOW. */ 4011141cc406Sopenharmony_ci /* bits_per_pixel is the number of bits per color one pixel needs */ 4012141cc406Sopenharmony_ci /* when transferred from the scanner, bits_perpixel_out is the */ 4013141cc406Sopenharmony_ci /* number of bits per color one pixel uses when transferred to the */ 4014141cc406Sopenharmony_ci /* frontend. These may be different. For example, with a depth of 4 */ 4015141cc406Sopenharmony_ci /* two pixels per byte are transferred from the scanner, but only one */ 4016141cc406Sopenharmony_ci /* pixel per byte is transferred to the frontend. */ 4017141cc406Sopenharmony_ci /* If lineart_fake is set to !=0, we need the parameters for a */ 4018141cc406Sopenharmony_ci /* grayscale scan, because the scanner has no lineart mode */ 4019141cc406Sopenharmony_ci 4020141cc406Sopenharmony_ci Microtek2_Device *md; 4021141cc406Sopenharmony_ci Microtek2_Info *mi; 4022141cc406Sopenharmony_ci 4023141cc406Sopenharmony_ci DBG(30, "get_scan_mode_and_depth: handle=%p\n", (void *) ms); 4024141cc406Sopenharmony_ci 4025141cc406Sopenharmony_ci md = ms->dev; 4026141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 4027141cc406Sopenharmony_ci 4028141cc406Sopenharmony_ci if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 ) 4029141cc406Sopenharmony_ci *mode = MS_MODE_COLOR; 4030141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) 4031141cc406Sopenharmony_ci *mode = MS_MODE_GRAY; 4032141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0) 4033141cc406Sopenharmony_ci *mode = MS_MODE_HALFTONE; 4034141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_LINEART) == 0 ) 4035141cc406Sopenharmony_ci { 4036141cc406Sopenharmony_ci if ( MI_LINEART_NONE(mi->scanmode) 4037141cc406Sopenharmony_ci || ms->val[OPT_AUTOADJUST].w == SANE_TRUE 4038141cc406Sopenharmony_ci || md->model_flags & MD_READ_CONTROL_BIT) 4039141cc406Sopenharmony_ci *mode = MS_MODE_LINEARTFAKE; 4040141cc406Sopenharmony_ci else 4041141cc406Sopenharmony_ci *mode = MS_MODE_LINEART; 4042141cc406Sopenharmony_ci } 4043141cc406Sopenharmony_ci else 4044141cc406Sopenharmony_ci { 4045141cc406Sopenharmony_ci DBG(1, "get_scan_mode_and_depth: Unknown mode %s\n", 4046141cc406Sopenharmony_ci ms->val[OPT_MODE].s); 4047141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 4048141cc406Sopenharmony_ci } 4049141cc406Sopenharmony_ci 4050141cc406Sopenharmony_ci if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 4051141cc406Sopenharmony_ci || strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) 4052141cc406Sopenharmony_ci { 4053141cc406Sopenharmony_ci if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_16 ) 4054141cc406Sopenharmony_ci { 4055141cc406Sopenharmony_ci *depth = 16; 4056141cc406Sopenharmony_ci *bits_per_pixel_in = *bits_per_pixel_out = 16; 4057141cc406Sopenharmony_ci } 4058141cc406Sopenharmony_ci else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_14 ) 4059141cc406Sopenharmony_ci { 4060141cc406Sopenharmony_ci *depth = 14; 4061141cc406Sopenharmony_ci *bits_per_pixel_in = *bits_per_pixel_out = 16; 4062141cc406Sopenharmony_ci } 4063141cc406Sopenharmony_ci else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_12 ) 4064141cc406Sopenharmony_ci { 4065141cc406Sopenharmony_ci *depth = 12; 4066141cc406Sopenharmony_ci *bits_per_pixel_in = *bits_per_pixel_out = 16; 4067141cc406Sopenharmony_ci } 4068141cc406Sopenharmony_ci else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_10 ) 4069141cc406Sopenharmony_ci { 4070141cc406Sopenharmony_ci *depth = 10; 4071141cc406Sopenharmony_ci *bits_per_pixel_in = *bits_per_pixel_out = 16; 4072141cc406Sopenharmony_ci } 4073141cc406Sopenharmony_ci else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_8 ) 4074141cc406Sopenharmony_ci { 4075141cc406Sopenharmony_ci *depth = 8; 4076141cc406Sopenharmony_ci *bits_per_pixel_in = *bits_per_pixel_out = 8; 4077141cc406Sopenharmony_ci } 4078141cc406Sopenharmony_ci else if ( ms->val[OPT_MODE].w == MD_DEPTHVAL_4 ) 4079141cc406Sopenharmony_ci { 4080141cc406Sopenharmony_ci *depth = 4; 4081141cc406Sopenharmony_ci *bits_per_pixel_in = 4; 4082141cc406Sopenharmony_ci *bits_per_pixel_out = 8; 4083141cc406Sopenharmony_ci } 4084141cc406Sopenharmony_ci } 4085141cc406Sopenharmony_ci else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0 ) 4086141cc406Sopenharmony_ci { 4087141cc406Sopenharmony_ci *depth = 1; 4088141cc406Sopenharmony_ci *bits_per_pixel_in = *bits_per_pixel_out = 1; 4089141cc406Sopenharmony_ci } 4090141cc406Sopenharmony_ci else /* lineart */ 4091141cc406Sopenharmony_ci { 4092141cc406Sopenharmony_ci *bits_per_pixel_out = 1; 4093141cc406Sopenharmony_ci if ( *mode == MS_MODE_LINEARTFAKE ) 4094141cc406Sopenharmony_ci { 4095141cc406Sopenharmony_ci *depth = 8; 4096141cc406Sopenharmony_ci *bits_per_pixel_in = 8; 4097141cc406Sopenharmony_ci } 4098141cc406Sopenharmony_ci else 4099141cc406Sopenharmony_ci { 4100141cc406Sopenharmony_ci *depth = 1; 4101141cc406Sopenharmony_ci *bits_per_pixel_in = 1; 4102141cc406Sopenharmony_ci } 4103141cc406Sopenharmony_ci } 4104141cc406Sopenharmony_ci 4105141cc406Sopenharmony_ci#if 0 4106141cc406Sopenharmony_ci if ( ms->val[OPT_PREVIEW].w == SANE_TRUE ) 4107141cc406Sopenharmony_ci { 4108141cc406Sopenharmony_ci if ( *depth > 8 ) 4109141cc406Sopenharmony_ci { 4110141cc406Sopenharmony_ci *depth = 8; 4111141cc406Sopenharmony_ci *bits_per_pixel_in = *bits_per_pixel_out = 8; 4112141cc406Sopenharmony_ci } 4113141cc406Sopenharmony_ci } 4114141cc406Sopenharmony_ci#endif 4115141cc406Sopenharmony_ci 4116141cc406Sopenharmony_ci DBG(30, "get_scan_mode_and_depth: mode=%d, depth=%d," 4117141cc406Sopenharmony_ci " bits_pp_in=%d, bits_pp_out=%d, preview=%d\n", 4118141cc406Sopenharmony_ci *mode, *depth, *bits_per_pixel_in, *bits_per_pixel_out, 4119141cc406Sopenharmony_ci ms->val[OPT_PREVIEW].w); 4120141cc406Sopenharmony_ci 4121141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4122141cc406Sopenharmony_ci} 4123141cc406Sopenharmony_ci 4124141cc406Sopenharmony_ci 4125141cc406Sopenharmony_ci/*---------- scsi_wait_for_image() -------------------------------------------*/ 4126141cc406Sopenharmony_ci 4127141cc406Sopenharmony_cistatic SANE_Status 4128141cc406Sopenharmony_ciscsi_wait_for_image(Microtek2_Scanner *ms) 4129141cc406Sopenharmony_ci{ 4130141cc406Sopenharmony_ci int retry = 60; 4131141cc406Sopenharmony_ci SANE_Status status; 4132141cc406Sopenharmony_ci 4133141cc406Sopenharmony_ci 4134141cc406Sopenharmony_ci DBG(30, "scsi_wait_for_image: ms=%p\n", (void *) ms); 4135141cc406Sopenharmony_ci 4136141cc406Sopenharmony_ci while ( retry-- > 0 ) 4137141cc406Sopenharmony_ci { 4138141cc406Sopenharmony_ci status = scsi_read_image_status(ms); 4139141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY ) 4140141cc406Sopenharmony_ci { 4141141cc406Sopenharmony_ci sleep(1); 4142141cc406Sopenharmony_ci continue; 4143141cc406Sopenharmony_ci } 4144141cc406Sopenharmony_ci if ( status == SANE_STATUS_GOOD ) 4145141cc406Sopenharmony_ci return status; 4146141cc406Sopenharmony_ci 4147141cc406Sopenharmony_ci /* status != GOOD && != BUSY */ 4148141cc406Sopenharmony_ci DBG(1, "scsi_wait_for_image: '%s'\n", sane_strstatus(status)); 4149141cc406Sopenharmony_ci return status; 4150141cc406Sopenharmony_ci } 4151141cc406Sopenharmony_ci 4152141cc406Sopenharmony_ci /* BUSY after n retries */ 4153141cc406Sopenharmony_ci DBG(1, "scsi_wait_for_image: '%s'\n", sane_strstatus(status)); 4154141cc406Sopenharmony_ci return status; 4155141cc406Sopenharmony_ci} 4156141cc406Sopenharmony_ci 4157141cc406Sopenharmony_ci 4158141cc406Sopenharmony_ci/*---------- scsi_read_gamma() -----------------------------------------------*/ 4159141cc406Sopenharmony_ci 4160141cc406Sopenharmony_ci/* currently not used */ 4161141cc406Sopenharmony_ci/* 4162141cc406Sopenharmony_cistatic SANE_Status 4163141cc406Sopenharmony_ciscsi_read_gamma(Microtek2_Scanner *ms, int color) 4164141cc406Sopenharmony_ci{ 4165141cc406Sopenharmony_ci uint8_t readgamma[RG_CMD_L]; 4166141cc406Sopenharmony_ci uint8_t result[3072]; 4167141cc406Sopenharmony_ci size_t size; 4168141cc406Sopenharmony_ci SANE_Bool endiantype; 4169141cc406Sopenharmony_ci SANE_Status status; 4170141cc406Sopenharmony_ci 4171141cc406Sopenharmony_ci RG_CMD(readgamma); 4172141cc406Sopenharmony_ci ENDIAN_TYPE(endiantype); 4173141cc406Sopenharmony_ci RG_PCORMAC(readgamma, endiantype); 4174141cc406Sopenharmony_ci RG_COLOR(readgamma, color); 4175141cc406Sopenharmony_ci RG_WORD(readgamma, ( ms->dev->lut_entry_size == 1 ) ? 0 : 1); 4176141cc406Sopenharmony_ci RG_TRANSFERLENGTH(readgamma, (color == 3 ) ? 3072 : 1024); 4177141cc406Sopenharmony_ci 4178141cc406Sopenharmony_ci dump_area(readgamma, 10, "ReadGamma"); 4179141cc406Sopenharmony_ci 4180141cc406Sopenharmony_ci size = sizeof(result); 4181141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, readgamma, sizeof(readgamma), 4182141cc406Sopenharmony_ci result, &size); 4183141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) { 4184141cc406Sopenharmony_ci DBG(1, "scsi_read_gamma: (L,R) read_gamma failed: status '%s'\n", 4185141cc406Sopenharmony_ci sane_strstatus(status)); 4186141cc406Sopenharmony_ci return status; 4187141cc406Sopenharmony_ci } 4188141cc406Sopenharmony_ci 4189141cc406Sopenharmony_ci dump_area(result, 3072, "Result"); 4190141cc406Sopenharmony_ci 4191141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4192141cc406Sopenharmony_ci} 4193141cc406Sopenharmony_ci*/ 4194141cc406Sopenharmony_ci 4195141cc406Sopenharmony_ci 4196141cc406Sopenharmony_ci/*---------- scsi_send_gamma() -----------------------------------------------*/ 4197141cc406Sopenharmony_ci 4198141cc406Sopenharmony_cistatic SANE_Status 4199141cc406Sopenharmony_ciscsi_send_gamma(Microtek2_Scanner *ms) 4200141cc406Sopenharmony_ci{ 4201141cc406Sopenharmony_ci SANE_Bool endiantype; 4202141cc406Sopenharmony_ci SANE_Status status; 4203141cc406Sopenharmony_ci size_t size; 4204141cc406Sopenharmony_ci uint8_t *cmd, color; 4205141cc406Sopenharmony_ci 4206141cc406Sopenharmony_ci 4207141cc406Sopenharmony_ci DBG(30, "scsi_send_gamma: pos=%p, size=%d, word=%d, color=%d\n", 4208141cc406Sopenharmony_ci (void *) ms->gamma_table, ms->lut_size_bytes, ms->word, 4209141cc406Sopenharmony_ci ms->current_color); 4210141cc406Sopenharmony_ci 4211141cc406Sopenharmony_ci if ( ( 3 * ms->lut_size_bytes ) <= 0xffff ) /*send Gamma with one command*/ 4212141cc406Sopenharmony_ci { 4213141cc406Sopenharmony_ci cmd = (uint8_t *) alloca(SG_CMD_L + 3 * ms->lut_size_bytes); 4214141cc406Sopenharmony_ci if ( cmd == NULL ) 4215141cc406Sopenharmony_ci { 4216141cc406Sopenharmony_ci DBG(1, "scsi_send_gamma: Couldn't get buffer for gamma table\n"); 4217141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4218141cc406Sopenharmony_ci } 4219141cc406Sopenharmony_ci 4220141cc406Sopenharmony_ci SG_SET_CMD(cmd); 4221141cc406Sopenharmony_ci ENDIAN_TYPE(endiantype) 4222141cc406Sopenharmony_ci SG_SET_PCORMAC(cmd, endiantype); 4223141cc406Sopenharmony_ci SG_SET_COLOR(cmd, ms->current_color); 4224141cc406Sopenharmony_ci SG_SET_WORD(cmd, ms->word); 4225141cc406Sopenharmony_ci SG_SET_TRANSFERLENGTH(cmd, 3 * ms->lut_size_bytes); 4226141cc406Sopenharmony_ci memcpy(cmd + SG_CMD_L, ms->gamma_table, 3 * ms->lut_size_bytes); 4227141cc406Sopenharmony_ci size = 3 * ms->lut_size_bytes; 4228141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4229141cc406Sopenharmony_ci dump_area2(cmd, SG_CMD_L, "sendgammacmd"); 4230141cc406Sopenharmony_ci if ( md_dump >= 3 ) 4231141cc406Sopenharmony_ci dump_area2(cmd + SG_CMD_L, size, "sendgammadata"); 4232141cc406Sopenharmony_ci 4233141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, size + SG_CMD_L, NULL, 0); 4234141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4235141cc406Sopenharmony_ci DBG(1, "scsi_send_gamma: '%s'\n", sane_strstatus(status)); 4236141cc406Sopenharmony_ci } 4237141cc406Sopenharmony_ci 4238141cc406Sopenharmony_ci else /* send gamma with 3 commands, one for each color */ 4239141cc406Sopenharmony_ci { 4240141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 4241141cc406Sopenharmony_ci { 4242141cc406Sopenharmony_ci cmd = (uint8_t *) alloca(SG_CMD_L + ms->lut_size_bytes); 4243141cc406Sopenharmony_ci if ( cmd == NULL ) 4244141cc406Sopenharmony_ci { 4245141cc406Sopenharmony_ci DBG(1, "scsi_send_gamma: Couldn't get buffer for gamma table\n"); 4246141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4247141cc406Sopenharmony_ci } 4248141cc406Sopenharmony_ci SG_SET_CMD(cmd); 4249141cc406Sopenharmony_ci ENDIAN_TYPE(endiantype) 4250141cc406Sopenharmony_ci SG_SET_PCORMAC(cmd, endiantype); 4251141cc406Sopenharmony_ci SG_SET_COLOR(cmd, color); 4252141cc406Sopenharmony_ci SG_SET_WORD(cmd, ms->word); 4253141cc406Sopenharmony_ci SG_SET_TRANSFERLENGTH(cmd, ms->lut_size_bytes); 4254141cc406Sopenharmony_ci memcpy(cmd + SG_CMD_L, 4255141cc406Sopenharmony_ci ms->gamma_table + color * ms->lut_size_bytes, 4256141cc406Sopenharmony_ci ms->lut_size_bytes); 4257141cc406Sopenharmony_ci size = ms->lut_size_bytes; 4258141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4259141cc406Sopenharmony_ci dump_area2(cmd, SG_CMD_L, "sendgammacmd"); 4260141cc406Sopenharmony_ci if ( md_dump >= 3 ) 4261141cc406Sopenharmony_ci dump_area2(cmd + SG_CMD_L, size, "sendgammadata"); 4262141cc406Sopenharmony_ci 4263141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, size + SG_CMD_L, NULL, 0); 4264141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4265141cc406Sopenharmony_ci DBG(1, "scsi_send_gamma: '%s'\n", sane_strstatus(status)); 4266141cc406Sopenharmony_ci } 4267141cc406Sopenharmony_ci 4268141cc406Sopenharmony_ci } 4269141cc406Sopenharmony_ci 4270141cc406Sopenharmony_ci return status; 4271141cc406Sopenharmony_ci} 4272141cc406Sopenharmony_ci 4273141cc406Sopenharmony_ci 4274141cc406Sopenharmony_ci/*---------- scsi_inquiry() --------------------------------------------------*/ 4275141cc406Sopenharmony_ci 4276141cc406Sopenharmony_cistatic SANE_Status 4277141cc406Sopenharmony_ciscsi_inquiry(Microtek2_Info *mi, char *device) 4278141cc406Sopenharmony_ci{ 4279141cc406Sopenharmony_ci SANE_Status status; 4280141cc406Sopenharmony_ci uint8_t cmd[INQ_CMD_L]; 4281141cc406Sopenharmony_ci uint8_t *result; 4282141cc406Sopenharmony_ci uint8_t inqlen; 4283141cc406Sopenharmony_ci size_t size; 4284141cc406Sopenharmony_ci int sfd; 4285141cc406Sopenharmony_ci 4286141cc406Sopenharmony_ci 4287141cc406Sopenharmony_ci DBG(30, "scsi_inquiry: mi=%p, device='%s'\n", (void *) mi, device); 4288141cc406Sopenharmony_ci 4289141cc406Sopenharmony_ci status = sanei_scsi_open(device, &sfd, scsi_sense_handler, 0); 4290141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4291141cc406Sopenharmony_ci { 4292141cc406Sopenharmony_ci DBG(1, "scsi_inquiry: '%s'\n", sane_strstatus(status)); 4293141cc406Sopenharmony_ci return status; 4294141cc406Sopenharmony_ci } 4295141cc406Sopenharmony_ci 4296141cc406Sopenharmony_ci INQ_CMD(cmd); 4297141cc406Sopenharmony_ci INQ_SET_ALLOC(cmd, INQ_ALLOC_L); 4298141cc406Sopenharmony_ci result = (uint8_t *) alloca(INQ_ALLOC_L); 4299141cc406Sopenharmony_ci if ( result == NULL ) 4300141cc406Sopenharmony_ci { 4301141cc406Sopenharmony_ci DBG(1, "scsi_inquiry: malloc failed\n"); 4302141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4303141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 4304141cc406Sopenharmony_ci } 4305141cc406Sopenharmony_ci 4306141cc406Sopenharmony_ci size = INQ_ALLOC_L; 4307141cc406Sopenharmony_ci status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), result, &size); 4308141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4309141cc406Sopenharmony_ci { 4310141cc406Sopenharmony_ci DBG(1, "scsi_inquiry: '%s'\n", sane_strstatus(status)); 4311141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4312141cc406Sopenharmony_ci return status; 4313141cc406Sopenharmony_ci } 4314141cc406Sopenharmony_ci 4315141cc406Sopenharmony_ci INQ_GET_INQLEN(inqlen, result); 4316141cc406Sopenharmony_ci INQ_SET_ALLOC(cmd, inqlen + INQ_ALLOC_L); 4317141cc406Sopenharmony_ci result = alloca(inqlen + INQ_ALLOC_L); 4318141cc406Sopenharmony_ci if ( result == NULL ) 4319141cc406Sopenharmony_ci { 4320141cc406Sopenharmony_ci DBG(1, "scsi_inquiry: malloc failed\n"); 4321141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4322141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 4323141cc406Sopenharmony_ci } 4324141cc406Sopenharmony_ci size = inqlen + INQ_ALLOC_L; 4325141cc406Sopenharmony_ci if (md_dump >= 2 ) 4326141cc406Sopenharmony_ci dump_area2(cmd, sizeof(cmd), "inquiry"); 4327141cc406Sopenharmony_ci 4328141cc406Sopenharmony_ci status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), result, &size); 4329141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4330141cc406Sopenharmony_ci { 4331141cc406Sopenharmony_ci DBG(1, "scsi_inquiry: cmd '%s'\n", sane_strstatus(status)); 4332141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4333141cc406Sopenharmony_ci return status; 4334141cc406Sopenharmony_ci } 4335141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4336141cc406Sopenharmony_ci 4337141cc406Sopenharmony_ci if (md_dump >= 2 ) 4338141cc406Sopenharmony_ci { 4339141cc406Sopenharmony_ci dump_area2((uint8_t *) result, size, "inquiryresult"); 4340141cc406Sopenharmony_ci dump_area((uint8_t *) result, size, "inquiryresult"); 4341141cc406Sopenharmony_ci } 4342141cc406Sopenharmony_ci 4343141cc406Sopenharmony_ci /* copy results */ 4344141cc406Sopenharmony_ci INQ_GET_QUAL(mi->device_qualifier, result); 4345141cc406Sopenharmony_ci INQ_GET_DEVT(mi->device_type, result); 4346141cc406Sopenharmony_ci INQ_GET_VERSION(mi->scsi_version, result); 4347141cc406Sopenharmony_ci INQ_GET_VENDOR(mi->vendor, (char *)result); 4348141cc406Sopenharmony_ci INQ_GET_MODEL(mi->model, (char *)result); 4349141cc406Sopenharmony_ci INQ_GET_REV(mi->revision, (char *)result); 4350141cc406Sopenharmony_ci INQ_GET_MODELCODE(mi->model_code, result); 4351141cc406Sopenharmony_ci 4352141cc406Sopenharmony_ci 4353141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4354141cc406Sopenharmony_ci} 4355141cc406Sopenharmony_ci 4356141cc406Sopenharmony_ci 4357141cc406Sopenharmony_ci/*---------- scsi_read_attributes() ------------------------------------------*/ 4358141cc406Sopenharmony_ci 4359141cc406Sopenharmony_cistatic SANE_Status 4360141cc406Sopenharmony_ciscsi_read_attributes(Microtek2_Info *pmi, char *device, uint8_t scan_source) 4361141cc406Sopenharmony_ci{ 4362141cc406Sopenharmony_ci SANE_Status status; 4363141cc406Sopenharmony_ci Microtek2_Info *mi; 4364141cc406Sopenharmony_ci uint8_t readattributes[RSA_CMD_L]; 4365141cc406Sopenharmony_ci uint8_t result[RSA_TRANSFERLENGTH]; 4366141cc406Sopenharmony_ci size_t size; 4367141cc406Sopenharmony_ci int sfd; 4368141cc406Sopenharmony_ci 4369141cc406Sopenharmony_ci 4370141cc406Sopenharmony_ci mi = &pmi[scan_source]; 4371141cc406Sopenharmony_ci 4372141cc406Sopenharmony_ci DBG(30, "scsi_read_attributes: mi=%p, device='%s', source=%d\n", 4373141cc406Sopenharmony_ci (void *) mi, device, scan_source); 4374141cc406Sopenharmony_ci 4375141cc406Sopenharmony_ci RSA_CMD(readattributes); 4376141cc406Sopenharmony_ci RSA_SETMEDIA(readattributes, scan_source); 4377141cc406Sopenharmony_ci status = sanei_scsi_open(device, &sfd, scsi_sense_handler, 0); 4378141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4379141cc406Sopenharmony_ci { 4380141cc406Sopenharmony_ci DBG(1, "scsi_read_attributes: open '%s'\n", sane_strstatus(status)); 4381141cc406Sopenharmony_ci return status; 4382141cc406Sopenharmony_ci } 4383141cc406Sopenharmony_ci 4384141cc406Sopenharmony_ci if (md_dump >= 2 ) 4385141cc406Sopenharmony_ci dump_area2(readattributes, sizeof(readattributes), "scannerattributes"); 4386141cc406Sopenharmony_ci 4387141cc406Sopenharmony_ci size = sizeof(result); 4388141cc406Sopenharmony_ci status = sanei_scsi_cmd(sfd, readattributes, 4389141cc406Sopenharmony_ci sizeof(readattributes), result, &size); 4390141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4391141cc406Sopenharmony_ci { 4392141cc406Sopenharmony_ci DBG(1, "scsi_read_attributes: cmd '%s'\n", sane_strstatus(status)); 4393141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4394141cc406Sopenharmony_ci return status; 4395141cc406Sopenharmony_ci } 4396141cc406Sopenharmony_ci 4397141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4398141cc406Sopenharmony_ci 4399141cc406Sopenharmony_ci /* The X6 appears to lie about the data format for a TMA */ 4400141cc406Sopenharmony_ci if ( (&pmi[0])->model_code == 0x91 ) 4401141cc406Sopenharmony_ci result[0] &= 0xfd; 4402141cc406Sopenharmony_ci /* default value for calib_divisor ... bit49?? */ 4403141cc406Sopenharmony_ci mi->calib_divisor = 1; 4404141cc406Sopenharmony_ci /* 9600XL */ 4405141cc406Sopenharmony_ci if ( (&pmi[0])->model_code == 0xde ) 4406141cc406Sopenharmony_ci mi->calib_divisor = 2; 4407141cc406Sopenharmony_ci /* 6400XL has problems in lineart mode*/ 4408141cc406Sopenharmony_ci if ( (&pmi[0])->model_code == 0x89 ) 4409141cc406Sopenharmony_ci result[13] &= 0xfe; /* simulate no lineart */ 4410141cc406Sopenharmony_ci#if 0 4411141cc406Sopenharmony_ci result[13] &= 0xfe; /* simulate no lineart */ 4412141cc406Sopenharmony_ci#endif 4413141cc406Sopenharmony_ci 4414141cc406Sopenharmony_ci /* copy all the stuff into the info structure */ 4415141cc406Sopenharmony_ci RSA_COLOR(mi->color, result); 4416141cc406Sopenharmony_ci RSA_ONEPASS(mi->onepass, result); 4417141cc406Sopenharmony_ci RSA_SCANNERTYPE(mi->scanner_type, result); 4418141cc406Sopenharmony_ci RSA_FEPROM(mi->feprom, result); 4419141cc406Sopenharmony_ci RSA_DATAFORMAT(mi->data_format, result); 4420141cc406Sopenharmony_ci RSA_COLORSEQUENCE(mi->color_sequence, result); 4421141cc406Sopenharmony_ci RSA_NIS(mi->new_image_status, result); 4422141cc406Sopenharmony_ci RSA_DATSEQ(mi->direction, result); 4423141cc406Sopenharmony_ci RSA_CCDGAP(mi->ccd_gap, result); 4424141cc406Sopenharmony_ci RSA_MAX_XRESOLUTION(mi->max_xresolution, result); 4425141cc406Sopenharmony_ci RSA_MAX_YRESOLUTION(mi->max_yresolution, result); 4426141cc406Sopenharmony_ci RSA_GEOWIDTH(mi->geo_width, result); 4427141cc406Sopenharmony_ci RSA_GEOHEIGHT(mi->geo_height, result); 4428141cc406Sopenharmony_ci RSA_OPTRESOLUTION(mi->opt_resolution, result); 4429141cc406Sopenharmony_ci RSA_DEPTH(mi->depth, result); 4430141cc406Sopenharmony_ci /* The X12USL doesn't say that it has 14bit */ 4431141cc406Sopenharmony_ci if ( (&pmi[0])->model_code == 0xb0 ) 4432141cc406Sopenharmony_ci mi->depth |= MI_HASDEPTH_14; 4433141cc406Sopenharmony_ci RSA_SCANMODE(mi->scanmode, result); 4434141cc406Sopenharmony_ci RSA_CCDPIXELS(mi->ccd_pixels, result); 4435141cc406Sopenharmony_ci RSA_LUTCAP(mi->lut_cap, result); 4436141cc406Sopenharmony_ci RSA_DNLDPTRN(mi->has_dnldptrn, result); 4437141cc406Sopenharmony_ci RSA_GRAINSLCT(mi->grain_slct, result); 4438141cc406Sopenharmony_ci RSA_SUPPOPT(mi->option_device, result); 4439141cc406Sopenharmony_ci RSA_CALIBWHITE(mi->calib_white, result); 4440141cc406Sopenharmony_ci RSA_CALIBSPACE(mi->calib_space, result); 4441141cc406Sopenharmony_ci RSA_NLENS(mi->nlens, result); 4442141cc406Sopenharmony_ci RSA_NWINDOWS(mi->nwindows, result); 4443141cc406Sopenharmony_ci RSA_SHTRNSFEREQU(mi->shtrnsferequ, result); 4444141cc406Sopenharmony_ci RSA_SCNBTTN(mi->scnbuttn, result); 4445141cc406Sopenharmony_ci RSA_BUFTYPE(mi->buftype, result); 4446141cc406Sopenharmony_ci RSA_REDBALANCE(mi->balance[0], result); 4447141cc406Sopenharmony_ci RSA_GREENBALANCE(mi->balance[1], result); 4448141cc406Sopenharmony_ci RSA_BLUEBALANCE(mi->balance[2], result); 4449141cc406Sopenharmony_ci RSA_APSMAXFRAMES(mi->aps_maxframes, result); 4450141cc406Sopenharmony_ci 4451141cc406Sopenharmony_ci if (md_dump >= 2 ) 4452141cc406Sopenharmony_ci dump_area2((uint8_t *) result, sizeof(result), 4453141cc406Sopenharmony_ci "scannerattributesresults"); 4454141cc406Sopenharmony_ci if ( md_dump >= 1 && md_dump_clear ) 4455141cc406Sopenharmony_ci dump_attributes(mi); 4456141cc406Sopenharmony_ci 4457141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4458141cc406Sopenharmony_ci} 4459141cc406Sopenharmony_ci 4460141cc406Sopenharmony_ci 4461141cc406Sopenharmony_ci/*---------- scsi_read_control_bits() ----------------------------------------*/ 4462141cc406Sopenharmony_ci 4463141cc406Sopenharmony_cistatic SANE_Status 4464141cc406Sopenharmony_ciscsi_read_control_bits(Microtek2_Scanner *ms) 4465141cc406Sopenharmony_ci{ 4466141cc406Sopenharmony_ci SANE_Status status; 4467141cc406Sopenharmony_ci uint8_t cmd[RCB_CMD_L]; 4468141cc406Sopenharmony_ci uint32_t byte; 4469141cc406Sopenharmony_ci int bit; 4470141cc406Sopenharmony_ci int count_1s; 4471141cc406Sopenharmony_ci 4472141cc406Sopenharmony_ci DBG(30, "scsi_read_control_bits: ms=%p, fd=%d\n", (void *) ms, ms->sfd); 4473141cc406Sopenharmony_ci DBG(30, "ms->control_bytes = %p\n", (void *) ms->control_bytes); 4474141cc406Sopenharmony_ci 4475141cc406Sopenharmony_ci RCB_SET_CMD(cmd); 4476141cc406Sopenharmony_ci RCB_SET_LENGTH(cmd, ms->n_control_bytes); 4477141cc406Sopenharmony_ci 4478141cc406Sopenharmony_ci if ( md_dump >= 2) 4479141cc406Sopenharmony_ci dump_area2(cmd, RCB_CMD_L, "readcontrolbits"); 4480141cc406Sopenharmony_ci 4481141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, 4482141cc406Sopenharmony_ci cmd, 4483141cc406Sopenharmony_ci sizeof(cmd), 4484141cc406Sopenharmony_ci ms->control_bytes, 4485141cc406Sopenharmony_ci &ms->n_control_bytes); 4486141cc406Sopenharmony_ci 4487141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4488141cc406Sopenharmony_ci { 4489141cc406Sopenharmony_ci DBG(1, "scsi_read_control_bits: cmd '%s'\n", sane_strstatus(status)); 4490141cc406Sopenharmony_ci return status; 4491141cc406Sopenharmony_ci } 4492141cc406Sopenharmony_ci 4493141cc406Sopenharmony_ci if ( md_dump >= 2) 4494141cc406Sopenharmony_ci dump_area2(ms->control_bytes, 4495141cc406Sopenharmony_ci ms->n_control_bytes, 4496141cc406Sopenharmony_ci "readcontrolbitsresult"); 4497141cc406Sopenharmony_ci 4498141cc406Sopenharmony_ci count_1s = 0; 4499141cc406Sopenharmony_ci for ( byte = 0; byte < ms->n_control_bytes; byte++ ) 4500141cc406Sopenharmony_ci { 4501141cc406Sopenharmony_ci for ( bit = 0; bit < 8; bit++ ) 4502141cc406Sopenharmony_ci { 4503141cc406Sopenharmony_ci if ( (ms->control_bytes[byte] >> bit) & 0x01 ) 4504141cc406Sopenharmony_ci ++count_1s; 4505141cc406Sopenharmony_ci } 4506141cc406Sopenharmony_ci } 4507141cc406Sopenharmony_ci DBG(20, "read_control_bits: number of 1's in controlbytes: %d\n", count_1s); 4508141cc406Sopenharmony_ci 4509141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4510141cc406Sopenharmony_ci} 4511141cc406Sopenharmony_ci 4512141cc406Sopenharmony_ci 4513141cc406Sopenharmony_ci/*---------- scsi_set_window() -----------------------------------------------*/ 4514141cc406Sopenharmony_ci 4515141cc406Sopenharmony_cistatic SANE_Status 4516141cc406Sopenharmony_ciscsi_set_window(Microtek2_Scanner *ms, int n) { /* n windows, not yet */ 4517141cc406Sopenharmony_ci /* implemented */ 4518141cc406Sopenharmony_ci SANE_Status status; 4519141cc406Sopenharmony_ci uint8_t *setwindow; 4520141cc406Sopenharmony_ci int size; 4521141cc406Sopenharmony_ci 4522141cc406Sopenharmony_ci 4523141cc406Sopenharmony_ci DBG(30, "scsi_set_window: ms=%p, wnd=%d\n", (void *) ms, n); 4524141cc406Sopenharmony_ci 4525141cc406Sopenharmony_ci size = SW_CMD_L + SW_HEADER_L + n * SW_BODY_L; 4526141cc406Sopenharmony_ci setwindow = (uint8_t *) malloc(size); 4527141cc406Sopenharmony_ci DBG(100, "scsi_set_window: setwindow= %p, malloc'd %d Bytes\n", 4528141cc406Sopenharmony_ci (void *) setwindow, size); 4529141cc406Sopenharmony_ci if ( setwindow == NULL ) 4530141cc406Sopenharmony_ci { 4531141cc406Sopenharmony_ci DBG(1, "scsi_set_window: malloc for setwindow failed\n"); 4532141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 4533141cc406Sopenharmony_ci } 4534141cc406Sopenharmony_ci memset(setwindow, 0, size); 4535141cc406Sopenharmony_ci 4536141cc406Sopenharmony_ci SW_CMD(setwindow); 4537141cc406Sopenharmony_ci SW_PARAM_LENGTH(setwindow, SW_HEADER_L + n * SW_BODY_L); 4538141cc406Sopenharmony_ci SW_WNDDESCLEN(setwindow + SW_HEADER_P, SW_WNDDESCVAL); 4539141cc406Sopenharmony_ci 4540141cc406Sopenharmony_ci#define POS (setwindow + SW_BODY_P(n-1)) 4541141cc406Sopenharmony_ci 4542141cc406Sopenharmony_ci SW_WNDID(POS, n-1); 4543141cc406Sopenharmony_ci SW_XRESDPI(POS, ms->x_resolution_dpi); 4544141cc406Sopenharmony_ci SW_YRESDPI(POS, ms->y_resolution_dpi); 4545141cc406Sopenharmony_ci SW_XPOSTL(POS, ms->x1_dots); 4546141cc406Sopenharmony_ci SW_YPOSTL(POS, ms->y1_dots); 4547141cc406Sopenharmony_ci SW_WNDWIDTH(POS, ms->width_dots); 4548141cc406Sopenharmony_ci SW_WNDHEIGHT(POS, ms->height_dots); 4549141cc406Sopenharmony_ci SW_THRESHOLD(POS, ms->threshold); 4550141cc406Sopenharmony_ci SW_IMGCOMP(POS, ms->mode); 4551141cc406Sopenharmony_ci SW_BITSPERPIXEL(POS, ms->depth); 4552141cc406Sopenharmony_ci SW_EXTHT(POS, ms->use_external_ht); 4553141cc406Sopenharmony_ci SW_INTHTINDEX(POS, ms->internal_ht_index); 4554141cc406Sopenharmony_ci SW_RIF(POS, 1); 4555141cc406Sopenharmony_ci SW_LENS(POS, 0); /* ???? */ 4556141cc406Sopenharmony_ci SW_INFINITE(POS, 0); 4557141cc406Sopenharmony_ci SW_STAY(POS, ms->stay); 4558141cc406Sopenharmony_ci SW_RAWDAT(POS, ms->rawdat); 4559141cc406Sopenharmony_ci SW_QUALITY(POS, ms->quality); 4560141cc406Sopenharmony_ci SW_FASTSCAN(POS, ms->fastscan); 4561141cc406Sopenharmony_ci SW_MEDIA(POS, ms->scan_source); 4562141cc406Sopenharmony_ci SW_BRIGHTNESS_M(POS, ms->brightness_m); 4563141cc406Sopenharmony_ci SW_CONTRAST_M(POS, ms->contrast_m); 4564141cc406Sopenharmony_ci SW_EXPOSURE_M(POS, ms->exposure_m); 4565141cc406Sopenharmony_ci SW_SHADOW_M(POS, ms->shadow_m); 4566141cc406Sopenharmony_ci SW_MIDTONE_M(POS, ms->midtone_m); 4567141cc406Sopenharmony_ci SW_HIGHLIGHT_M(POS, ms->highlight_m); 4568141cc406Sopenharmony_ci /* the following properties are only referenced if it's a color scan */ 4569141cc406Sopenharmony_ci /* but I guess they don't matter at a gray scan */ 4570141cc406Sopenharmony_ci SW_BRIGHTNESS_R(POS, ms->brightness_r); 4571141cc406Sopenharmony_ci SW_CONTRAST_R(POS, ms->contrast_r); 4572141cc406Sopenharmony_ci SW_EXPOSURE_R(POS, ms->exposure_r); 4573141cc406Sopenharmony_ci SW_SHADOW_R(POS, ms->shadow_r); 4574141cc406Sopenharmony_ci SW_MIDTONE_R(POS, ms->midtone_r); 4575141cc406Sopenharmony_ci SW_HIGHLIGHT_R(POS, ms->highlight_r); 4576141cc406Sopenharmony_ci SW_BRIGHTNESS_G(POS, ms->brightness_g); 4577141cc406Sopenharmony_ci SW_CONTRAST_G(POS, ms->contrast_g); 4578141cc406Sopenharmony_ci SW_EXPOSURE_G(POS, ms->exposure_g); 4579141cc406Sopenharmony_ci SW_SHADOW_G(POS, ms->shadow_g); 4580141cc406Sopenharmony_ci SW_MIDTONE_G(POS, ms->midtone_g); 4581141cc406Sopenharmony_ci SW_HIGHLIGHT_G(POS, ms->highlight_g); 4582141cc406Sopenharmony_ci SW_BRIGHTNESS_B(POS, ms->brightness_b); 4583141cc406Sopenharmony_ci SW_CONTRAST_B(POS, ms->contrast_b); 4584141cc406Sopenharmony_ci SW_EXPOSURE_B(POS, ms->exposure_b); 4585141cc406Sopenharmony_ci SW_SHADOW_B(POS, ms->shadow_b); 4586141cc406Sopenharmony_ci SW_MIDTONE_B(POS, ms->midtone_b); 4587141cc406Sopenharmony_ci SW_HIGHLIGHT_B(POS, ms->highlight_b); 4588141cc406Sopenharmony_ci 4589141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4590141cc406Sopenharmony_ci { 4591141cc406Sopenharmony_ci dump_area2(setwindow, 10, "setwindowcmd"); 4592141cc406Sopenharmony_ci dump_area2(setwindow + 10 ,8 , "setwindowheader"); 4593141cc406Sopenharmony_ci dump_area2(setwindow + 18 ,61 , "setwindowbody"); 4594141cc406Sopenharmony_ci } 4595141cc406Sopenharmony_ci 4596141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, setwindow, size, NULL, 0); 4597141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4598141cc406Sopenharmony_ci DBG(1, "scsi_set_window: '%s'\n", sane_strstatus(status)); 4599141cc406Sopenharmony_ci 4600141cc406Sopenharmony_ci DBG(100, "scsi_set_window: free setwindow at %p\n", (void *) setwindow); 4601141cc406Sopenharmony_ci free((void *) setwindow); 4602141cc406Sopenharmony_ci return status; 4603141cc406Sopenharmony_ci} 4604141cc406Sopenharmony_ci 4605141cc406Sopenharmony_ci 4606141cc406Sopenharmony_ci/*---------- scsi_read_image_info() ------------------------------------------*/ 4607141cc406Sopenharmony_ci 4608141cc406Sopenharmony_cistatic SANE_Status 4609141cc406Sopenharmony_ciscsi_read_image_info(Microtek2_Scanner *ms) 4610141cc406Sopenharmony_ci{ 4611141cc406Sopenharmony_ci uint8_t cmd[RII_CMD_L]; 4612141cc406Sopenharmony_ci uint8_t result[RII_RESULT_L]; 4613141cc406Sopenharmony_ci size_t size; 4614141cc406Sopenharmony_ci SANE_Status status; 4615141cc406Sopenharmony_ci Microtek2_Device *md; 4616141cc406Sopenharmony_ci 4617141cc406Sopenharmony_ci md = ms->dev; 4618141cc406Sopenharmony_ci 4619141cc406Sopenharmony_ci DBG(30, "scsi_read_image_info: ms=%p\n", (void *) ms); 4620141cc406Sopenharmony_ci 4621141cc406Sopenharmony_ci RII_SET_CMD(cmd); 4622141cc406Sopenharmony_ci 4623141cc406Sopenharmony_ci if ( md_dump >= 2) 4624141cc406Sopenharmony_ci dump_area2(cmd, RII_CMD_L, "readimageinfo"); 4625141cc406Sopenharmony_ci 4626141cc406Sopenharmony_ci size = sizeof(result); 4627141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), result, &size); 4628141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4629141cc406Sopenharmony_ci { 4630141cc406Sopenharmony_ci DBG(1, "scsi_read_image_info: '%s'\n", sane_strstatus(status)); 4631141cc406Sopenharmony_ci return status; 4632141cc406Sopenharmony_ci } 4633141cc406Sopenharmony_ci 4634141cc406Sopenharmony_ci if ( md_dump >= 2) 4635141cc406Sopenharmony_ci dump_area2(result, size, "readimageinforesult"); 4636141cc406Sopenharmony_ci 4637141cc406Sopenharmony_ci /* The V300 returns some values in only two bytes */ 4638141cc406Sopenharmony_ci if ( !(md->revision==2.70) && (md->model_flags & MD_RII_TWO_BYTES) ) 4639141cc406Sopenharmony_ci { 4640141cc406Sopenharmony_ci RII_GET_V300_WIDTHPIXEL(ms->ppl, result); 4641141cc406Sopenharmony_ci RII_GET_V300_WIDTHBYTES(ms->bpl, result); 4642141cc406Sopenharmony_ci RII_GET_V300_HEIGHTLINES(ms->src_remaining_lines, result); 4643141cc406Sopenharmony_ci RII_GET_V300_REMAINBYTES(ms->remaining_bytes, result); 4644141cc406Sopenharmony_ci } 4645141cc406Sopenharmony_ci else 4646141cc406Sopenharmony_ci { 4647141cc406Sopenharmony_ci RII_GET_WIDTHPIXEL(ms->ppl, result); 4648141cc406Sopenharmony_ci RII_GET_WIDTHBYTES(ms->bpl, result); 4649141cc406Sopenharmony_ci RII_GET_HEIGHTLINES(ms->src_remaining_lines, result); 4650141cc406Sopenharmony_ci RII_GET_REMAINBYTES(ms->remaining_bytes, result); 4651141cc406Sopenharmony_ci } 4652141cc406Sopenharmony_ci 4653141cc406Sopenharmony_ci DBG(30, "scsi_read_image_info: ppl=%d, bpl=%d, lines=%d, remain=%d\n", 4654141cc406Sopenharmony_ci ms->ppl, ms->bpl, ms->src_remaining_lines, ms->remaining_bytes); 4655141cc406Sopenharmony_ci 4656141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4657141cc406Sopenharmony_ci} 4658141cc406Sopenharmony_ci 4659141cc406Sopenharmony_ci 4660141cc406Sopenharmony_ci/*---------- scsi_read_image() -----------------------------------------------*/ 4661141cc406Sopenharmony_ci 4662141cc406Sopenharmony_cistatic SANE_Status 4663141cc406Sopenharmony_ciscsi_read_image(Microtek2_Scanner *ms, uint8_t *buffer, int bytes_per_pixel) 4664141cc406Sopenharmony_ci{ 4665141cc406Sopenharmony_ci uint8_t cmd[RI_CMD_L]; 4666141cc406Sopenharmony_ci SANE_Bool endiantype; 4667141cc406Sopenharmony_ci SANE_Status status; 4668141cc406Sopenharmony_ci size_t size; 4669141cc406Sopenharmony_ci size_t i; 4670141cc406Sopenharmony_ci uint8_t tmp; 4671141cc406Sopenharmony_ci 4672141cc406Sopenharmony_ci 4673141cc406Sopenharmony_ci DBG(30, "scsi_read_image: ms=%p, buffer=%p\n", 4674141cc406Sopenharmony_ci (void *) ms, (void *) buffer); 4675141cc406Sopenharmony_ci 4676141cc406Sopenharmony_ci ENDIAN_TYPE(endiantype) 4677141cc406Sopenharmony_ci RI_SET_CMD(cmd); 4678141cc406Sopenharmony_ci RI_SET_PCORMAC(cmd, endiantype); 4679141cc406Sopenharmony_ci RI_SET_COLOR(cmd, ms->current_read_color); 4680141cc406Sopenharmony_ci RI_SET_TRANSFERLENGTH(cmd, ms->transfer_length); 4681141cc406Sopenharmony_ci 4682141cc406Sopenharmony_ci DBG(30, "scsi_read_image: transferlength=%d\n", ms->transfer_length); 4683141cc406Sopenharmony_ci 4684141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4685141cc406Sopenharmony_ci dump_area2(cmd, RI_CMD_L, "readimagecmd"); 4686141cc406Sopenharmony_ci 4687141cc406Sopenharmony_ci size = ms->transfer_length; 4688141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), buffer, &size); 4689141cc406Sopenharmony_ci 4690141cc406Sopenharmony_ci if ( buffer && ( ms->dev->model_flags & MD_PHANTOM_C6 ) && endiantype ) 4691141cc406Sopenharmony_ci { 4692141cc406Sopenharmony_ci switch(bytes_per_pixel) 4693141cc406Sopenharmony_ci { 4694141cc406Sopenharmony_ci case 1: break; 4695141cc406Sopenharmony_ci case 2: 4696141cc406Sopenharmony_ci for ( i = 1; i < size; i += 2 ) 4697141cc406Sopenharmony_ci { 4698141cc406Sopenharmony_ci tmp = buffer[i-1]; 4699141cc406Sopenharmony_ci buffer[i-1] = buffer[i]; 4700141cc406Sopenharmony_ci buffer[i] = tmp; 4701141cc406Sopenharmony_ci } 4702141cc406Sopenharmony_ci break; 4703141cc406Sopenharmony_ci default: 4704141cc406Sopenharmony_ci DBG(1, "scsi_read_image: Unexpected bytes_per_pixel=%d\n", bytes_per_pixel); 4705141cc406Sopenharmony_ci } 4706141cc406Sopenharmony_ci } 4707141cc406Sopenharmony_ci 4708141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4709141cc406Sopenharmony_ci DBG(1, "scsi_read_image: '%s'\n", sane_strstatus(status)); 4710141cc406Sopenharmony_ci 4711141cc406Sopenharmony_ci if ( md_dump > 3 ) 4712141cc406Sopenharmony_ci dump_area2(buffer, ms->transfer_length, "readimageresult"); 4713141cc406Sopenharmony_ci 4714141cc406Sopenharmony_ci return status; 4715141cc406Sopenharmony_ci} 4716141cc406Sopenharmony_ci 4717141cc406Sopenharmony_ci 4718141cc406Sopenharmony_ci/*---------- scsi_read_image_status() ----------------------------------------*/ 4719141cc406Sopenharmony_ci 4720141cc406Sopenharmony_cistatic SANE_Status 4721141cc406Sopenharmony_ciscsi_read_image_status(Microtek2_Scanner *ms) 4722141cc406Sopenharmony_ci{ 4723141cc406Sopenharmony_ci Microtek2_Device *md; 4724141cc406Sopenharmony_ci Microtek2_Info *mi; 4725141cc406Sopenharmony_ci uint8_t cmd[RIS_CMD_L]; 4726141cc406Sopenharmony_ci uint8_t dummy; 4727141cc406Sopenharmony_ci size_t dummy_length; 4728141cc406Sopenharmony_ci SANE_Status status; 4729141cc406Sopenharmony_ci SANE_Bool endian_type; 4730141cc406Sopenharmony_ci 4731141cc406Sopenharmony_ci md = ms->dev; 4732141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 4733141cc406Sopenharmony_ci 4734141cc406Sopenharmony_ci DBG(30, "scsi_read_image_status: ms=%p\n", (void *) ms); 4735141cc406Sopenharmony_ci 4736141cc406Sopenharmony_ci ENDIAN_TYPE(endian_type) 4737141cc406Sopenharmony_ci RIS_SET_CMD(cmd); 4738141cc406Sopenharmony_ci RIS_SET_PCORMAC(cmd, endian_type); 4739141cc406Sopenharmony_ci RIS_SET_COLOR(cmd, ms->current_read_color); 4740141cc406Sopenharmony_ci 4741141cc406Sopenharmony_ci/* mi->new_image_status = SANE_TRUE; */ /* for testing*/ 4742141cc406Sopenharmony_ci 4743141cc406Sopenharmony_ci if ( mi->new_image_status == SANE_TRUE ) 4744141cc406Sopenharmony_ci { 4745141cc406Sopenharmony_ci DBG(30, "scsi_read_image_status: use new image status \n"); 4746141cc406Sopenharmony_ci dummy_length = 1; 4747141cc406Sopenharmony_ci cmd[8] = 1; 4748141cc406Sopenharmony_ci } 4749141cc406Sopenharmony_ci else 4750141cc406Sopenharmony_ci { 4751141cc406Sopenharmony_ci DBG(30, "scsi_read_image_status: use old image status \n"); 4752141cc406Sopenharmony_ci dummy_length = 0; 4753141cc406Sopenharmony_ci cmd[8] = 0; 4754141cc406Sopenharmony_ci } 4755141cc406Sopenharmony_ci 4756141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4757141cc406Sopenharmony_ci dump_area2(cmd, sizeof(cmd), "readimagestatus"); 4758141cc406Sopenharmony_ci 4759141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), &dummy, &dummy_length); 4760141cc406Sopenharmony_ci 4761141cc406Sopenharmony_ci if ( mi->new_image_status == SANE_TRUE ) 4762141cc406Sopenharmony_ci { 4763141cc406Sopenharmony_ci if ( dummy == 0 ) 4764141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 4765141cc406Sopenharmony_ci else 4766141cc406Sopenharmony_ci status = SANE_STATUS_DEVICE_BUSY; 4767141cc406Sopenharmony_ci } 4768141cc406Sopenharmony_ci 4769141cc406Sopenharmony_ci /* For some (X6USB) scanner 4770141cc406Sopenharmony_ci We say we are going to try to read 1 byte of data (as recommended 4771141cc406Sopenharmony_ci in the Microtek SCSI command documentation under "New Image Status") 4772141cc406Sopenharmony_ci so that dubious SCSI host adapters (like the one in at least some 4773141cc406Sopenharmony_ci Microtek X6 USB scanners) don't get wedged trying to do a zero 4774141cc406Sopenharmony_ci length read. However, we do not actually try to read this byte of 4775141cc406Sopenharmony_ci data, as that wedges the USB scanner as well. 4776141cc406Sopenharmony_ci IOW the SCSI command says we are going to read 1 byte, but in fact 4777141cc406Sopenharmony_ci we don't: */ 4778141cc406Sopenharmony_ci /*cmd[8] = 1; 4779141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), &dummy, 0); */ 4780141cc406Sopenharmony_ci 4781141cc406Sopenharmony_ci 4782141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4783141cc406Sopenharmony_ci DBG(1, "scsi_read_image_status: '%s'\n", sane_strstatus(status)); 4784141cc406Sopenharmony_ci 4785141cc406Sopenharmony_ci return status; 4786141cc406Sopenharmony_ci} 4787141cc406Sopenharmony_ci 4788141cc406Sopenharmony_ci/*---------- scsi_read_shading () --------------------------------------------*/ 4789141cc406Sopenharmony_ci 4790141cc406Sopenharmony_cistatic SANE_Status 4791141cc406Sopenharmony_ciscsi_read_shading(Microtek2_Scanner *ms, uint8_t *buffer, uint32_t length) 4792141cc406Sopenharmony_ci{ 4793141cc406Sopenharmony_ci uint8_t cmd[RSI_CMD_L]; 4794141cc406Sopenharmony_ci SANE_Bool endiantype; 4795141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 4796141cc406Sopenharmony_ci size_t size; 4797141cc406Sopenharmony_ci 4798141cc406Sopenharmony_ci DBG(30, "scsi_read_shading: pos=%p, size=%d, word=%d, color=%d, dark=%d\n", 4799141cc406Sopenharmony_ci (void *) buffer, length, ms->word, ms->current_color, ms->dark); 4800141cc406Sopenharmony_ci 4801141cc406Sopenharmony_ci size = length; 4802141cc406Sopenharmony_ci 4803141cc406Sopenharmony_ci RSI_SET_CMD(cmd); 4804141cc406Sopenharmony_ci ENDIAN_TYPE(endiantype) 4805141cc406Sopenharmony_ci RSI_SET_PCORMAC(cmd, endiantype); 4806141cc406Sopenharmony_ci RSI_SET_COLOR(cmd, ms->current_color); 4807141cc406Sopenharmony_ci RSI_SET_DARK(cmd, ms->dark); 4808141cc406Sopenharmony_ci RSI_SET_WORD(cmd, ms->word); 4809141cc406Sopenharmony_ci RSI_SET_TRANSFERLENGTH(cmd, size); 4810141cc406Sopenharmony_ci 4811141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4812141cc406Sopenharmony_ci dump_area2(cmd, RSI_CMD_L, "readshading"); 4813141cc406Sopenharmony_ci 4814141cc406Sopenharmony_ci DBG(100, "scsi_read_shading: sfd=%d, cmd=%p, sizeofcmd=%lu," 4815141cc406Sopenharmony_ci "dest=%p, destsize=%lu\n", 4816141cc406Sopenharmony_ci ms->sfd, (void *) cmd, (u_long) sizeof(cmd), (void *) buffer, 4817141cc406Sopenharmony_ci (u_long) size); 4818141cc406Sopenharmony_ci 4819141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), buffer, &size); 4820141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4821141cc406Sopenharmony_ci DBG(1, "scsi_read_shading: '%s'\n", sane_strstatus(status)); 4822141cc406Sopenharmony_ci 4823141cc406Sopenharmony_ci if ( md_dump > 3) 4824141cc406Sopenharmony_ci dump_area2(buffer, 4825141cc406Sopenharmony_ci size, 4826141cc406Sopenharmony_ci "readshadingresult"); 4827141cc406Sopenharmony_ci 4828141cc406Sopenharmony_ci return status; 4829141cc406Sopenharmony_ci} 4830141cc406Sopenharmony_ci 4831141cc406Sopenharmony_ci 4832141cc406Sopenharmony_ci/*---------- scsi_send_shading () --------------------------------------------*/ 4833141cc406Sopenharmony_ci 4834141cc406Sopenharmony_cistatic SANE_Status 4835141cc406Sopenharmony_ciscsi_send_shading(Microtek2_Scanner *ms, 4836141cc406Sopenharmony_ci uint8_t *shading_data, 4837141cc406Sopenharmony_ci uint32_t length, 4838141cc406Sopenharmony_ci uint8_t dark) 4839141cc406Sopenharmony_ci{ 4840141cc406Sopenharmony_ci SANE_Bool endiantype; 4841141cc406Sopenharmony_ci SANE_Status status; 4842141cc406Sopenharmony_ci size_t size; 4843141cc406Sopenharmony_ci uint8_t *cmd; 4844141cc406Sopenharmony_ci 4845141cc406Sopenharmony_ci 4846141cc406Sopenharmony_ci DBG(30, "scsi_send_shading: pos=%p, size=%d, word=%d, color=%d, dark=%d\n", 4847141cc406Sopenharmony_ci (void *) shading_data, length, ms->word, ms->current_color, dark); 4848141cc406Sopenharmony_ci 4849141cc406Sopenharmony_ci cmd = (uint8_t *) malloc(SSI_CMD_L + length); 4850141cc406Sopenharmony_ci DBG(100, "scsi_send_shading: cmd=%p, malloc'd %d bytes\n", 4851141cc406Sopenharmony_ci (void *) cmd, SSI_CMD_L + length); 4852141cc406Sopenharmony_ci if ( cmd == NULL ) 4853141cc406Sopenharmony_ci { 4854141cc406Sopenharmony_ci DBG(1, "scsi_send_shading: Couldn't get buffer for shading table\n"); 4855141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 4856141cc406Sopenharmony_ci } 4857141cc406Sopenharmony_ci 4858141cc406Sopenharmony_ci SSI_SET_CMD(cmd); 4859141cc406Sopenharmony_ci ENDIAN_TYPE(endiantype) 4860141cc406Sopenharmony_ci SSI_SET_PCORMAC(cmd, endiantype); 4861141cc406Sopenharmony_ci SSI_SET_COLOR(cmd, ms->current_color); 4862141cc406Sopenharmony_ci SSI_SET_DARK(cmd, dark); 4863141cc406Sopenharmony_ci SSI_SET_WORD(cmd, ms->word); 4864141cc406Sopenharmony_ci SSI_SET_TRANSFERLENGTH(cmd, length); 4865141cc406Sopenharmony_ci memcpy(cmd + SSI_CMD_L, shading_data, length); 4866141cc406Sopenharmony_ci size = length; 4867141cc406Sopenharmony_ci 4868141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4869141cc406Sopenharmony_ci dump_area2(cmd, SSI_CMD_L, "sendshading"); 4870141cc406Sopenharmony_ci if ( md_dump >= 3 ) 4871141cc406Sopenharmony_ci dump_area2(cmd + SSI_CMD_L, size, "sendshadingdata"); 4872141cc406Sopenharmony_ci 4873141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, cmd, size + SSI_CMD_L, NULL, 0); 4874141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4875141cc406Sopenharmony_ci DBG(1, "scsi_send_shading: '%s'\n", sane_strstatus(status)); 4876141cc406Sopenharmony_ci 4877141cc406Sopenharmony_ci DBG(100, "free cmd at %p\n", (void *) cmd); 4878141cc406Sopenharmony_ci free((void *) cmd); 4879141cc406Sopenharmony_ci 4880141cc406Sopenharmony_ci return status; 4881141cc406Sopenharmony_ci 4882141cc406Sopenharmony_ci} 4883141cc406Sopenharmony_ci 4884141cc406Sopenharmony_ci 4885141cc406Sopenharmony_ci/*---------- scsi_read_system_status() ---------------------------------------*/ 4886141cc406Sopenharmony_ci 4887141cc406Sopenharmony_cistatic SANE_Status 4888141cc406Sopenharmony_ciscsi_read_system_status(Microtek2_Device *md, int fd) 4889141cc406Sopenharmony_ci{ 4890141cc406Sopenharmony_ci uint8_t cmd[RSS_CMD_L]; 4891141cc406Sopenharmony_ci uint8_t result[RSS_RESULT_L]; 4892141cc406Sopenharmony_ci int sfd; 4893141cc406Sopenharmony_ci size_t size; 4894141cc406Sopenharmony_ci SANE_Status status; 4895141cc406Sopenharmony_ci 4896141cc406Sopenharmony_ci DBG(30, "scsi_read_system_status: md=%p, fd=%d\n", (void *) md, fd); 4897141cc406Sopenharmony_ci 4898141cc406Sopenharmony_ci if ( fd == -1 ) 4899141cc406Sopenharmony_ci { 4900141cc406Sopenharmony_ci status = sanei_scsi_open(md->name, &sfd, scsi_sense_handler, 0); 4901141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4902141cc406Sopenharmony_ci { 4903141cc406Sopenharmony_ci DBG(1, "scsi_read_system_status: open '%s'\n", 4904141cc406Sopenharmony_ci sane_strstatus(status)); 4905141cc406Sopenharmony_ci return status; 4906141cc406Sopenharmony_ci } 4907141cc406Sopenharmony_ci } 4908141cc406Sopenharmony_ci else 4909141cc406Sopenharmony_ci sfd = fd; 4910141cc406Sopenharmony_ci 4911141cc406Sopenharmony_ci RSS_CMD(cmd); 4912141cc406Sopenharmony_ci 4913141cc406Sopenharmony_ci if ( md_dump >= 2) 4914141cc406Sopenharmony_ci dump_area2(cmd, RSS_CMD_L, "readsystemstatus"); 4915141cc406Sopenharmony_ci 4916141cc406Sopenharmony_ci size = sizeof(result); 4917141cc406Sopenharmony_ci status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), result, &size); 4918141cc406Sopenharmony_ci 4919141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4920141cc406Sopenharmony_ci { 4921141cc406Sopenharmony_ci DBG(1, "scsi_read_system_status: cmd '%s'\n", sane_strstatus(status)); 4922141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4923141cc406Sopenharmony_ci return status; 4924141cc406Sopenharmony_ci } 4925141cc406Sopenharmony_ci 4926141cc406Sopenharmony_ci if ( fd == -1 ) 4927141cc406Sopenharmony_ci sanei_scsi_close(sfd); 4928141cc406Sopenharmony_ci 4929141cc406Sopenharmony_ci if ( md_dump >= 2) 4930141cc406Sopenharmony_ci dump_area2(result, size, "readsystemstatusresult"); 4931141cc406Sopenharmony_ci 4932141cc406Sopenharmony_ci md->status.sskip = RSS_SSKIP(result); 4933141cc406Sopenharmony_ci md->status.ntrack = RSS_NTRACK(result); 4934141cc406Sopenharmony_ci md->status.ncalib = RSS_NCALIB(result); 4935141cc406Sopenharmony_ci md->status.tlamp = RSS_TLAMP(result); 4936141cc406Sopenharmony_ci md->status.flamp = RSS_FLAMP(result); 4937141cc406Sopenharmony_ci md->status.rdyman= RSS_RDYMAN(result); 4938141cc406Sopenharmony_ci md->status.trdy = RSS_TRDY(result); 4939141cc406Sopenharmony_ci md->status.frdy = RSS_FRDY(result); 4940141cc406Sopenharmony_ci md->status.adp = RSS_RDYMAN(result); 4941141cc406Sopenharmony_ci md->status.detect = RSS_DETECT(result); 4942141cc406Sopenharmony_ci md->status.adptime = RSS_ADPTIME(result); 4943141cc406Sopenharmony_ci md->status.lensstatus = RSS_LENSSTATUS(result); 4944141cc406Sopenharmony_ci md->status.aloff = RSS_ALOFF(result); 4945141cc406Sopenharmony_ci md->status.timeremain = RSS_TIMEREMAIN(result); 4946141cc406Sopenharmony_ci md->status.tmacnt = RSS_TMACNT(result); 4947141cc406Sopenharmony_ci md->status.paper = RSS_PAPER(result); 4948141cc406Sopenharmony_ci md->status.adfcnt = RSS_ADFCNT(result); 4949141cc406Sopenharmony_ci md->status.currentmode = RSS_CURRENTMODE(result); 4950141cc406Sopenharmony_ci md->status.buttoncount = RSS_BUTTONCOUNT(result); 4951141cc406Sopenharmony_ci 4952141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4953141cc406Sopenharmony_ci} 4954141cc406Sopenharmony_ci 4955141cc406Sopenharmony_ci 4956141cc406Sopenharmony_ci/*---------- scsi_request_sense() --------------------------------------------*/ 4957141cc406Sopenharmony_ci 4958141cc406Sopenharmony_ci/* currently not used */ 4959141cc406Sopenharmony_ci 4960141cc406Sopenharmony_ci#if 0 4961141cc406Sopenharmony_ci 4962141cc406Sopenharmony_cistatic SANE_Status 4963141cc406Sopenharmony_ciscsi_request_sense(Microtek2_Scanner *ms) 4964141cc406Sopenharmony_ci{ 4965141cc406Sopenharmony_ci uint8_t requestsense[RQS_CMD_L]; 4966141cc406Sopenharmony_ci uint8_t buffer[100]; 4967141cc406Sopenharmony_ci SANE_Status status; 4968141cc406Sopenharmony_ci int size; 4969141cc406Sopenharmony_ci int asl; 4970141cc406Sopenharmony_ci int as_info_length; 4971141cc406Sopenharmony_ci 4972141cc406Sopenharmony_ci DBG(30, "scsi_request_sense: ms=%p\n", (void *) ms); 4973141cc406Sopenharmony_ci 4974141cc406Sopenharmony_ci RQS_CMD(requestsense); 4975141cc406Sopenharmony_ci RQS_ALLOCLENGTH(requestsense, 100); 4976141cc406Sopenharmony_ci 4977141cc406Sopenharmony_ci size = sizeof(buffer); 4978141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, requestsense, sizeof(requestsense), 4979141cc406Sopenharmony_ci buffer, &size); 4980141cc406Sopenharmony_ci 4981141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 4982141cc406Sopenharmony_ci { 4983141cc406Sopenharmony_ci DBG(1, "scsi_request_sense: '%s'\n", sane_strstatus(status)); 4984141cc406Sopenharmony_ci return status; 4985141cc406Sopenharmony_ci } 4986141cc406Sopenharmony_ci 4987141cc406Sopenharmony_ci if ( md_dump >= 2 ) 4988141cc406Sopenharmony_ci dump_area2(buffer, size, "requestsenseresult"); 4989141cc406Sopenharmony_ci 4990141cc406Sopenharmony_ci dump_area(buffer, RQS_LENGTH(buffer), "RequestSense"); 4991141cc406Sopenharmony_ci asl = RQS_ASL(buffer); 4992141cc406Sopenharmony_ci if ( (as_info_length = RQS_ASINFOLENGTH(buffer)) > 0 ) 4993141cc406Sopenharmony_ci DBG(25, "scsi_request_sense: info '%.*s'\n", 4994141cc406Sopenharmony_ci as_info_length, RQS_ASINFO(buffer)); 4995141cc406Sopenharmony_ci 4996141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4997141cc406Sopenharmony_ci} 4998141cc406Sopenharmony_ci#endif 4999141cc406Sopenharmony_ci 5000141cc406Sopenharmony_ci 5001141cc406Sopenharmony_ci/*---------- scsi_send_system_status() ---------------------------------------*/ 5002141cc406Sopenharmony_ci 5003141cc406Sopenharmony_cistatic SANE_Status 5004141cc406Sopenharmony_ciscsi_send_system_status(Microtek2_Device *md, int fd) 5005141cc406Sopenharmony_ci{ 5006141cc406Sopenharmony_ci uint8_t cmd[SSS_CMD_L + SSS_DATA_L]; 5007141cc406Sopenharmony_ci uint8_t *pos; 5008141cc406Sopenharmony_ci int sfd; 5009141cc406Sopenharmony_ci SANE_Status status; 5010141cc406Sopenharmony_ci 5011141cc406Sopenharmony_ci 5012141cc406Sopenharmony_ci DBG(30, "scsi_send_system_status: md=%p, fd=%d\n", (void *) md, fd); 5013141cc406Sopenharmony_ci 5014141cc406Sopenharmony_ci memset(cmd, 0, SSS_CMD_L + SSS_DATA_L); 5015141cc406Sopenharmony_ci if ( fd == -1 ) 5016141cc406Sopenharmony_ci { 5017141cc406Sopenharmony_ci status = sanei_scsi_open(md->name, &sfd, scsi_sense_handler, 0); 5018141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5019141cc406Sopenharmony_ci { 5020141cc406Sopenharmony_ci DBG(1, "scsi_send_system_status: open '%s'\n", 5021141cc406Sopenharmony_ci sane_strstatus(status)); 5022141cc406Sopenharmony_ci return status; 5023141cc406Sopenharmony_ci } 5024141cc406Sopenharmony_ci } 5025141cc406Sopenharmony_ci else 5026141cc406Sopenharmony_ci sfd = fd; 5027141cc406Sopenharmony_ci 5028141cc406Sopenharmony_ci SSS_CMD(cmd); 5029141cc406Sopenharmony_ci pos = cmd + SSS_CMD_L; 5030141cc406Sopenharmony_ci SSS_STICK(pos, md->status.stick); 5031141cc406Sopenharmony_ci SSS_NTRACK(pos, md->status.ntrack); 5032141cc406Sopenharmony_ci SSS_NCALIB(pos, md->status.ncalib); 5033141cc406Sopenharmony_ci SSS_TLAMP(pos, md->status.tlamp); 5034141cc406Sopenharmony_ci SSS_FLAMP(pos, md->status.flamp); 5035141cc406Sopenharmony_ci SSS_RESERVED17(pos, md->status.reserved17); 5036141cc406Sopenharmony_ci SSS_RDYMAN(pos, md->status.rdyman); 5037141cc406Sopenharmony_ci SSS_TRDY(pos, md->status.trdy); 5038141cc406Sopenharmony_ci SSS_FRDY(pos, md->status.frdy); 5039141cc406Sopenharmony_ci SSS_ADP(pos, md->status.adp); 5040141cc406Sopenharmony_ci SSS_DETECT(pos, md->status.detect); 5041141cc406Sopenharmony_ci SSS_ADPTIME(pos, md->status.adptime); 5042141cc406Sopenharmony_ci SSS_LENSSTATUS(pos, md->status.lensstatus); 5043141cc406Sopenharmony_ci SSS_ALOFF(pos, md->status.aloff); 5044141cc406Sopenharmony_ci SSS_TIMEREMAIN(pos, md->status.timeremain); 5045141cc406Sopenharmony_ci SSS_TMACNT(pos, md->status.tmacnt); 5046141cc406Sopenharmony_ci SSS_PAPER(pos, md->status.paper); 5047141cc406Sopenharmony_ci SSS_ADFCNT(pos, md->status.adfcnt); 5048141cc406Sopenharmony_ci SSS_CURRENTMODE(pos, md->status.currentmode); 5049141cc406Sopenharmony_ci SSS_BUTTONCOUNT(pos, md->status.buttoncount); 5050141cc406Sopenharmony_ci 5051141cc406Sopenharmony_ci if ( md_dump >= 2) 5052141cc406Sopenharmony_ci { 5053141cc406Sopenharmony_ci dump_area2(cmd, SSS_CMD_L, "sendsystemstatus"); 5054141cc406Sopenharmony_ci dump_area2(cmd + SSS_CMD_L, SSS_DATA_L, "sendsystemstatusdata"); 5055141cc406Sopenharmony_ci } 5056141cc406Sopenharmony_ci 5057141cc406Sopenharmony_ci status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), NULL, 0); 5058141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5059141cc406Sopenharmony_ci DBG(1, "scsi_send_system_status: '%s'\n", sane_strstatus(status)); 5060141cc406Sopenharmony_ci 5061141cc406Sopenharmony_ci if ( fd == -1 ) 5062141cc406Sopenharmony_ci sanei_scsi_close(sfd); 5063141cc406Sopenharmony_ci return status; 5064141cc406Sopenharmony_ci} 5065141cc406Sopenharmony_ci 5066141cc406Sopenharmony_ci 5067141cc406Sopenharmony_ci/*---------- scsi_sense_handler() --------------------------------------------*/ 5068141cc406Sopenharmony_ci/* rewritten 19.12.2001 for better SANE_STATUS return codes */ 5069141cc406Sopenharmony_ci 5070141cc406Sopenharmony_cistatic SANE_Status 5071141cc406Sopenharmony_ciscsi_sense_handler (int fd, u_char *sense, void *arg) 5072141cc406Sopenharmony_ci{ 5073141cc406Sopenharmony_ci int as_info_length; 5074141cc406Sopenharmony_ci uint8_t sense_key; 5075141cc406Sopenharmony_ci uint8_t asc; 5076141cc406Sopenharmony_ci uint8_t ascq; 5077141cc406Sopenharmony_ci 5078141cc406Sopenharmony_ci 5079141cc406Sopenharmony_ci DBG(30, "scsi_sense_handler: fd=%d, sense=%p arg=%p\n", 5080141cc406Sopenharmony_ci fd, (void *) sense, arg); 5081141cc406Sopenharmony_ci 5082141cc406Sopenharmony_ci dump_area(sense, RQS_LENGTH(sense), "SenseBuffer"); 5083141cc406Sopenharmony_ci 5084141cc406Sopenharmony_ci sense_key = RQS_SENSEKEY(sense); 5085141cc406Sopenharmony_ci asc = RQS_ASC(sense); 5086141cc406Sopenharmony_ci ascq = RQS_ASCQ(sense); 5087141cc406Sopenharmony_ci 5088141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: SENSE KEY (0x%02x), " 5089141cc406Sopenharmony_ci "ASC (0x%02x), ASCQ (0x%02x)\n", sense_key, asc, ascq); 5090141cc406Sopenharmony_ci 5091141cc406Sopenharmony_ci if ( (as_info_length = RQS_ASINFOLENGTH(sense)) > 0 ) 5092141cc406Sopenharmony_ci DBG(5,"scsi_sense_handler: info: '%*s'\n", 5093141cc406Sopenharmony_ci as_info_length, RQS_ASINFO(sense)); 5094141cc406Sopenharmony_ci 5095141cc406Sopenharmony_ci switch ( sense_key ) 5096141cc406Sopenharmony_ci { 5097141cc406Sopenharmony_ci case RQS_SENSEKEY_NOSENSE: 5098141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5099141cc406Sopenharmony_ci 5100141cc406Sopenharmony_ci case RQS_SENSEKEY_HWERR: 5101141cc406Sopenharmony_ci case RQS_SENSEKEY_ILLEGAL: 5102141cc406Sopenharmony_ci case RQS_SENSEKEY_VENDOR: 5103141cc406Sopenharmony_ci if ( asc == 0x4a && ascq == 0x00 ) 5104141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Command phase error\n"); 5105141cc406Sopenharmony_ci else if ( asc == 0x2c && ascq == 0x00 ) 5106141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Command sequence error\n"); 5107141cc406Sopenharmony_ci else if ( asc == 0x4b && ascq == 0x00 ) 5108141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Data phase error\n"); 5109141cc406Sopenharmony_ci else if ( asc == 0x40 ) 5110141cc406Sopenharmony_ci { 5111141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Hardware diagnostic failure:\n"); 5112141cc406Sopenharmony_ci switch ( ascq ) 5113141cc406Sopenharmony_ci { 5114141cc406Sopenharmony_ci case RQS_ASCQ_CPUERR: 5115141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: CPU error\n"); 5116141cc406Sopenharmony_ci break; 5117141cc406Sopenharmony_ci case RQS_ASCQ_SRAMERR: 5118141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: SRAM error\n"); 5119141cc406Sopenharmony_ci break; 5120141cc406Sopenharmony_ci case RQS_ASCQ_DRAMERR: 5121141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: DRAM error\n"); 5122141cc406Sopenharmony_ci break; 5123141cc406Sopenharmony_ci case RQS_ASCQ_DCOFF: 5124141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: DC Offset error\n"); 5125141cc406Sopenharmony_ci break; 5126141cc406Sopenharmony_ci case RQS_ASCQ_GAIN: 5127141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Gain error\n"); 5128141cc406Sopenharmony_ci break; 5129141cc406Sopenharmony_ci case RQS_ASCQ_POS: 5130141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Positioning error\n"); 5131141cc406Sopenharmony_ci break; 5132141cc406Sopenharmony_ci default: 5133141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Unknown combination of ASC" 5134141cc406Sopenharmony_ci " (0x%02x) and ASCQ (0x%02x)\n", asc, ascq); 5135141cc406Sopenharmony_ci break; 5136141cc406Sopenharmony_ci } 5137141cc406Sopenharmony_ci } 5138141cc406Sopenharmony_ci else if ( asc == 0x00 && ascq == 0x05) 5139141cc406Sopenharmony_ci { 5140141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: End of data detected\n"); 5141141cc406Sopenharmony_ci return SANE_STATUS_EOF; 5142141cc406Sopenharmony_ci } 5143141cc406Sopenharmony_ci else if ( asc == 0x3d && ascq == 0x00) 5144141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Invalid bit in IDENTIFY\n"); 5145141cc406Sopenharmony_ci else if ( asc == 0x2c && ascq == 0x02 ) 5146141cc406Sopenharmony_ci/* Ok */ DBG(5, "scsi_sense_handler: Invalid comb. of windows specified\n"); 5147141cc406Sopenharmony_ci else if ( asc == 0x20 && ascq == 0x00 ) 5148141cc406Sopenharmony_ci/* Ok */ DBG(5, "scsi_sense_handler: Invalid command opcode\n"); 5149141cc406Sopenharmony_ci else if ( asc == 0x24 && ascq == 0x00 ) 5150141cc406Sopenharmony_ci/* Ok */ DBG(5, "scsi_sense_handler: Invalid field in CDB\n"); 5151141cc406Sopenharmony_ci else if ( asc == 0x26 && ascq == 0x00 ) 5152141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Invalid field in the param list\n"); 5153141cc406Sopenharmony_ci else if ( asc == 0x49 && ascq == 0x00 ) 5154141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Invalid message error\n"); 5155141cc406Sopenharmony_ci else if ( asc == 0x60 && ascq == 0x00 ) 5156141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Lamp failure\n"); 5157141cc406Sopenharmony_ci else if ( asc == 0x25 && ascq == 0x00 ) 5158141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Unsupported logic. unit\n"); 5159141cc406Sopenharmony_ci else if ( asc == 0x53 && ascq == 0x00 ) 5160141cc406Sopenharmony_ci { 5161141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: ADF paper jam or no paper\n"); 5162141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 5163141cc406Sopenharmony_ci } 5164141cc406Sopenharmony_ci else if ( asc == 0x54 && ascq == 0x00 ) 5165141cc406Sopenharmony_ci { 5166141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Media bumping\n"); 5167141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; /* Don't know if this is right! */ 5168141cc406Sopenharmony_ci } 5169141cc406Sopenharmony_ci else if ( asc == 0x55 && ascq == 0x00 ) 5170141cc406Sopenharmony_ci { 5171141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Scan Job stopped or cancelled\n"); 5172141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 5173141cc406Sopenharmony_ci } 5174141cc406Sopenharmony_ci else if ( asc == 0x3a && ascq == 0x00 ) 5175141cc406Sopenharmony_ci { 5176141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Media (ADF or TMA) not available\n"); 5177141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 5178141cc406Sopenharmony_ci } 5179141cc406Sopenharmony_ci else if ( asc == 0x3a && ascq == 0x01 ) 5180141cc406Sopenharmony_ci { 5181141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Door is not closed\n"); 5182141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 5183141cc406Sopenharmony_ci } 5184141cc406Sopenharmony_ci else if ( asc == 0x3a && ascq == 0x02 ) 5185141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Door is not opened\n"); 5186141cc406Sopenharmony_ci else if ( asc == 0x00 && ascq == 0x00 ) 5187141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: No additional sense information\n"); 5188141cc406Sopenharmony_ci/* Ok */ else if ( asc == 0x1a && ascq == 0x00 ) 5189141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Parameter list length error\n"); 5190141cc406Sopenharmony_ci else if ( asc == 0x26 && ascq == 0x02 ) 5191141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Parameter value invalid\n"); 5192141cc406Sopenharmony_ci else if ( asc == 0x03 && ascq == 0x00 ) 5193141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Peripheral device write fault - " 5194141cc406Sopenharmony_ci "Firmware Download Error\n"); 5195141cc406Sopenharmony_ci else if ( asc == 0x2c && ascq == 0x01 ) 5196141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Too many windows specified\n"); 5197141cc406Sopenharmony_ci else if ( asc == 0x80 && ascq == 0x00 ) 5198141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Target abort scan\n"); 5199141cc406Sopenharmony_ci else if ( asc == 0x96 && ascq == 0x08 ) 5200141cc406Sopenharmony_ci { 5201141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Firewire Device busy\n"); 5202141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 5203141cc406Sopenharmony_ci } 5204141cc406Sopenharmony_ci else 5205141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Unknown combination of SENSE KEY " 5206141cc406Sopenharmony_ci "(0x%02x), ASC (0x%02x) and ASCQ (0x%02x)\n", 5207141cc406Sopenharmony_ci sense_key, asc, ascq); 5208141cc406Sopenharmony_ci 5209141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 5210141cc406Sopenharmony_ci 5211141cc406Sopenharmony_ci default: 5212141cc406Sopenharmony_ci DBG(5, "scsi_sense_handler: Unknown sense key (0x%02x)\n", 5213141cc406Sopenharmony_ci sense_key); 5214141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 5215141cc406Sopenharmony_ci } 5216141cc406Sopenharmony_ci} 5217141cc406Sopenharmony_ci 5218141cc406Sopenharmony_ci 5219141cc406Sopenharmony_ci/*---------- scsi_test_unit_ready() ------------------------------------------*/ 5220141cc406Sopenharmony_ci 5221141cc406Sopenharmony_cistatic SANE_Status 5222141cc406Sopenharmony_ciscsi_test_unit_ready(Microtek2_Device *md) 5223141cc406Sopenharmony_ci{ 5224141cc406Sopenharmony_ci SANE_Status status; 5225141cc406Sopenharmony_ci uint8_t tur[TUR_CMD_L]; 5226141cc406Sopenharmony_ci int sfd; 5227141cc406Sopenharmony_ci 5228141cc406Sopenharmony_ci 5229141cc406Sopenharmony_ci DBG(30, "scsi_test_unit_ready: md=%s\n", md->name); 5230141cc406Sopenharmony_ci 5231141cc406Sopenharmony_ci TUR_CMD(tur); 5232141cc406Sopenharmony_ci status = sanei_scsi_open(md->name, &sfd, scsi_sense_handler, 0); 5233141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5234141cc406Sopenharmony_ci { 5235141cc406Sopenharmony_ci DBG(1, "scsi_test_unit_ready: open '%s'\n", sane_strstatus(status)); 5236141cc406Sopenharmony_ci return status; 5237141cc406Sopenharmony_ci } 5238141cc406Sopenharmony_ci 5239141cc406Sopenharmony_ci if ( md_dump >= 2 ) 5240141cc406Sopenharmony_ci dump_area2(tur, sizeof(tur), "testunitready"); 5241141cc406Sopenharmony_ci 5242141cc406Sopenharmony_ci status = sanei_scsi_cmd(sfd, tur, sizeof(tur), NULL, 0); 5243141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5244141cc406Sopenharmony_ci DBG(1, "scsi_test_unit_ready: cmd '%s'\n", sane_strstatus(status)); 5245141cc406Sopenharmony_ci 5246141cc406Sopenharmony_ci sanei_scsi_close(sfd); 5247141cc406Sopenharmony_ci return status; 5248141cc406Sopenharmony_ci} 5249141cc406Sopenharmony_ci 5250141cc406Sopenharmony_ci 5251141cc406Sopenharmony_ci/*---------- sane_start() ----------------------------------------------------*/ 5252141cc406Sopenharmony_ci 5253141cc406Sopenharmony_ciSANE_Status 5254141cc406Sopenharmony_cisane_start(SANE_Handle handle) 5255141cc406Sopenharmony_ci{ 5256141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 5257141cc406Sopenharmony_ci Microtek2_Scanner *ms = handle; 5258141cc406Sopenharmony_ci Microtek2_Device *md; 5259141cc406Sopenharmony_ci Microtek2_Info *mi; 5260141cc406Sopenharmony_ci uint8_t *pos; 5261141cc406Sopenharmony_ci int color, rc, retry; 5262141cc406Sopenharmony_ci 5263141cc406Sopenharmony_ci DBG(30, "sane_start: handle=0x%p\n", handle); 5264141cc406Sopenharmony_ci 5265141cc406Sopenharmony_ci md = ms->dev; 5266141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 5267141cc406Sopenharmony_ci ms->n_control_bytes = md->n_control_bytes; 5268141cc406Sopenharmony_ci 5269141cc406Sopenharmony_ci if ( md->model_flags & MD_READ_CONTROL_BIT ) 5270141cc406Sopenharmony_ci { 5271141cc406Sopenharmony_ci if (ms->control_bytes) free((void *)ms->control_bytes); 5272141cc406Sopenharmony_ci ms->control_bytes = (uint8_t *) malloc(ms->n_control_bytes); 5273141cc406Sopenharmony_ci DBG(100, "sane_start: ms->control_bytes=%p, malloc'd %lu bytes\n", 5274141cc406Sopenharmony_ci (void *) ms->control_bytes, (u_long) ms->n_control_bytes); 5275141cc406Sopenharmony_ci if ( ms->control_bytes == NULL ) 5276141cc406Sopenharmony_ci { 5277141cc406Sopenharmony_ci DBG(1, "sane_start: malloc() for control bits failed\n"); 5278141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 5279141cc406Sopenharmony_ci goto cleanup; 5280141cc406Sopenharmony_ci } 5281141cc406Sopenharmony_ci } 5282141cc406Sopenharmony_ci 5283141cc406Sopenharmony_ci if (ms->sfd < 0) /* first or only pass of this scan */ 5284141cc406Sopenharmony_ci { 5285141cc406Sopenharmony_ci /* open device */ 5286141cc406Sopenharmony_ci for ( retry = 0; retry < 10; retry++ ) 5287141cc406Sopenharmony_ci { 5288141cc406Sopenharmony_ci status = sanei_scsi_open (md->sane.name, &ms->sfd, 5289141cc406Sopenharmony_ci scsi_sense_handler, 0); 5290141cc406Sopenharmony_ci if ( status != SANE_STATUS_DEVICE_BUSY ) 5291141cc406Sopenharmony_ci break; 5292141cc406Sopenharmony_ci DBG(30, "sane_start: Scanner busy, trying again\n"); 5293141cc406Sopenharmony_ci sleep(1); 5294141cc406Sopenharmony_ci } 5295141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5296141cc406Sopenharmony_ci { 5297141cc406Sopenharmony_ci DBG(1, "sane_start: scsi_open: '%s'\n", sane_strstatus(status)); 5298141cc406Sopenharmony_ci goto cleanup; 5299141cc406Sopenharmony_ci } 5300141cc406Sopenharmony_ci 5301141cc406Sopenharmony_ci status = scsi_read_system_status(md, ms->sfd); 5302141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5303141cc406Sopenharmony_ci goto cleanup; 5304141cc406Sopenharmony_ci 5305141cc406Sopenharmony_ci if ( ms->val[OPT_CALIB_BACKEND].w == SANE_TRUE ) 5306141cc406Sopenharmony_ci DBG(30, "sane_start: backend calibration on\n"); 5307141cc406Sopenharmony_ci else 5308141cc406Sopenharmony_ci DBG(30, "sane_start: backend calibration off\n"); 5309141cc406Sopenharmony_ci 5310141cc406Sopenharmony_ci if ( ( ms->val[OPT_CALIB_BACKEND].w == SANE_TRUE ) 5311141cc406Sopenharmony_ci && !( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) ) 5312141cc406Sopenharmony_ci { 5313141cc406Sopenharmony_ci /* Read shading only once - possible with CIS scanners */ 5314141cc406Sopenharmony_ci /* assuming only CIS scanners use Controlbits */ 5315141cc406Sopenharmony_ci if ( ( md->shading_table_w == NULL ) 5316141cc406Sopenharmony_ci || !( md->model_flags & MD_READ_CONTROL_BIT ) ) 5317141cc406Sopenharmony_ci { 5318141cc406Sopenharmony_ci status = get_scan_parameters(ms); 5319141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5320141cc406Sopenharmony_ci goto cleanup; 5321141cc406Sopenharmony_ci 5322141cc406Sopenharmony_ci status = read_shading_image(ms); 5323141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5324141cc406Sopenharmony_ci goto cleanup; 5325141cc406Sopenharmony_ci } 5326141cc406Sopenharmony_ci } 5327141cc406Sopenharmony_ci 5328141cc406Sopenharmony_ci status = get_scan_parameters(ms); 5329141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5330141cc406Sopenharmony_ci goto cleanup; 5331141cc406Sopenharmony_ci 5332141cc406Sopenharmony_ci status = scsi_read_system_status(md, ms->sfd); 5333141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5334141cc406Sopenharmony_ci goto cleanup; 5335141cc406Sopenharmony_ci 5336141cc406Sopenharmony_ci md->status.aloff |= 128; 5337141cc406Sopenharmony_ci md->status.timeremain = 10; 5338141cc406Sopenharmony_ci 5339141cc406Sopenharmony_ci if ( ms->scan_source == MS_SOURCE_FLATBED 5340141cc406Sopenharmony_ci || ms->scan_source == MS_SOURCE_ADF ) 5341141cc406Sopenharmony_ci { 5342141cc406Sopenharmony_ci md->status.flamp |= MD_FLAMP_ON; 5343141cc406Sopenharmony_ci md->status.tlamp &= ~MD_TLAMP_ON; 5344141cc406Sopenharmony_ci } 5345141cc406Sopenharmony_ci else 5346141cc406Sopenharmony_ci { 5347141cc406Sopenharmony_ci md->status.flamp &= ~MD_FLAMP_ON; 5348141cc406Sopenharmony_ci md->status.tlamp |= MD_TLAMP_ON; 5349141cc406Sopenharmony_ci } 5350141cc406Sopenharmony_ci 5351141cc406Sopenharmony_ci if ( ms->lightlid35 ) 5352141cc406Sopenharmony_ci { 5353141cc406Sopenharmony_ci md->status.flamp &= ~MD_FLAMP_ON; 5354141cc406Sopenharmony_ci/* md->status.tlamp |= MD_TLAMP_ON;*/ 5355141cc406Sopenharmony_ci/* with this line on some scanners (X6, 0x91) the Flamp goes on */ 5356141cc406Sopenharmony_ci } 5357141cc406Sopenharmony_ci 5358141cc406Sopenharmony_ci if ( ms->no_backtracking ) 5359141cc406Sopenharmony_ci md->status.ntrack |= MD_NTRACK_ON; 5360141cc406Sopenharmony_ci else 5361141cc406Sopenharmony_ci md->status.ntrack &= ~MD_NTRACK_ON; 5362141cc406Sopenharmony_ci 5363141cc406Sopenharmony_ci status = scsi_send_system_status(md, ms->sfd); 5364141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5365141cc406Sopenharmony_ci goto cleanup; 5366141cc406Sopenharmony_ci 5367141cc406Sopenharmony_ci /* calculate gamma: we assume, that the gamma values are transferred */ 5368141cc406Sopenharmony_ci /* with one send gamma command, even if it is a 3 pass scanner */ 5369141cc406Sopenharmony_ci if ( md->model_flags & MD_NO_GAMMA ) 5370141cc406Sopenharmony_ci { 5371141cc406Sopenharmony_ci ms->lut_size = (int) pow(2.0, (double) ms->depth); 5372141cc406Sopenharmony_ci ms->lut_entry_size = ms->depth > 8 ? 2 : 1; 5373141cc406Sopenharmony_ci } 5374141cc406Sopenharmony_ci else 5375141cc406Sopenharmony_ci { 5376141cc406Sopenharmony_ci get_lut_size(mi, &ms->lut_size, &ms->lut_entry_size); 5377141cc406Sopenharmony_ci } 5378141cc406Sopenharmony_ci ms->lut_size_bytes = ms->lut_size * ms->lut_entry_size; 5379141cc406Sopenharmony_ci ms->word = (ms->lut_entry_size == 2); 5380141cc406Sopenharmony_ci 5381141cc406Sopenharmony_ci ms->gamma_table = (uint8_t *) malloc(3 * ms->lut_size_bytes ); 5382141cc406Sopenharmony_ci DBG(100, "sane_start: ms->gamma_table=%p, malloc'd %d bytes\n", 5383141cc406Sopenharmony_ci (void *) ms->gamma_table, 3 * ms->lut_size_bytes); 5384141cc406Sopenharmony_ci if ( ms->gamma_table == NULL ) 5385141cc406Sopenharmony_ci { 5386141cc406Sopenharmony_ci DBG(1, "sane_start: malloc for gammatable failed\n"); 5387141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 5388141cc406Sopenharmony_ci goto cleanup; 5389141cc406Sopenharmony_ci } 5390141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 5391141cc406Sopenharmony_ci { 5392141cc406Sopenharmony_ci pos = ms->gamma_table + color * ms->lut_size_bytes; 5393141cc406Sopenharmony_ci calculate_gamma(ms, pos, color, ms->gamma_mode); 5394141cc406Sopenharmony_ci } 5395141cc406Sopenharmony_ci 5396141cc406Sopenharmony_ci /* Some models ignore the settings for the exposure time, */ 5397141cc406Sopenharmony_ci /* so we must do it ourselves. Apparently this seems to be */ 5398141cc406Sopenharmony_ci /* the case for all models that have the chunky data format */ 5399141cc406Sopenharmony_ci 5400141cc406Sopenharmony_ci if ( mi->data_format == MI_DATAFMT_CHUNKY ) 5401141cc406Sopenharmony_ci set_exposure(ms); 5402141cc406Sopenharmony_ci 5403141cc406Sopenharmony_ci if ( ! (md->model_flags & MD_NO_GAMMA) ) 5404141cc406Sopenharmony_ci { 5405141cc406Sopenharmony_ci status = scsi_send_gamma(ms); 5406141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5407141cc406Sopenharmony_ci goto cleanup; 5408141cc406Sopenharmony_ci } 5409141cc406Sopenharmony_ci 5410141cc406Sopenharmony_ci status = scsi_set_window(ms, 1); 5411141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5412141cc406Sopenharmony_ci goto cleanup; 5413141cc406Sopenharmony_ci 5414141cc406Sopenharmony_ci ms->scanning = SANE_TRUE; 5415141cc406Sopenharmony_ci ms->cancelled = SANE_FALSE; 5416141cc406Sopenharmony_ci } 5417141cc406Sopenharmony_ci 5418141cc406Sopenharmony_ci ++ms->current_pass; 5419141cc406Sopenharmony_ci 5420141cc406Sopenharmony_ci status = scsi_read_image_info(ms); 5421141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5422141cc406Sopenharmony_ci goto cleanup; 5423141cc406Sopenharmony_ci 5424141cc406Sopenharmony_ci status = prepare_buffers(ms); 5425141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5426141cc406Sopenharmony_ci goto cleanup; 5427141cc406Sopenharmony_ci 5428141cc406Sopenharmony_ci status = calculate_sane_params(ms); 5429141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5430141cc406Sopenharmony_ci goto cleanup; 5431141cc406Sopenharmony_ci 5432141cc406Sopenharmony_ci if ( !( md->model_flags & MD_NO_RIS_COMMAND ) ) 5433141cc406Sopenharmony_ci { 5434141cc406Sopenharmony_ci /* !!FIXME!! - hack for C6USB because RIS over USB doesn't wait until */ 5435141cc406Sopenharmony_ci /* scanner ready */ 5436141cc406Sopenharmony_ci if (mi->model_code == 0x9a) 5437141cc406Sopenharmony_ci sleep(2); 5438141cc406Sopenharmony_ci 5439141cc406Sopenharmony_ci status = scsi_wait_for_image(ms); 5440141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5441141cc406Sopenharmony_ci goto cleanup; 5442141cc406Sopenharmony_ci } 5443141cc406Sopenharmony_ci 5444141cc406Sopenharmony_ci if ( ms->calib_backend 5445141cc406Sopenharmony_ci && ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) 5446141cc406Sopenharmony_ci && ( ( md->shading_table_w == NULL ) 5447141cc406Sopenharmony_ci || ( ms->mode != md->shading_table_contents ) 5448141cc406Sopenharmony_ci ) 5449141cc406Sopenharmony_ci ) 5450141cc406Sopenharmony_ci { 5451141cc406Sopenharmony_ci status = read_cx_shading(ms); 5452141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5453141cc406Sopenharmony_ci goto cleanup; 5454141cc406Sopenharmony_ci } 5455141cc406Sopenharmony_ci 5456141cc406Sopenharmony_ci if ( ms->lightlid35 ) 5457141cc406Sopenharmony_ci /* hopefully this leads to a switched off flatbed lamp with lightlid */ 5458141cc406Sopenharmony_ci { 5459141cc406Sopenharmony_ci status = scsi_read_system_status(md, ms->sfd); 5460141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5461141cc406Sopenharmony_ci goto cleanup; 5462141cc406Sopenharmony_ci 5463141cc406Sopenharmony_ci md->status.flamp &= ~MD_FLAMP_ON; 5464141cc406Sopenharmony_ci md->status.tlamp &= ~MD_TLAMP_ON; 5465141cc406Sopenharmony_ci 5466141cc406Sopenharmony_ci status = scsi_send_system_status(md, ms->sfd); 5467141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5468141cc406Sopenharmony_ci goto cleanup; 5469141cc406Sopenharmony_ci } 5470141cc406Sopenharmony_ci 5471141cc406Sopenharmony_ci if ( md->model_flags & MD_READ_CONTROL_BIT ) 5472141cc406Sopenharmony_ci { 5473141cc406Sopenharmony_ci status = scsi_read_control_bits(ms); 5474141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5475141cc406Sopenharmony_ci goto cleanup; 5476141cc406Sopenharmony_ci 5477141cc406Sopenharmony_ci if ( ms->calib_backend ) 5478141cc406Sopenharmony_ci { 5479141cc406Sopenharmony_ci status = condense_shading(ms); 5480141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 5481141cc406Sopenharmony_ci goto cleanup; 5482141cc406Sopenharmony_ci } 5483141cc406Sopenharmony_ci } 5484141cc406Sopenharmony_ci 5485141cc406Sopenharmony_ci /* open a pipe and fork a child process, that actually reads the data */ 5486141cc406Sopenharmony_ci rc = pipe(ms->fd); 5487141cc406Sopenharmony_ci if ( rc == -1 ) 5488141cc406Sopenharmony_ci { 5489141cc406Sopenharmony_ci DBG(1, "sane_start: pipe failed\n"); 5490141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 5491141cc406Sopenharmony_ci goto cleanup; 5492141cc406Sopenharmony_ci } 5493141cc406Sopenharmony_ci 5494141cc406Sopenharmony_ci /* create reader routine as new thread or process */ 5495141cc406Sopenharmony_ci ms->pid = sanei_thread_begin( reader_process,(void*) ms); 5496141cc406Sopenharmony_ci 5497141cc406Sopenharmony_ci if ( !sanei_thread_is_valid (ms->pid) ) 5498141cc406Sopenharmony_ci { 5499141cc406Sopenharmony_ci DBG(1, "sane_start: fork failed\n"); 5500141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 5501141cc406Sopenharmony_ci goto cleanup; 5502141cc406Sopenharmony_ci } 5503141cc406Sopenharmony_ci 5504141cc406Sopenharmony_ci if (sanei_thread_is_forked()) close(ms->fd[1]); 5505141cc406Sopenharmony_ci 5506141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5507141cc406Sopenharmony_ci 5508141cc406Sopenharmony_cicleanup: 5509141cc406Sopenharmony_ci cleanup_scanner(ms); 5510141cc406Sopenharmony_ci return status; 5511141cc406Sopenharmony_ci} 5512141cc406Sopenharmony_ci 5513141cc406Sopenharmony_ci/*---------- prepare_buffers -------------------------------------------------*/ 5514141cc406Sopenharmony_ci 5515141cc406Sopenharmony_cistatic SANE_Status 5516141cc406Sopenharmony_ciprepare_buffers(Microtek2_Scanner *ms) 5517141cc406Sopenharmony_ci{ 5518141cc406Sopenharmony_ci SANE_Status status; 5519141cc406Sopenharmony_ci Microtek2_Device *md; 5520141cc406Sopenharmony_ci Microtek2_Info *mi; 5521141cc406Sopenharmony_ci uint32_t strip_lines; 5522141cc406Sopenharmony_ci int i; 5523141cc406Sopenharmony_ci 5524141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 5525141cc406Sopenharmony_ci DBG(30, "prepare_buffers: ms=0x%p\n", (void *) ms); 5526141cc406Sopenharmony_ci 5527141cc406Sopenharmony_ci md = ms->dev; 5528141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 5529141cc406Sopenharmony_ci 5530141cc406Sopenharmony_ci /* calculate maximum number of lines to read */ 5531141cc406Sopenharmony_ci strip_lines = (int) ((double) ms->y_resolution_dpi * md->opts.strip_height); 5532141cc406Sopenharmony_ci if ( strip_lines == 0 ) 5533141cc406Sopenharmony_ci strip_lines = 1; 5534141cc406Sopenharmony_ci 5535141cc406Sopenharmony_ci /* calculate number of lines that fit into the source buffer */ 5536141cc406Sopenharmony_ci#ifdef TESTBACKEND 5537141cc406Sopenharmony_ci ms->src_max_lines = MIN( 5000000 / ms->bpl, strip_lines); 5538141cc406Sopenharmony_ci#else 5539141cc406Sopenharmony_ci ms->src_max_lines = MIN( sanei_scsi_max_request_size / ms->bpl, strip_lines); 5540141cc406Sopenharmony_ci#endif 5541141cc406Sopenharmony_ci if ( ms->src_max_lines == 0 ) 5542141cc406Sopenharmony_ci { 5543141cc406Sopenharmony_ci DBG(1, "sane_start: Scan buffer too small\n"); 5544141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 5545141cc406Sopenharmony_ci goto cleanup; 5546141cc406Sopenharmony_ci } 5547141cc406Sopenharmony_ci 5548141cc406Sopenharmony_ci /* allocate buffers */ 5549141cc406Sopenharmony_ci ms->src_buffer_size = ms->src_max_lines * ms->bpl; 5550141cc406Sopenharmony_ci 5551141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_COLOR && mi->data_format == MI_DATAFMT_LPLSEGREG ) 5552141cc406Sopenharmony_ci { 5553141cc406Sopenharmony_ci /* In this case the data is not necessarily in the order RGB */ 5554141cc406Sopenharmony_ci /* and there may be different numbers of read red, green and blue */ 5555141cc406Sopenharmony_ci /* segments. We allocate a second buffer to read new lines in */ 5556141cc406Sopenharmony_ci /* and hold undelivered pixels in the other buffer */ 5557141cc406Sopenharmony_ci int extra_buf_size; 5558141cc406Sopenharmony_ci 5559141cc406Sopenharmony_ci extra_buf_size = 2 * ms->bpl * mi->ccd_gap 5560141cc406Sopenharmony_ci * (int) ceil( (double) mi->max_yresolution 5561141cc406Sopenharmony_ci / (double) mi->opt_resolution); 5562141cc406Sopenharmony_ci for ( i = 0; i < 2; i++ ) 5563141cc406Sopenharmony_ci { 5564141cc406Sopenharmony_ci if ( ms->buf.src_buffer[i] ) 5565141cc406Sopenharmony_ci free((void *) ms->buf.src_buffer[i]); 5566141cc406Sopenharmony_ci ms->buf.src_buffer[i] = (uint8_t *) malloc(ms->src_buffer_size 5567141cc406Sopenharmony_ci + extra_buf_size); 5568141cc406Sopenharmony_ci DBG(100, "prepare_buffers: ms->buf.src_buffer[%d]=%p," 5569141cc406Sopenharmony_ci "malloc'd %d bytes\n", i, (void *) ms->buf.src_buffer[i], 5570141cc406Sopenharmony_ci ms->src_buffer_size + extra_buf_size); 5571141cc406Sopenharmony_ci if ( ms->buf.src_buffer[i] == NULL ) 5572141cc406Sopenharmony_ci { 5573141cc406Sopenharmony_ci DBG(1, "sane_start: malloc for scan buffer failed\n"); 5574141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 5575141cc406Sopenharmony_ci goto cleanup; 5576141cc406Sopenharmony_ci } 5577141cc406Sopenharmony_ci } 5578141cc406Sopenharmony_ci ms->buf.free_lines = ms->src_max_lines + extra_buf_size / ms->bpl; 5579141cc406Sopenharmony_ci ms->buf.free_max_lines = ms->buf.free_lines; 5580141cc406Sopenharmony_ci ms->buf.src_buf = ms->buf.src_buffer[0]; 5581141cc406Sopenharmony_ci ms->buf.current_src = 0; /* index to current buffer */ 5582141cc406Sopenharmony_ci } 5583141cc406Sopenharmony_ci else 5584141cc406Sopenharmony_ci { 5585141cc406Sopenharmony_ci if ( ms->buf.src_buf ) 5586141cc406Sopenharmony_ci free((void *) ms->buf.src_buf); 5587141cc406Sopenharmony_ci ms->buf.src_buf = malloc(ms->src_buffer_size); 5588141cc406Sopenharmony_ci DBG(100, "sane_start: ms->buf.src_buf=%p, malloc'd %d bytes\n", 5589141cc406Sopenharmony_ci (void *) ms->buf.src_buf, ms->src_buffer_size); 5590141cc406Sopenharmony_ci if ( ms->buf.src_buf == NULL ) 5591141cc406Sopenharmony_ci { 5592141cc406Sopenharmony_ci DBG(1, "sane_start: malloc for scan buffer failed\n"); 5593141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 5594141cc406Sopenharmony_ci goto cleanup; 5595141cc406Sopenharmony_ci } 5596141cc406Sopenharmony_ci } 5597141cc406Sopenharmony_ci 5598141cc406Sopenharmony_ci for ( i = 0; i < 3; i++ ) 5599141cc406Sopenharmony_ci { 5600141cc406Sopenharmony_ci ms->buf.current_pos[i] = ms->buf.src_buffer[0]; 5601141cc406Sopenharmony_ci ms->buf.planes[0][i] = 0; 5602141cc406Sopenharmony_ci ms->buf.planes[1][i] = 0; 5603141cc406Sopenharmony_ci } 5604141cc406Sopenharmony_ci 5605141cc406Sopenharmony_ci /* allocate a temporary buffer for the data, if auto_adjust threshold */ 5606141cc406Sopenharmony_ci /* is selected. */ 5607141cc406Sopenharmony_ci 5608141cc406Sopenharmony_ci if ( ms->auto_adjust == 1 ) 5609141cc406Sopenharmony_ci { 5610141cc406Sopenharmony_ci ms->temporary_buffer = (uint8_t *) malloc(ms->remaining_bytes); 5611141cc406Sopenharmony_ci DBG(100, "sane_start: ms->temporary_buffer=%p, malloc'd %d bytes\n", 5612141cc406Sopenharmony_ci (void *) ms->temporary_buffer, ms->remaining_bytes); 5613141cc406Sopenharmony_ci if ( ms->temporary_buffer == NULL ) 5614141cc406Sopenharmony_ci { 5615141cc406Sopenharmony_ci DBG(1, "sane_start: malloc() for temporary buffer failed\n"); 5616141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 5617141cc406Sopenharmony_ci goto cleanup; 5618141cc406Sopenharmony_ci } 5619141cc406Sopenharmony_ci } 5620141cc406Sopenharmony_ci else 5621141cc406Sopenharmony_ci ms->temporary_buffer = NULL; 5622141cc406Sopenharmony_ci 5623141cc406Sopenharmony_ci /* some data formats have additional information in a scan line, which */ 5624141cc406Sopenharmony_ci /* is not transferred to the frontend; real_bpl is the number of bytes */ 5625141cc406Sopenharmony_ci /* per line, that is copied into the frontend's buffer */ 5626141cc406Sopenharmony_ci ms->real_bpl = (uint32_t) ceil( ((double) ms->ppl * 5627141cc406Sopenharmony_ci (double) ms->bits_per_pixel_out) / 8.0 ); 5628141cc406Sopenharmony_ci if ( mi->onepass && ms->mode == MS_MODE_COLOR ) 5629141cc406Sopenharmony_ci ms->real_bpl *= 3; 5630141cc406Sopenharmony_ci 5631141cc406Sopenharmony_ci ms->real_remaining_bytes = ms->real_bpl * ms->src_remaining_lines; 5632141cc406Sopenharmony_ci 5633141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5634141cc406Sopenharmony_ci 5635141cc406Sopenharmony_cicleanup: 5636141cc406Sopenharmony_ci cleanup_scanner(ms); 5637141cc406Sopenharmony_ci return status; 5638141cc406Sopenharmony_ci 5639141cc406Sopenharmony_ci} 5640141cc406Sopenharmony_cistatic void 5641141cc406Sopenharmony_ciwrite_shading_buf_pnm(Microtek2_Scanner *ms, uint32_t lines) 5642141cc406Sopenharmony_ci{ 5643141cc406Sopenharmony_ci FILE *outfile; 5644141cc406Sopenharmony_ci uint16_t pixel, color, linenr, factor; 5645141cc406Sopenharmony_ci unsigned char img_val_out; 5646141cc406Sopenharmony_ci float img_val = 0; 5647141cc406Sopenharmony_ci Microtek2_Device *md; 5648141cc406Sopenharmony_ci Microtek2_Info *mi; 5649141cc406Sopenharmony_ci 5650141cc406Sopenharmony_ci md = ms->dev; 5651141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 5652141cc406Sopenharmony_ci 5653141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 5654141cc406Sopenharmony_ci factor = 256; 5655141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_14 ) 5656141cc406Sopenharmony_ci factor = 64; 5657141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_12 ) 5658141cc406Sopenharmony_ci factor = 16; 5659141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_10 ) 5660141cc406Sopenharmony_ci factor = 4; 5661141cc406Sopenharmony_ci else 5662141cc406Sopenharmony_ci factor = 1; 5663141cc406Sopenharmony_ci if ( md->model_flags & MD_16BIT_TRANSFER ) 5664141cc406Sopenharmony_ci factor = 256; 5665141cc406Sopenharmony_ci 5666141cc406Sopenharmony_ci outfile = fopen("shading_buf_w.pnm", "w"); 5667141cc406Sopenharmony_ci fprintf(outfile, "P6\n#imagedata\n%d %d\n255\n", 5668141cc406Sopenharmony_ci mi->geo_width / mi->calib_divisor, lines); 5669141cc406Sopenharmony_ci for ( linenr=0; linenr < lines; linenr++ ) 5670141cc406Sopenharmony_ci { 5671141cc406Sopenharmony_ci if (mi->data_format == MI_DATAFMT_LPLSEGREG) 5672141cc406Sopenharmony_ci { 5673141cc406Sopenharmony_ci DBG(1, "Output of shading buffer unsupported for" 5674141cc406Sopenharmony_ci "Segreg Data format\n"); 5675141cc406Sopenharmony_ci break; 5676141cc406Sopenharmony_ci } 5677141cc406Sopenharmony_ci 5678141cc406Sopenharmony_ci for ( pixel=0; 5679141cc406Sopenharmony_ci pixel < (uint16_t) (mi->geo_width / mi->calib_divisor); 5680141cc406Sopenharmony_ci pixel++) 5681141cc406Sopenharmony_ci { 5682141cc406Sopenharmony_ci for ( color=0; color < 3; color++ ) 5683141cc406Sopenharmony_ci { 5684141cc406Sopenharmony_ci switch( mi->data_format ) 5685141cc406Sopenharmony_ci { 5686141cc406Sopenharmony_ci case MI_DATAFMT_LPLCONCAT: 5687141cc406Sopenharmony_ci if ( md->shading_depth > 8) 5688141cc406Sopenharmony_ci img_val = *((uint16_t *) ms->shading_image 5689141cc406Sopenharmony_ci + linenr * ( ms->bpl / ms->lut_entry_size ) 5690141cc406Sopenharmony_ci + mi->color_sequence[color] 5691141cc406Sopenharmony_ci * ( ms->bpl / ms->lut_entry_size / 3 ) 5692141cc406Sopenharmony_ci + pixel); 5693141cc406Sopenharmony_ci else 5694141cc406Sopenharmony_ci img_val = *((uint8_t *) ms->shading_image 5695141cc406Sopenharmony_ci + linenr * ( ms->bpl / ms->lut_entry_size ) 5696141cc406Sopenharmony_ci + mi->color_sequence[color] 5697141cc406Sopenharmony_ci * ( ms->bpl / ms->lut_entry_size / 3 ) 5698141cc406Sopenharmony_ci + pixel); 5699141cc406Sopenharmony_ci 5700141cc406Sopenharmony_ci break; 5701141cc406Sopenharmony_ci case MI_DATAFMT_CHUNKY: 5702141cc406Sopenharmony_ci case MI_DATAFMT_9800: 5703141cc406Sopenharmony_ci img_val = *((uint16_t *)ms->shading_image 5704141cc406Sopenharmony_ci + linenr * 3 * ( mi->geo_width 5705141cc406Sopenharmony_ci / mi->calib_divisor ) 5706141cc406Sopenharmony_ci + 3 * pixel 5707141cc406Sopenharmony_ci + mi->color_sequence[color]); 5708141cc406Sopenharmony_ci break; 5709141cc406Sopenharmony_ci } 5710141cc406Sopenharmony_ci img_val /= factor; 5711141cc406Sopenharmony_ci img_val_out = (unsigned char)img_val; 5712141cc406Sopenharmony_ci fputc(img_val_out, outfile); 5713141cc406Sopenharmony_ci } 5714141cc406Sopenharmony_ci } 5715141cc406Sopenharmony_ci } 5716141cc406Sopenharmony_ci fclose(outfile); 5717141cc406Sopenharmony_ci 5718141cc406Sopenharmony_ci return; 5719141cc406Sopenharmony_ci} 5720141cc406Sopenharmony_ci 5721141cc406Sopenharmony_cistatic void 5722141cc406Sopenharmony_ciwrite_shading_pnm(Microtek2_Scanner *ms) 5723141cc406Sopenharmony_ci{ 5724141cc406Sopenharmony_ci FILE *outfile_w = NULL, *outfile_d = NULL; 5725141cc406Sopenharmony_ci int pixel, color, line, offset, num_shading_pixels, output_height; 5726141cc406Sopenharmony_ci uint16_t img_val, factor; 5727141cc406Sopenharmony_ci 5728141cc406Sopenharmony_ci Microtek2_Device *md; 5729141cc406Sopenharmony_ci Microtek2_Info *mi; 5730141cc406Sopenharmony_ci 5731141cc406Sopenharmony_ci output_height = 180; 5732141cc406Sopenharmony_ci md = ms->dev; 5733141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 5734141cc406Sopenharmony_ci 5735141cc406Sopenharmony_ci DBG(30, "write_shading_pnm: ms=%p\n", (void *) ms); 5736141cc406Sopenharmony_ci 5737141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 5738141cc406Sopenharmony_ci factor = 256; 5739141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_14 ) 5740141cc406Sopenharmony_ci factor = 64; 5741141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_12 ) 5742141cc406Sopenharmony_ci factor = 16; 5743141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_10 ) 5744141cc406Sopenharmony_ci factor = 4; 5745141cc406Sopenharmony_ci else 5746141cc406Sopenharmony_ci factor = 1; 5747141cc406Sopenharmony_ci if ( md->model_flags & MD_16BIT_TRANSFER ) 5748141cc406Sopenharmony_ci factor = 256; 5749141cc406Sopenharmony_ci 5750141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) 5751141cc406Sopenharmony_ci num_shading_pixels = ms->n_control_bytes * 8; 5752141cc406Sopenharmony_ci else 5753141cc406Sopenharmony_ci num_shading_pixels = mi->geo_width / mi->calib_divisor; 5754141cc406Sopenharmony_ci if ( md->shading_table_w != NULL ) 5755141cc406Sopenharmony_ci { 5756141cc406Sopenharmony_ci outfile_w = fopen("microtek2_shading_w.pnm", "w"); 5757141cc406Sopenharmony_ci fprintf(outfile_w, "P6\n#imagedata\n%d %d\n255\n", 5758141cc406Sopenharmony_ci num_shading_pixels, output_height); 5759141cc406Sopenharmony_ci } 5760141cc406Sopenharmony_ci if ( md->shading_table_d != NULL ) 5761141cc406Sopenharmony_ci { 5762141cc406Sopenharmony_ci outfile_d = fopen("microtek2_shading_d.pnm", "w"); 5763141cc406Sopenharmony_ci fprintf(outfile_d, "P6\n#imagedata\n%d %d\n255\n", 5764141cc406Sopenharmony_ci num_shading_pixels, output_height); 5765141cc406Sopenharmony_ci } 5766141cc406Sopenharmony_ci for ( line=0; line < output_height; ++line ) 5767141cc406Sopenharmony_ci { 5768141cc406Sopenharmony_ci for ( pixel=0; pixel < num_shading_pixels ; ++pixel) 5769141cc406Sopenharmony_ci { 5770141cc406Sopenharmony_ci for ( color=0; color < 3; ++color ) 5771141cc406Sopenharmony_ci { 5772141cc406Sopenharmony_ci offset = mi->color_sequence[color] 5773141cc406Sopenharmony_ci * num_shading_pixels 5774141cc406Sopenharmony_ci + pixel; 5775141cc406Sopenharmony_ci if ( md->shading_table_w != NULL ) 5776141cc406Sopenharmony_ci { 5777141cc406Sopenharmony_ci if ( ms->lut_entry_size == 2 ) 5778141cc406Sopenharmony_ci { 5779141cc406Sopenharmony_ci img_val = *((uint16_t *) md->shading_table_w + offset ); 5780141cc406Sopenharmony_ci img_val /= factor; 5781141cc406Sopenharmony_ci } 5782141cc406Sopenharmony_ci else 5783141cc406Sopenharmony_ci img_val = *((uint8_t *) md->shading_table_w + offset ); 5784141cc406Sopenharmony_ci fputc((unsigned char)img_val, outfile_w); 5785141cc406Sopenharmony_ci } 5786141cc406Sopenharmony_ci 5787141cc406Sopenharmony_ci if ( md->shading_table_d != NULL ) 5788141cc406Sopenharmony_ci { 5789141cc406Sopenharmony_ci if ( ms->lut_entry_size == 2 ) 5790141cc406Sopenharmony_ci { 5791141cc406Sopenharmony_ci img_val = *((uint16_t *) md->shading_table_d + offset ); 5792141cc406Sopenharmony_ci img_val /= factor; 5793141cc406Sopenharmony_ci } 5794141cc406Sopenharmony_ci else 5795141cc406Sopenharmony_ci img_val = *((uint8_t *) md->shading_table_d + offset ); 5796141cc406Sopenharmony_ci fputc((unsigned char)img_val, outfile_d); 5797141cc406Sopenharmony_ci } 5798141cc406Sopenharmony_ci } 5799141cc406Sopenharmony_ci } 5800141cc406Sopenharmony_ci } 5801141cc406Sopenharmony_ci if ( md->shading_table_w != NULL ) 5802141cc406Sopenharmony_ci fclose(outfile_w); 5803141cc406Sopenharmony_ci if ( md->shading_table_d != NULL ) 5804141cc406Sopenharmony_ci fclose(outfile_d); 5805141cc406Sopenharmony_ci 5806141cc406Sopenharmony_ci return; 5807141cc406Sopenharmony_ci} 5808141cc406Sopenharmony_ci 5809141cc406Sopenharmony_cistatic void 5810141cc406Sopenharmony_ciwrite_cshading_pnm(Microtek2_Scanner *ms) 5811141cc406Sopenharmony_ci{ 5812141cc406Sopenharmony_ci FILE *outfile; 5813141cc406Sopenharmony_ci Microtek2_Device *md; 5814141cc406Sopenharmony_ci Microtek2_Info *mi; 5815141cc406Sopenharmony_ci int pixel, color, line, offset, img_val, img_height=30, factor; 5816141cc406Sopenharmony_ci 5817141cc406Sopenharmony_ci md = ms->dev; 5818141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 5819141cc406Sopenharmony_ci 5820141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 5821141cc406Sopenharmony_ci factor = 256; 5822141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_14 ) 5823141cc406Sopenharmony_ci factor = 64; 5824141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_12 ) 5825141cc406Sopenharmony_ci factor = 16; 5826141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_10 ) 5827141cc406Sopenharmony_ci factor = 4; 5828141cc406Sopenharmony_ci else 5829141cc406Sopenharmony_ci factor = 1; 5830141cc406Sopenharmony_ci if ( md->model_flags & MD_16BIT_TRANSFER ) 5831141cc406Sopenharmony_ci factor = 256; 5832141cc406Sopenharmony_ci 5833141cc406Sopenharmony_ci outfile = fopen("microtek2_cshading_w.pnm", "w"); 5834141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_COLOR ) 5835141cc406Sopenharmony_ci fprintf(outfile, "P6\n#imagedata\n%d %d\n255\n", ms->ppl, img_height); 5836141cc406Sopenharmony_ci else 5837141cc406Sopenharmony_ci fprintf(outfile, "P5\n#imagedata\n%d %d\n255\n", ms->ppl, img_height); 5838141cc406Sopenharmony_ci 5839141cc406Sopenharmony_ci for ( line=0; line < img_height; ++line ) 5840141cc406Sopenharmony_ci { 5841141cc406Sopenharmony_ci for ( pixel=0; pixel < (int)ms->ppl; ++pixel) 5842141cc406Sopenharmony_ci { 5843141cc406Sopenharmony_ci for ( color=0; color < 3; ++color ) 5844141cc406Sopenharmony_ci { 5845141cc406Sopenharmony_ci offset = color * (int)ms->ppl + pixel; 5846141cc406Sopenharmony_ci if ( ms->lut_entry_size == 1 ) 5847141cc406Sopenharmony_ci img_val = (int) *((uint8_t *)ms->condensed_shading_w + offset); 5848141cc406Sopenharmony_ci else 5849141cc406Sopenharmony_ci { 5850141cc406Sopenharmony_ci img_val = (int) *((uint16_t *)ms->condensed_shading_w 5851141cc406Sopenharmony_ci + offset); 5852141cc406Sopenharmony_ci img_val /= factor; 5853141cc406Sopenharmony_ci } 5854141cc406Sopenharmony_ci fputc((unsigned char)img_val, outfile); 5855141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_GRAY ) 5856141cc406Sopenharmony_ci break; 5857141cc406Sopenharmony_ci } 5858141cc406Sopenharmony_ci } 5859141cc406Sopenharmony_ci } 5860141cc406Sopenharmony_ci fclose(outfile); 5861141cc406Sopenharmony_ci 5862141cc406Sopenharmony_ci return; 5863141cc406Sopenharmony_ci} 5864141cc406Sopenharmony_ci 5865141cc406Sopenharmony_ci 5866141cc406Sopenharmony_ci 5867141cc406Sopenharmony_ci/*---------- condense_shading() ----------------------------------------------*/ 5868141cc406Sopenharmony_ci 5869141cc406Sopenharmony_cistatic SANE_Status 5870141cc406Sopenharmony_cicondense_shading(Microtek2_Scanner *ms) 5871141cc406Sopenharmony_ci{ 5872141cc406Sopenharmony_ci /* This function extracts the relevant shading pixels from */ 5873141cc406Sopenharmony_ci /* the shading image according to the 1's in the result of */ 5874141cc406Sopenharmony_ci /* 'read control bits', and stores them in a memory block. */ 5875141cc406Sopenharmony_ci /* We will then have as many shading pixels as there are */ 5876141cc406Sopenharmony_ci /* pixels per line. The order of the pixels in the condensed */ 5877141cc406Sopenharmony_ci /* shading data block will always be left to right. The color */ 5878141cc406Sopenharmony_ci /* sequence remains unchanged. */ 5879141cc406Sopenharmony_ci 5880141cc406Sopenharmony_ci Microtek2_Device *md; 5881141cc406Sopenharmony_ci Microtek2_Info *mi; 5882141cc406Sopenharmony_ci uint32_t byte; 5883141cc406Sopenharmony_ci uint32_t cond_length; /* bytes per condensed shading line */ 5884141cc406Sopenharmony_ci int color, count, lfd_bit; 5885141cc406Sopenharmony_ci int shad_bplc, shad_pixels; /* bytes per line & color in shading image */ 5886141cc406Sopenharmony_ci int bit, flag; 5887141cc406Sopenharmony_ci uint32_t sh_offset, csh_offset; 5888141cc406Sopenharmony_ci int gray_filter_color = 1; /* which color of the shading is taken for gray*/ 5889141cc406Sopenharmony_ci 5890141cc406Sopenharmony_ci md = ms->dev; 5891141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 5892141cc406Sopenharmony_ci 5893141cc406Sopenharmony_ci DBG(30, "condense_shading: ms=%p, ppl=%d\n", (void *) ms, ms->ppl); 5894141cc406Sopenharmony_ci if ( md->shading_table_w == NULL ) 5895141cc406Sopenharmony_ci { 5896141cc406Sopenharmony_ci DBG(1, "condense shading: no shading table found, skip shading\n"); 5897141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 5898141cc406Sopenharmony_ci } 5899141cc406Sopenharmony_ci 5900141cc406Sopenharmony_ci get_lut_size( mi, &ms->lut_size, &ms->lut_entry_size ); 5901141cc406Sopenharmony_ci 5902141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) 5903141cc406Sopenharmony_ci { 5904141cc406Sopenharmony_ci shad_pixels = ms->n_control_bytes * 8; 5905141cc406Sopenharmony_ci gray_filter_color = 0; /* 336CX reads only one shading in gray mode*/ 5906141cc406Sopenharmony_ci } 5907141cc406Sopenharmony_ci else 5908141cc406Sopenharmony_ci shad_pixels = mi->geo_width; 5909141cc406Sopenharmony_ci 5910141cc406Sopenharmony_ci shad_bplc = shad_pixels * ms->lut_entry_size; 5911141cc406Sopenharmony_ci 5912141cc406Sopenharmony_ci if ( md_dump >= 3 ) 5913141cc406Sopenharmony_ci { 5914141cc406Sopenharmony_ci dump_area2(md->shading_table_w, shad_bplc * 3, "shading_table_w"); 5915141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) 5916141cc406Sopenharmony_ci write_shading_pnm(ms); 5917141cc406Sopenharmony_ci } 5918141cc406Sopenharmony_ci 5919141cc406Sopenharmony_ci cond_length = ms->bpl * ms->lut_entry_size; 5920141cc406Sopenharmony_ci 5921141cc406Sopenharmony_ci if ( ms->condensed_shading_w ) 5922141cc406Sopenharmony_ci { 5923141cc406Sopenharmony_ci free((void*) ms->condensed_shading_w ); 5924141cc406Sopenharmony_ci ms->condensed_shading_w = NULL; 5925141cc406Sopenharmony_ci } 5926141cc406Sopenharmony_ci ms->condensed_shading_w = (uint8_t *)malloc(cond_length); 5927141cc406Sopenharmony_ci DBG(100, "condense_shading: ms->condensed_shading_w=%p," 5928141cc406Sopenharmony_ci "malloc'd %d bytes\n", 5929141cc406Sopenharmony_ci (void *) ms->condensed_shading_w, cond_length); 5930141cc406Sopenharmony_ci if ( ms->condensed_shading_w == NULL ) 5931141cc406Sopenharmony_ci { 5932141cc406Sopenharmony_ci DBG(1, "condense_shading: malloc for white table failed\n"); 5933141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 5934141cc406Sopenharmony_ci } 5935141cc406Sopenharmony_ci 5936141cc406Sopenharmony_ci if ( md->shading_table_d != NULL ) 5937141cc406Sopenharmony_ci { 5938141cc406Sopenharmony_ci if ( md_dump >= 3 ) 5939141cc406Sopenharmony_ci dump_area2(md->shading_table_d, shad_bplc * 3, 5940141cc406Sopenharmony_ci "shading_table_d"); 5941141cc406Sopenharmony_ci 5942141cc406Sopenharmony_ci if ( ms->condensed_shading_d ) 5943141cc406Sopenharmony_ci { 5944141cc406Sopenharmony_ci free((void*) ms->condensed_shading_d ); 5945141cc406Sopenharmony_ci ms->condensed_shading_d = NULL; 5946141cc406Sopenharmony_ci } 5947141cc406Sopenharmony_ci ms->condensed_shading_d = (uint8_t *)malloc(cond_length); 5948141cc406Sopenharmony_ci DBG(100, "condense_shading: ms->condensed_shading_d=%p," 5949141cc406Sopenharmony_ci " malloc'd %d bytes\n", 5950141cc406Sopenharmony_ci (void *) ms->condensed_shading_d, cond_length); 5951141cc406Sopenharmony_ci if ( ms->condensed_shading_d == NULL ) 5952141cc406Sopenharmony_ci { 5953141cc406Sopenharmony_ci DBG(1, "condense_shading: malloc for dark table failed\n"); 5954141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 5955141cc406Sopenharmony_ci } 5956141cc406Sopenharmony_ci } 5957141cc406Sopenharmony_ci 5958141cc406Sopenharmony_ci DBG(128, "controlbit offset=%d\n", md->controlbit_offset); 5959141cc406Sopenharmony_ci 5960141cc406Sopenharmony_ci count = 0; 5961141cc406Sopenharmony_ci 5962141cc406Sopenharmony_ci for (lfd_bit = 0; ( lfd_bit < mi->geo_width ) && ( count < (int)ms->ppl ); 5963141cc406Sopenharmony_ci ++lfd_bit) 5964141cc406Sopenharmony_ci { 5965141cc406Sopenharmony_ci byte = ( lfd_bit + md->controlbit_offset ) / 8; 5966141cc406Sopenharmony_ci bit = ( lfd_bit + md->controlbit_offset ) % 8; 5967141cc406Sopenharmony_ci 5968141cc406Sopenharmony_ci if ( mi->direction & MI_DATSEQ_RTOL ) 5969141cc406Sopenharmony_ci flag = ((ms->control_bytes[byte] >> bit) & 0x01); 5970141cc406Sopenharmony_ci else 5971141cc406Sopenharmony_ci flag = ((ms->control_bytes[byte] >> (7 - bit)) & 0x01); 5972141cc406Sopenharmony_ci 5973141cc406Sopenharmony_ci if ( flag == 1 ) /* flag==1 if byte's bit is set */ 5974141cc406Sopenharmony_ci { 5975141cc406Sopenharmony_ci for ( color = 0; color < 3; ++color ) 5976141cc406Sopenharmony_ci { 5977141cc406Sopenharmony_ci if ( ( ms->mode == MS_MODE_COLOR ) 5978141cc406Sopenharmony_ci || ( ( ms->mode == MS_MODE_GRAY ) 5979141cc406Sopenharmony_ci && ( color == gray_filter_color ) ) 5980141cc406Sopenharmony_ci || ( ( ms->mode == MS_MODE_LINEARTFAKE ) 5981141cc406Sopenharmony_ci && ( color == gray_filter_color ) ) 5982141cc406Sopenharmony_ci ) 5983141cc406Sopenharmony_ci { 5984141cc406Sopenharmony_ci sh_offset = color * shad_pixels + lfd_bit; 5985141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) 5986141cc406Sopenharmony_ci sh_offset += md->controlbit_offset; 5987141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_COLOR ) 5988141cc406Sopenharmony_ci csh_offset = color * ms->ppl + count; 5989141cc406Sopenharmony_ci else 5990141cc406Sopenharmony_ci csh_offset = count; 5991141cc406Sopenharmony_ci 5992141cc406Sopenharmony_ci if ( csh_offset > cond_length ) 5993141cc406Sopenharmony_ci { 5994141cc406Sopenharmony_ci DBG(1, "condense_shading: wrong control bits data, " ); 5995141cc406Sopenharmony_ci DBG(1, "csh_offset (%d) > cond_length(%d)\n", 5996141cc406Sopenharmony_ci csh_offset, cond_length ); 5997141cc406Sopenharmony_ci csh_offset = cond_length; 5998141cc406Sopenharmony_ci } 5999141cc406Sopenharmony_ci 6000141cc406Sopenharmony_ci if ( ms->lut_entry_size == 2 ) 6001141cc406Sopenharmony_ci { 6002141cc406Sopenharmony_ci *((uint16_t *)ms->condensed_shading_w + csh_offset) = 6003141cc406Sopenharmony_ci *((uint16_t *)md->shading_table_w 6004141cc406Sopenharmony_ci + sh_offset); 6005141cc406Sopenharmony_ci if ( ms->condensed_shading_d != NULL ) 6006141cc406Sopenharmony_ci *((uint16_t *)ms->condensed_shading_d + csh_offset) = 6007141cc406Sopenharmony_ci *((uint16_t *)md->shading_table_d 6008141cc406Sopenharmony_ci + sh_offset); 6009141cc406Sopenharmony_ci } 6010141cc406Sopenharmony_ci else 6011141cc406Sopenharmony_ci { 6012141cc406Sopenharmony_ci *((uint8_t *)ms->condensed_shading_w + csh_offset) = 6013141cc406Sopenharmony_ci *((uint8_t *)md->shading_table_w 6014141cc406Sopenharmony_ci + sh_offset); 6015141cc406Sopenharmony_ci if ( ms->condensed_shading_d != NULL ) 6016141cc406Sopenharmony_ci *((uint8_t *)ms->condensed_shading_d + csh_offset) = 6017141cc406Sopenharmony_ci *((uint8_t *)md->shading_table_d 6018141cc406Sopenharmony_ci + sh_offset); 6019141cc406Sopenharmony_ci } 6020141cc406Sopenharmony_ci } 6021141cc406Sopenharmony_ci } 6022141cc406Sopenharmony_ci ++count; 6023141cc406Sopenharmony_ci } 6024141cc406Sopenharmony_ci } 6025141cc406Sopenharmony_ci 6026141cc406Sopenharmony_ci if ( md_dump >= 3 ) 6027141cc406Sopenharmony_ci { 6028141cc406Sopenharmony_ci dump_area2(ms->condensed_shading_w, cond_length, "condensed_shading_w"); 6029141cc406Sopenharmony_ci if ( ms->condensed_shading_d != NULL ) 6030141cc406Sopenharmony_ci dump_area2(ms->condensed_shading_d, cond_length, 6031141cc406Sopenharmony_ci "condensed_shading_d"); 6032141cc406Sopenharmony_ci 6033141cc406Sopenharmony_ci write_cshading_pnm(ms); 6034141cc406Sopenharmony_ci } 6035141cc406Sopenharmony_ci 6036141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6037141cc406Sopenharmony_ci} 6038141cc406Sopenharmony_ci 6039141cc406Sopenharmony_ci 6040141cc406Sopenharmony_ci/*---------- read_shading_image() --------------------------------------------*/ 6041141cc406Sopenharmony_ci 6042141cc406Sopenharmony_cistatic SANE_Status 6043141cc406Sopenharmony_ciread_shading_image(Microtek2_Scanner *ms) 6044141cc406Sopenharmony_ci{ 6045141cc406Sopenharmony_ci SANE_Status status; 6046141cc406Sopenharmony_ci Microtek2_Device *md; 6047141cc406Sopenharmony_ci Microtek2_Info *mi; 6048141cc406Sopenharmony_ci uint32_t lines; 6049141cc406Sopenharmony_ci uint8_t *buf; 6050141cc406Sopenharmony_ci int max_lines; 6051141cc406Sopenharmony_ci int lines_to_read; 6052141cc406Sopenharmony_ci 6053141cc406Sopenharmony_ci DBG(30, "read_shading_image: ms=%p\n", (void *) ms); 6054141cc406Sopenharmony_ci 6055141cc406Sopenharmony_ci md = ms->dev; 6056141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 6057141cc406Sopenharmony_ci 6058141cc406Sopenharmony_ci 6059141cc406Sopenharmony_ci if ( ! MI_WHITE_SHADING_ONLY(mi->shtrnsferequ) 6060141cc406Sopenharmony_ci || ( md->model_flags & MD_PHANTOM_C6 ) ) 6061141cc406Sopenharmony_ci 6062141cc406Sopenharmony_ci /* Dark shading correction */ 6063141cc406Sopenharmony_ci /* ~~~~~~~~~~~~~~~~~~~~~~~ */ 6064141cc406Sopenharmony_ci { 6065141cc406Sopenharmony_ci DBG(30, "read_shading_image: reading black data\n"); 6066141cc406Sopenharmony_ci md->status.ntrack |= MD_NTRACK_ON; 6067141cc406Sopenharmony_ci md->status.ncalib &= ~MD_NCALIB_ON; 6068141cc406Sopenharmony_ci md->status.flamp |= MD_FLAMP_ON; 6069141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM_C6 ) 6070141cc406Sopenharmony_ci { 6071141cc406Sopenharmony_ci md->status.stick |= MD_STICK_ON; 6072141cc406Sopenharmony_ci md->status.reserved17 |= MD_RESERVED17_ON; 6073141cc406Sopenharmony_ci } 6074141cc406Sopenharmony_ci 6075141cc406Sopenharmony_ci get_calib_params(ms); 6076141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM_C6 ) 6077141cc406Sopenharmony_ci ms->stay = 1; 6078141cc406Sopenharmony_ci 6079141cc406Sopenharmony_ci status = scsi_send_system_status(md, ms->sfd); 6080141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6081141cc406Sopenharmony_ci return status; 6082141cc406Sopenharmony_ci 6083141cc406Sopenharmony_ci status = scsi_set_window(ms, 1); 6084141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6085141cc406Sopenharmony_ci return status; 6086141cc406Sopenharmony_ci 6087141cc406Sopenharmony_ci#ifdef TESTBACKEND 6088141cc406Sopenharmony_ci status = scsi_read_sh_image_info(ms); 6089141cc406Sopenharmony_ci#else 6090141cc406Sopenharmony_ci status = scsi_read_image_info(ms); 6091141cc406Sopenharmony_ci#endif 6092141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6093141cc406Sopenharmony_ci return status; 6094141cc406Sopenharmony_ci 6095141cc406Sopenharmony_ci status = scsi_wait_for_image(ms); 6096141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6097141cc406Sopenharmony_ci return status; 6098141cc406Sopenharmony_ci 6099141cc406Sopenharmony_ci status = scsi_read_system_status(md, ms->sfd); 6100141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6101141cc406Sopenharmony_ci return status; 6102141cc406Sopenharmony_ci 6103141cc406Sopenharmony_ci md->status.flamp &= ~MD_FLAMP_ON; 6104141cc406Sopenharmony_ci 6105141cc406Sopenharmony_ci status = scsi_send_system_status(md, ms->sfd); 6106141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6107141cc406Sopenharmony_ci return status; 6108141cc406Sopenharmony_ci 6109141cc406Sopenharmony_ci ms->shading_image = malloc(ms->bpl * ms->src_remaining_lines); 6110141cc406Sopenharmony_ci DBG(100, "read shading image: ms->shading_image=%p," 6111141cc406Sopenharmony_ci " malloc'd %d bytes\n", 6112141cc406Sopenharmony_ci (void *) ms->shading_image, 6113141cc406Sopenharmony_ci ms->bpl * ms->src_remaining_lines); 6114141cc406Sopenharmony_ci if ( ms->shading_image == NULL ) 6115141cc406Sopenharmony_ci { 6116141cc406Sopenharmony_ci DBG(1, "read_shading_image: malloc for buffer failed\n"); 6117141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6118141cc406Sopenharmony_ci } 6119141cc406Sopenharmony_ci 6120141cc406Sopenharmony_ci buf = ms->shading_image; 6121141cc406Sopenharmony_ci 6122141cc406Sopenharmony_ci#ifdef TESTBACKEND 6123141cc406Sopenharmony_ci max_lines = 5000000 / ms->bpl; 6124141cc406Sopenharmony_ci#else 6125141cc406Sopenharmony_ci max_lines = sanei_scsi_max_request_size / ms->bpl; 6126141cc406Sopenharmony_ci#endif 6127141cc406Sopenharmony_ci if ( max_lines == 0 ) 6128141cc406Sopenharmony_ci { 6129141cc406Sopenharmony_ci DBG(1, "read_shading_image: buffer too small\n"); 6130141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 6131141cc406Sopenharmony_ci } 6132141cc406Sopenharmony_ci lines = ms->src_remaining_lines; 6133141cc406Sopenharmony_ci while ( ms->src_remaining_lines > 0 ) 6134141cc406Sopenharmony_ci { 6135141cc406Sopenharmony_ci lines_to_read = MIN(max_lines, ms->src_remaining_lines); 6136141cc406Sopenharmony_ci ms->src_buffer_size = lines_to_read * ms->bpl; 6137141cc406Sopenharmony_ci ms->transfer_length = ms->src_buffer_size; 6138141cc406Sopenharmony_ci#ifdef TESTBACKEND 6139141cc406Sopenharmony_ci status = scsi_read_sh_d_image(ms, buf); 6140141cc406Sopenharmony_ci#else 6141141cc406Sopenharmony_ci status = scsi_read_image(ms, buf, md->shading_depth>8 ? 2 : 1); 6142141cc406Sopenharmony_ci#endif 6143141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6144141cc406Sopenharmony_ci { 6145141cc406Sopenharmony_ci DBG(1, "read_shading_image: read image failed: '%s'\n", 6146141cc406Sopenharmony_ci sane_strstatus(status)); 6147141cc406Sopenharmony_ci return status; 6148141cc406Sopenharmony_ci } 6149141cc406Sopenharmony_ci 6150141cc406Sopenharmony_ci ms->src_remaining_lines -= lines_to_read; 6151141cc406Sopenharmony_ci buf += ms->src_buffer_size; 6152141cc406Sopenharmony_ci } 6153141cc406Sopenharmony_ci 6154141cc406Sopenharmony_ci status = prepare_shading_data(ms, lines, &md->shading_table_d); 6155141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6156141cc406Sopenharmony_ci return status; 6157141cc406Sopenharmony_ci 6158141cc406Sopenharmony_ci /* send shading data to the device */ 6159141cc406Sopenharmony_ci /* Some models use "read_control bit", and the shading must be */ 6160141cc406Sopenharmony_ci /* applied by the backend later */ 6161141cc406Sopenharmony_ci if ( ! (md->model_flags & MD_READ_CONTROL_BIT) ) 6162141cc406Sopenharmony_ci { 6163141cc406Sopenharmony_ci status = shading_function(ms, md->shading_table_d); 6164141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6165141cc406Sopenharmony_ci return status; 6166141cc406Sopenharmony_ci 6167141cc406Sopenharmony_ci ms->word = ms->lut_entry_size == 2 ? 1 : 0; 6168141cc406Sopenharmony_ci ms->current_color = MS_COLOR_ALL; 6169141cc406Sopenharmony_ci status = scsi_send_shading(ms, 6170141cc406Sopenharmony_ci md->shading_table_d, 6171141cc406Sopenharmony_ci 3 * ms->lut_entry_size 6172141cc406Sopenharmony_ci * mi->geo_width / mi->calib_divisor, 6173141cc406Sopenharmony_ci 1); 6174141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6175141cc406Sopenharmony_ci return status; 6176141cc406Sopenharmony_ci } 6177141cc406Sopenharmony_ci 6178141cc406Sopenharmony_ci DBG(100, "free memory for ms->shading_image at %p\n", 6179141cc406Sopenharmony_ci (void *) ms->shading_image); 6180141cc406Sopenharmony_ci free((void *) ms->shading_image); 6181141cc406Sopenharmony_ci ms->shading_image = NULL; 6182141cc406Sopenharmony_ci } 6183141cc406Sopenharmony_ci 6184141cc406Sopenharmony_ci /* white shading correction */ 6185141cc406Sopenharmony_ci /* ~~~~~~~~~~~~~~~~~~~~~~~~ */ 6186141cc406Sopenharmony_ci DBG(30, "read_shading_image: reading white data\n"); 6187141cc406Sopenharmony_ci 6188141cc406Sopenharmony_ci /* According to the doc NCalib must be set for white shading data */ 6189141cc406Sopenharmony_ci /* if we have a black and a white shading correction and must be */ 6190141cc406Sopenharmony_ci /* cleared if we have only a white shading collection */ 6191141cc406Sopenharmony_ci if ( ! MI_WHITE_SHADING_ONLY(mi->shtrnsferequ) 6192141cc406Sopenharmony_ci || ( md->model_flags & MD_PHANTOM_C6 ) ) 6193141cc406Sopenharmony_ci md->status.ncalib |= MD_NCALIB_ON; 6194141cc406Sopenharmony_ci else 6195141cc406Sopenharmony_ci md->status.ncalib &= ~MD_NCALIB_ON; 6196141cc406Sopenharmony_ci 6197141cc406Sopenharmony_ci md->status.flamp |= MD_FLAMP_ON; 6198141cc406Sopenharmony_ci/* md->status.tlamp &= ~MD_TLAMP_ON; */ 6199141cc406Sopenharmony_ci md->status.ntrack |= MD_NTRACK_ON; 6200141cc406Sopenharmony_ci 6201141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM_C6 ) 6202141cc406Sopenharmony_ci { 6203141cc406Sopenharmony_ci md->status.stick &= ~MD_STICK_ON; 6204141cc406Sopenharmony_ci md->status.reserved17 |= MD_RESERVED17_ON; 6205141cc406Sopenharmony_ci } 6206141cc406Sopenharmony_ci 6207141cc406Sopenharmony_ci get_calib_params(ms); 6208141cc406Sopenharmony_ci 6209141cc406Sopenharmony_ci#ifdef NO_PHANTOMTYPE_SHADING 6210141cc406Sopenharmony_ci/* md->status.stick &= ~MD_STICK_ON; */ 6211141cc406Sopenharmony_ci/* md->status.ncalib &= ~MD_NCALIB_ON; */ 6212141cc406Sopenharmony_ci/* md->status.reserved17 &= ~MD_RESERVED17_ON; */ 6213141cc406Sopenharmony_ci ms->rawdat = 0; 6214141cc406Sopenharmony_ci#endif 6215141cc406Sopenharmony_ci 6216141cc406Sopenharmony_ci status = scsi_send_system_status(md, ms->sfd); 6217141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6218141cc406Sopenharmony_ci return status; 6219141cc406Sopenharmony_ci 6220141cc406Sopenharmony_ci status = scsi_set_window(ms, 1); 6221141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6222141cc406Sopenharmony_ci return status; 6223141cc406Sopenharmony_ci 6224141cc406Sopenharmony_ci#ifdef TESTBACKEND 6225141cc406Sopenharmony_ci status = scsi_read_sh_image_info(ms); 6226141cc406Sopenharmony_ci#else 6227141cc406Sopenharmony_ci status = scsi_read_image_info(ms); 6228141cc406Sopenharmony_ci#endif 6229141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6230141cc406Sopenharmony_ci return status; 6231141cc406Sopenharmony_ci 6232141cc406Sopenharmony_ci status = scsi_wait_for_image(ms); 6233141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6234141cc406Sopenharmony_ci return status; 6235141cc406Sopenharmony_ci 6236141cc406Sopenharmony_ci#ifdef NO_PHANTOMTYPE_SHADING 6237141cc406Sopenharmony_ci if ( !( md->model_flags & MD_READ_CONTROL_BIT ) ) 6238141cc406Sopenharmony_ci { 6239141cc406Sopenharmony_ci#endif 6240141cc406Sopenharmony_ci status = scsi_read_system_status(md, ms->sfd); 6241141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6242141cc406Sopenharmony_ci return status; 6243141cc406Sopenharmony_ci#ifdef NO_PHANTOMTYPE_SHADING 6244141cc406Sopenharmony_ci } 6245141cc406Sopenharmony_ci#endif 6246141cc406Sopenharmony_ci 6247141cc406Sopenharmony_ci#ifdef NO_PHANTOMTYPE_SHADING 6248141cc406Sopenharmony_ci if ( mi->model_code == 0x94 ) 6249141cc406Sopenharmony_ci status = scsi_read_control_bits(ms); 6250141cc406Sopenharmony_ci#endif 6251141cc406Sopenharmony_ci 6252141cc406Sopenharmony_ci ms->shading_image = malloc(ms->bpl * ms->src_remaining_lines); 6253141cc406Sopenharmony_ci DBG(100, "read shading image: ms->shading_image=%p, malloc'd %d bytes\n", 6254141cc406Sopenharmony_ci (void *) ms->shading_image, ms->bpl * ms->src_remaining_lines); 6255141cc406Sopenharmony_ci if ( ms->shading_image == NULL ) 6256141cc406Sopenharmony_ci { 6257141cc406Sopenharmony_ci DBG(1, "read_shading_image: malloc for buffer failed\n"); 6258141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6259141cc406Sopenharmony_ci } 6260141cc406Sopenharmony_ci 6261141cc406Sopenharmony_ci buf = ms->shading_image; 6262141cc406Sopenharmony_ci#ifdef TESTBACKEND 6263141cc406Sopenharmony_ci max_lines = 5000000 / ms->bpl; 6264141cc406Sopenharmony_ci#else 6265141cc406Sopenharmony_ci max_lines = sanei_scsi_max_request_size / ms->bpl; 6266141cc406Sopenharmony_ci#endif 6267141cc406Sopenharmony_ci if ( max_lines == 0 ) 6268141cc406Sopenharmony_ci { 6269141cc406Sopenharmony_ci DBG(1, "read_shading_image: buffer too small\n"); 6270141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 6271141cc406Sopenharmony_ci } 6272141cc406Sopenharmony_ci lines = ms->src_remaining_lines; 6273141cc406Sopenharmony_ci while ( ms->src_remaining_lines > 0 ) 6274141cc406Sopenharmony_ci { 6275141cc406Sopenharmony_ci lines_to_read = MIN(max_lines, ms->src_remaining_lines); 6276141cc406Sopenharmony_ci ms->src_buffer_size = lines_to_read * ms->bpl; 6277141cc406Sopenharmony_ci ms->transfer_length = ms->src_buffer_size; 6278141cc406Sopenharmony_ci 6279141cc406Sopenharmony_ci#ifdef TESTBACKEND 6280141cc406Sopenharmony_ci status = scsi_read_sh_w_image(ms, buf); 6281141cc406Sopenharmony_ci#else 6282141cc406Sopenharmony_ci status = scsi_read_image(ms, buf, md->shading_depth>8 ? 2 : 1); 6283141cc406Sopenharmony_ci#endif 6284141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6285141cc406Sopenharmony_ci return status; 6286141cc406Sopenharmony_ci 6287141cc406Sopenharmony_ci ms->src_remaining_lines -= lines_to_read; 6288141cc406Sopenharmony_ci buf += ms->src_buffer_size; 6289141cc406Sopenharmony_ci } 6290141cc406Sopenharmony_ci 6291141cc406Sopenharmony_ci status = prepare_shading_data(ms, lines, &md->shading_table_w); 6292141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6293141cc406Sopenharmony_ci return status; 6294141cc406Sopenharmony_ci 6295141cc406Sopenharmony_ci if ( md_dump >= 3 ) 6296141cc406Sopenharmony_ci { 6297141cc406Sopenharmony_ci write_shading_buf_pnm(ms, lines); 6298141cc406Sopenharmony_ci write_shading_pnm(ms); 6299141cc406Sopenharmony_ci } 6300141cc406Sopenharmony_ci 6301141cc406Sopenharmony_ci /* send shading data to the device */ 6302141cc406Sopenharmony_ci /* Some models use "read_control bit", and the shading must be */ 6303141cc406Sopenharmony_ci /* applied by the backend later */ 6304141cc406Sopenharmony_ci if ( ! (md->model_flags & MD_READ_CONTROL_BIT) ) 6305141cc406Sopenharmony_ci { 6306141cc406Sopenharmony_ci status = shading_function(ms, md->shading_table_w); 6307141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6308141cc406Sopenharmony_ci return status; 6309141cc406Sopenharmony_ci 6310141cc406Sopenharmony_ci ms->word = ms->lut_entry_size == 2 ? 1 : 0; 6311141cc406Sopenharmony_ci ms->current_color = MS_COLOR_ALL; 6312141cc406Sopenharmony_ci status = scsi_send_shading(ms, 6313141cc406Sopenharmony_ci md->shading_table_w, 6314141cc406Sopenharmony_ci 3 * ms->lut_entry_size 6315141cc406Sopenharmony_ci * mi->geo_width / mi->calib_divisor, 6316141cc406Sopenharmony_ci 0); 6317141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6318141cc406Sopenharmony_ci return status; 6319141cc406Sopenharmony_ci } 6320141cc406Sopenharmony_ci 6321141cc406Sopenharmony_ci ms->rawdat = 0; 6322141cc406Sopenharmony_ci ms->stay = 0; 6323141cc406Sopenharmony_ci md->status.ncalib |= MD_NCALIB_ON; 6324141cc406Sopenharmony_ci 6325141cc406Sopenharmony_ci if ( md->model_flags & MD_PHANTOM_C6 ) 6326141cc406Sopenharmony_ci { 6327141cc406Sopenharmony_ci md->status.stick &= ~MD_STICK_ON; 6328141cc406Sopenharmony_ci md->status.reserved17 &= ~MD_RESERVED17_ON; 6329141cc406Sopenharmony_ci } 6330141cc406Sopenharmony_ci 6331141cc406Sopenharmony_ci#ifdef NO_PHANTOMTYPE_SHADING 6332141cc406Sopenharmony_ci if (mi->model_code == 0x94) 6333141cc406Sopenharmony_ci md->status.ncalib &= ~MD_NCALIB_ON; 6334141cc406Sopenharmony_ci#endif 6335141cc406Sopenharmony_ci 6336141cc406Sopenharmony_ci status = scsi_send_system_status(md, ms->sfd); 6337141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6338141cc406Sopenharmony_ci return status; 6339141cc406Sopenharmony_ci 6340141cc406Sopenharmony_ci DBG(100, "free memory for ms->shading_image at %p\n", 6341141cc406Sopenharmony_ci (void *) ms->shading_image); 6342141cc406Sopenharmony_ci free((void *) ms->shading_image); 6343141cc406Sopenharmony_ci ms->shading_image = NULL; 6344141cc406Sopenharmony_ci 6345141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6346141cc406Sopenharmony_ci 6347141cc406Sopenharmony_ci} 6348141cc406Sopenharmony_ci 6349141cc406Sopenharmony_ci/*---------- prepare_shading_data() ------------------------------------------*/ 6350141cc406Sopenharmony_ci 6351141cc406Sopenharmony_cistatic SANE_Status 6352141cc406Sopenharmony_ciprepare_shading_data(Microtek2_Scanner *ms, uint32_t lines, uint8_t **data) 6353141cc406Sopenharmony_ci{ 6354141cc406Sopenharmony_ci /* This function calculates one line of black or white shading data */ 6355141cc406Sopenharmony_ci /* from the shading image. At the end we have one line. The */ 6356141cc406Sopenharmony_ci /* color sequence is unchanged. */ 6357141cc406Sopenharmony_ci 6358141cc406Sopenharmony_ci#define MICROTEK2_CALIB_USE_MEDIAN 6359141cc406Sopenharmony_ci 6360141cc406Sopenharmony_ci Microtek2_Device *md; 6361141cc406Sopenharmony_ci Microtek2_Info *mi; 6362141cc406Sopenharmony_ci uint32_t length,line; 6363141cc406Sopenharmony_ci int color, i; 6364141cc406Sopenharmony_ci SANE_Status status; 6365141cc406Sopenharmony_ci 6366141cc406Sopenharmony_ci#ifdef MICROTEK2_CALIB_USE_MEDIAN 6367141cc406Sopenharmony_ci uint16_t *sortbuf, value; 6368141cc406Sopenharmony_ci#else 6369141cc406Sopenharmony_ci uint32_t value; 6370141cc406Sopenharmony_ci#endif 6371141cc406Sopenharmony_ci 6372141cc406Sopenharmony_ci DBG(30, "prepare_shading_data: ms=%p, lines=%d, *data=%p\n", 6373141cc406Sopenharmony_ci (void *) ms, lines, (void *) *data); 6374141cc406Sopenharmony_ci 6375141cc406Sopenharmony_ci md = ms->dev; 6376141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 6377141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 6378141cc406Sopenharmony_ci 6379141cc406Sopenharmony_ci get_lut_size(mi, &ms->lut_size, &ms->lut_entry_size); 6380141cc406Sopenharmony_ci length = 3 * ms->lut_entry_size * mi->geo_width / mi->calib_divisor; 6381141cc406Sopenharmony_ci 6382141cc406Sopenharmony_ci if ( *data == NULL ) 6383141cc406Sopenharmony_ci { 6384141cc406Sopenharmony_ci *data = (uint8_t *) malloc(length); 6385141cc406Sopenharmony_ci DBG(100, "prepare_shading_data: malloc'd %d bytes at %p\n", 6386141cc406Sopenharmony_ci length, (void *) *data); 6387141cc406Sopenharmony_ci if ( *data == NULL ) 6388141cc406Sopenharmony_ci { 6389141cc406Sopenharmony_ci DBG(1, "prepare_shading_data: malloc for shading table failed\n"); 6390141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6391141cc406Sopenharmony_ci } 6392141cc406Sopenharmony_ci } 6393141cc406Sopenharmony_ci 6394141cc406Sopenharmony_ci#ifdef MICROTEK2_CALIB_USE_MEDIAN 6395141cc406Sopenharmony_ci sortbuf = malloc( lines * ms->lut_entry_size ); 6396141cc406Sopenharmony_ci DBG(100, "prepare_shading_data: sortbuf= %p, malloc'd %d Bytes\n", 6397141cc406Sopenharmony_ci (void *) sortbuf, lines * ms->lut_entry_size); 6398141cc406Sopenharmony_ci if ( sortbuf == NULL ) 6399141cc406Sopenharmony_ci { 6400141cc406Sopenharmony_ci DBG(1, "prepare_shading_data: malloc for sort buffer failed\n"); 6401141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6402141cc406Sopenharmony_ci } 6403141cc406Sopenharmony_ci#endif 6404141cc406Sopenharmony_ci 6405141cc406Sopenharmony_ci switch( mi->data_format ) 6406141cc406Sopenharmony_ci { 6407141cc406Sopenharmony_ci case MI_DATAFMT_LPLCONCAT: 6408141cc406Sopenharmony_ci if ( ms->lut_entry_size == 1 ) 6409141cc406Sopenharmony_ci { 6410141cc406Sopenharmony_ci DBG(1, "prepare_shading_data: wordsize == 1 unsupported\n"); 6411141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 6412141cc406Sopenharmony_ci } 6413141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 6414141cc406Sopenharmony_ci { 6415141cc406Sopenharmony_ci for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++ ) 6416141cc406Sopenharmony_ci { 6417141cc406Sopenharmony_ci value = 0; 6418141cc406Sopenharmony_ci for ( line = 0; line < lines; line++ ) 6419141cc406Sopenharmony_ci#ifndef MICROTEK2_CALIB_USE_MEDIAN 6420141cc406Sopenharmony_ci/* average the shading lines to get the shading data */ 6421141cc406Sopenharmony_ci value += *((uint16_t *) ms->shading_image 6422141cc406Sopenharmony_ci + line * ( ms->bpl / ms->lut_entry_size ) 6423141cc406Sopenharmony_ci + color * ( ms->bpl / ms->lut_entry_size / 3 ) 6424141cc406Sopenharmony_ci + i); 6425141cc406Sopenharmony_ci value /= lines; 6426141cc406Sopenharmony_ci *((uint16_t *) *data 6427141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = 6428141cc406Sopenharmony_ci (uint16_t) MIN(0xffff, value); 6429141cc406Sopenharmony_ci#else 6430141cc406Sopenharmony_ci/* use a median filter to get the shading data -- should be better */ 6431141cc406Sopenharmony_ci *(sortbuf + line ) = 6432141cc406Sopenharmony_ci *((uint16_t *) ms->shading_image 6433141cc406Sopenharmony_ci + line * ( ms->bpl / ms->lut_entry_size ) 6434141cc406Sopenharmony_ci + color * ( ms->bpl / ms->lut_entry_size / 3 ) 6435141cc406Sopenharmony_ci + i); 6436141cc406Sopenharmony_ci qsort(sortbuf, lines, sizeof(uint16_t), 6437141cc406Sopenharmony_ci (qsortfunc)compare_func_16); 6438141cc406Sopenharmony_ci value = *(sortbuf + ( lines - 1 ) / 2 ); 6439141cc406Sopenharmony_ci *((uint16_t *) *data 6440141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = value; 6441141cc406Sopenharmony_ci#endif 6442141cc406Sopenharmony_ci } 6443141cc406Sopenharmony_ci } 6444141cc406Sopenharmony_ci break; 6445141cc406Sopenharmony_ci 6446141cc406Sopenharmony_ci case MI_DATAFMT_CHUNKY: 6447141cc406Sopenharmony_ci case MI_DATAFMT_9800: 6448141cc406Sopenharmony_ci if ( ms->lut_entry_size == 1 ) 6449141cc406Sopenharmony_ci { 6450141cc406Sopenharmony_ci DBG(1, "prepare_shading_data: wordsize == 1 unsupported\n"); 6451141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 6452141cc406Sopenharmony_ci } 6453141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 6454141cc406Sopenharmony_ci { 6455141cc406Sopenharmony_ci for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++ ) 6456141cc406Sopenharmony_ci { 6457141cc406Sopenharmony_ci value = 0; 6458141cc406Sopenharmony_ci for ( line = 0; line < lines; line++ ) 6459141cc406Sopenharmony_ci#ifndef MICROTEK2_CALIB_USE_MEDIAN 6460141cc406Sopenharmony_ci/* average the shading lines to get the shading data */ 6461141cc406Sopenharmony_ci value += *((uint16_t *) ms->shading_image 6462141cc406Sopenharmony_ci + line * 3 * mi->geo_width / mi->calib_divisor 6463141cc406Sopenharmony_ci + 3 * i 6464141cc406Sopenharmony_ci + color); 6465141cc406Sopenharmony_ci 6466141cc406Sopenharmony_ci value /= lines; 6467141cc406Sopenharmony_ci *((uint16_t *) *data 6468141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = 6469141cc406Sopenharmony_ci (uint16_t) MIN(0xffff, value); 6470141cc406Sopenharmony_ci#else 6471141cc406Sopenharmony_ci/* use a median filter to get the shading data -- should be better */ 6472141cc406Sopenharmony_ci *(sortbuf + line ) = 6473141cc406Sopenharmony_ci *((uint16_t *) ms->shading_image 6474141cc406Sopenharmony_ci + line * 3 * mi->geo_width / mi->calib_divisor 6475141cc406Sopenharmony_ci + 3 * i 6476141cc406Sopenharmony_ci + color); 6477141cc406Sopenharmony_ci qsort(sortbuf, lines, sizeof(uint16_t), 6478141cc406Sopenharmony_ci (qsortfunc)compare_func_16); 6479141cc406Sopenharmony_ci value = *(sortbuf + ( lines - 1 ) / 2 ); 6480141cc406Sopenharmony_ci *((uint16_t *) *data 6481141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = value; 6482141cc406Sopenharmony_ci#endif 6483141cc406Sopenharmony_ci } 6484141cc406Sopenharmony_ci } 6485141cc406Sopenharmony_ci break; 6486141cc406Sopenharmony_ci 6487141cc406Sopenharmony_ci case MI_DATAFMT_LPLSEGREG: 6488141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 6489141cc406Sopenharmony_ci { 6490141cc406Sopenharmony_ci for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++ ) 6491141cc406Sopenharmony_ci { 6492141cc406Sopenharmony_ci value = 0; 6493141cc406Sopenharmony_ci if ( ms->lut_entry_size == 1 ) 6494141cc406Sopenharmony_ci { 6495141cc406Sopenharmony_ci for ( line = 0; line < lines; line++ ) 6496141cc406Sopenharmony_ci value += *((uint8_t *) ms->shading_image 6497141cc406Sopenharmony_ci + line * 3 * mi->geo_width / mi->calib_divisor 6498141cc406Sopenharmony_ci + 3 * i 6499141cc406Sopenharmony_ci + color); 6500141cc406Sopenharmony_ci 6501141cc406Sopenharmony_ci value /= lines; 6502141cc406Sopenharmony_ci *((uint8_t *) *data 6503141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = 6504141cc406Sopenharmony_ci (uint8_t) MIN(0xff, value); 6505141cc406Sopenharmony_ci 6506141cc406Sopenharmony_ci } 6507141cc406Sopenharmony_ci else 6508141cc406Sopenharmony_ci { 6509141cc406Sopenharmony_ci for ( line = 0; line < lines; line++ ) 6510141cc406Sopenharmony_ci value += *((uint16_t *) ms->shading_image 6511141cc406Sopenharmony_ci + line * 3 * mi->geo_width / mi->calib_divisor 6512141cc406Sopenharmony_ci + 3 * i 6513141cc406Sopenharmony_ci + color); 6514141cc406Sopenharmony_ci 6515141cc406Sopenharmony_ci value /= lines; 6516141cc406Sopenharmony_ci#ifndef MICROTEK2_CALIB_USE_MEDIAN 6517141cc406Sopenharmony_ci *((uint16_t *) *data 6518141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = 6519141cc406Sopenharmony_ci (uint16_t) MIN(0xffff, value); 6520141cc406Sopenharmony_ci#else 6521141cc406Sopenharmony_ci *((uint16_t *) *data 6522141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = value; 6523141cc406Sopenharmony_ci#endif 6524141cc406Sopenharmony_ci } 6525141cc406Sopenharmony_ci 6526141cc406Sopenharmony_ci } 6527141cc406Sopenharmony_ci } 6528141cc406Sopenharmony_ci break; 6529141cc406Sopenharmony_ci 6530141cc406Sopenharmony_ci default: 6531141cc406Sopenharmony_ci DBG(1, "prepare_shading_data: Unsupported data format 0x%02x\n", 6532141cc406Sopenharmony_ci mi->data_format); 6533141cc406Sopenharmony_ci status = SANE_STATUS_UNSUPPORTED; 6534141cc406Sopenharmony_ci } 6535141cc406Sopenharmony_ci 6536141cc406Sopenharmony_ci#ifdef MICROTEK2_CALIB_USE_MEDIAN 6537141cc406Sopenharmony_ci DBG(100, "prepare_shading_data: free sortbuf at %p\n", (void *) sortbuf); 6538141cc406Sopenharmony_ci free(sortbuf); 6539141cc406Sopenharmony_ci sortbuf = NULL; 6540141cc406Sopenharmony_ci#endif 6541141cc406Sopenharmony_ci return status; 6542141cc406Sopenharmony_ci} 6543141cc406Sopenharmony_ci 6544141cc406Sopenharmony_ci 6545141cc406Sopenharmony_ci/*---------- read_cx_shading() -----------------------------------------------*/ 6546141cc406Sopenharmony_ci 6547141cc406Sopenharmony_cistatic SANE_Status 6548141cc406Sopenharmony_ciread_cx_shading(Microtek2_Scanner *ms) 6549141cc406Sopenharmony_ci{ 6550141cc406Sopenharmony_ci SANE_Status status; 6551141cc406Sopenharmony_ci Microtek2_Device *md; 6552141cc406Sopenharmony_ci md = ms->dev; 6553141cc406Sopenharmony_ci 6554141cc406Sopenharmony_ci DBG(30, "read_cx_shading: ms=%p\n",(void *) ms); 6555141cc406Sopenharmony_ci 6556141cc406Sopenharmony_ci md->shading_table_contents = ms->mode; 6557141cc406Sopenharmony_ci 6558141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_COLOR ) 6559141cc406Sopenharmony_ci ms->current_color = MS_COLOR_ALL; 6560141cc406Sopenharmony_ci else 6561141cc406Sopenharmony_ci ms->current_color = MS_COLOR_GREEN; /* for grayscale */ 6562141cc406Sopenharmony_ci 6563141cc406Sopenharmony_ci ms->word = 1; 6564141cc406Sopenharmony_ci ms->dark = 0; 6565141cc406Sopenharmony_ci 6566141cc406Sopenharmony_ci status = read_cx_shading_image(ms); 6567141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6568141cc406Sopenharmony_ci goto cleanup; 6569141cc406Sopenharmony_ci 6570141cc406Sopenharmony_ci ms->word = 0; /* the Windows driver reads dark shading with word=0 */ 6571141cc406Sopenharmony_ci ms->dark = 1; 6572141cc406Sopenharmony_ci status = read_cx_shading_image(ms); 6573141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6574141cc406Sopenharmony_ci goto cleanup; 6575141cc406Sopenharmony_ci 6576141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6577141cc406Sopenharmony_ci 6578141cc406Sopenharmony_cicleanup: 6579141cc406Sopenharmony_ci cleanup_scanner(ms); 6580141cc406Sopenharmony_ci return status; 6581141cc406Sopenharmony_ci} 6582141cc406Sopenharmony_ci 6583141cc406Sopenharmony_ci 6584141cc406Sopenharmony_ci/*---------- read_cx_shading_image() -----------------------------------------*/ 6585141cc406Sopenharmony_ci 6586141cc406Sopenharmony_cistatic SANE_Status 6587141cc406Sopenharmony_ciread_cx_shading_image(Microtek2_Scanner *ms) 6588141cc406Sopenharmony_ci{ 6589141cc406Sopenharmony_ci SANE_Status status; 6590141cc406Sopenharmony_ci Microtek2_Device *md; 6591141cc406Sopenharmony_ci uint32_t shading_bytes, linesize, buffer_size; 6592141cc406Sopenharmony_ci uint8_t *buf; 6593141cc406Sopenharmony_ci int max_lines, lines_to_read, remaining_lines; 6594141cc406Sopenharmony_ci 6595141cc406Sopenharmony_ci md = ms->dev; 6596141cc406Sopenharmony_ci 6597141cc406Sopenharmony_ci shading_bytes = ms->n_control_bytes * 8 * md->shading_length; 6598141cc406Sopenharmony_ci if ( ms->current_color == MS_COLOR_ALL ) 6599141cc406Sopenharmony_ci shading_bytes *= 3; 6600141cc406Sopenharmony_ci if ( ms->word == 1 ) 6601141cc406Sopenharmony_ci shading_bytes *= 2; 6602141cc406Sopenharmony_ci 6603141cc406Sopenharmony_ci if ( ms->shading_image ) 6604141cc406Sopenharmony_ci { 6605141cc406Sopenharmony_ci free((void *) ms->shading_image); 6606141cc406Sopenharmony_ci ms->shading_image = NULL; 6607141cc406Sopenharmony_ci } 6608141cc406Sopenharmony_ci ms->shading_image = malloc(shading_bytes); 6609141cc406Sopenharmony_ci DBG(100, "read_cx_shading: ms->shading_image=%p, malloc'd %d bytes\n", 6610141cc406Sopenharmony_ci (void *) ms->shading_image, shading_bytes); 6611141cc406Sopenharmony_ci if ( ms->shading_image == NULL ) 6612141cc406Sopenharmony_ci { 6613141cc406Sopenharmony_ci DBG(1, "read_cx_shading: malloc for cx_shading buffer failed\n"); 6614141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6615141cc406Sopenharmony_ci } 6616141cc406Sopenharmony_ci 6617141cc406Sopenharmony_ci buf = ms->shading_image; 6618141cc406Sopenharmony_ci 6619141cc406Sopenharmony_ci DBG(30, "read_cx_shading_image: ms=%p, shading_bytes=%d\n", 6620141cc406Sopenharmony_ci (void *) ms, shading_bytes); 6621141cc406Sopenharmony_ci 6622141cc406Sopenharmony_ci linesize = shading_bytes / md->shading_length; 6623141cc406Sopenharmony_ci#ifdef TESTBACKEND 6624141cc406Sopenharmony_ci max_lines = 5000000 / linesize; 6625141cc406Sopenharmony_ci#else 6626141cc406Sopenharmony_ci max_lines = sanei_scsi_max_request_size / linesize; 6627141cc406Sopenharmony_ci#endif 6628141cc406Sopenharmony_ci /* the following part is like in "read_shading_image" */ 6629141cc406Sopenharmony_ci remaining_lines = md->shading_length; 6630141cc406Sopenharmony_ci while ( remaining_lines > 0 ) 6631141cc406Sopenharmony_ci { 6632141cc406Sopenharmony_ci lines_to_read = MIN(max_lines, remaining_lines); 6633141cc406Sopenharmony_ci buffer_size = lines_to_read * linesize; 6634141cc406Sopenharmony_ci 6635141cc406Sopenharmony_ci status = scsi_read_shading(ms, buf, buffer_size); 6636141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6637141cc406Sopenharmony_ci { 6638141cc406Sopenharmony_ci DBG(1, "read_cx_shading: '%s'\n", sane_strstatus(status)); 6639141cc406Sopenharmony_ci return status; 6640141cc406Sopenharmony_ci } 6641141cc406Sopenharmony_ci remaining_lines -= lines_to_read; 6642141cc406Sopenharmony_ci buf += buffer_size; 6643141cc406Sopenharmony_ci } 6644141cc406Sopenharmony_ci 6645141cc406Sopenharmony_ci status = calc_cx_shading_line(ms); 6646141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 6647141cc406Sopenharmony_ci { 6648141cc406Sopenharmony_ci DBG(1, "read_cx_shading: '%s'\n", sane_strstatus(status)); 6649141cc406Sopenharmony_ci return status; 6650141cc406Sopenharmony_ci } 6651141cc406Sopenharmony_ci 6652141cc406Sopenharmony_ci if ( ms->shading_image ) 6653141cc406Sopenharmony_ci { 6654141cc406Sopenharmony_ci DBG(100, "free memory for ms->shading_image at %p\n", 6655141cc406Sopenharmony_ci (void *) ms->shading_image); 6656141cc406Sopenharmony_ci free((void *) ms->shading_image); 6657141cc406Sopenharmony_ci ms->shading_image = NULL; 6658141cc406Sopenharmony_ci } 6659141cc406Sopenharmony_ci 6660141cc406Sopenharmony_ci return status; 6661141cc406Sopenharmony_ci} 6662141cc406Sopenharmony_ci 6663141cc406Sopenharmony_ci/*---------- calc_cx_shading_line() ------------------------------------------*/ 6664141cc406Sopenharmony_ci/* calculates the mean value of the shading lines and stores one line of */ 6665141cc406Sopenharmony_ci/* 8-bit shading data. Scanning direction + color sequence remain as they are */ 6666141cc406Sopenharmony_ci/* ToDo: more than 8-bit data */ 6667141cc406Sopenharmony_ci 6668141cc406Sopenharmony_cistatic SANE_Status 6669141cc406Sopenharmony_cicalc_cx_shading_line(Microtek2_Scanner *ms) 6670141cc406Sopenharmony_ci{ 6671141cc406Sopenharmony_ci Microtek2_Device *md; 6672141cc406Sopenharmony_ci SANE_Status status; 6673141cc406Sopenharmony_ci uint8_t *current_byte, *buf, *shading_table_pointer; 6674141cc406Sopenharmony_ci uint8_t color, factor; 6675141cc406Sopenharmony_ci uint32_t shading_line_pixels, shading_line_bytes, 6676141cc406Sopenharmony_ci shading_data_bytes, line, i, accu, color_offset; 6677141cc406Sopenharmony_ci uint16_t *sortbuf, value; 6678141cc406Sopenharmony_ci 6679141cc406Sopenharmony_ci md = ms->dev; 6680141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 6681141cc406Sopenharmony_ci 6682141cc406Sopenharmony_ci sortbuf = malloc( md->shading_length * sizeof(float) ); 6683141cc406Sopenharmony_ci DBG(100, "calc_cx_shading: sortbuf= %p, malloc'd %lu Bytes\n", 6684141cc406Sopenharmony_ci (void *) sortbuf, (u_long) (md->shading_length * sizeof(float))); 6685141cc406Sopenharmony_ci if ( sortbuf == NULL ) 6686141cc406Sopenharmony_ci { 6687141cc406Sopenharmony_ci DBG(1, "calc_cx_shading: malloc for sort buffer failed\n"); 6688141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6689141cc406Sopenharmony_ci } 6690141cc406Sopenharmony_ci 6691141cc406Sopenharmony_ci buf = ms->shading_image; 6692141cc406Sopenharmony_ci shading_line_pixels = ms->n_control_bytes * 8; /* = 2560 for 330CX */ 6693141cc406Sopenharmony_ci shading_line_bytes = shading_line_pixels; /* grayscale */ 6694141cc406Sopenharmony_ci if ( ms->mode == MS_MODE_COLOR ) /* color */ 6695141cc406Sopenharmony_ci shading_line_bytes *= 3; 6696141cc406Sopenharmony_ci shading_data_bytes = shading_line_bytes; /* 8-bit color depth */ 6697141cc406Sopenharmony_ci if (ms->word == 1) /* > 8-bit color depth */ 6698141cc406Sopenharmony_ci shading_data_bytes *= 2; 6699141cc406Sopenharmony_ci factor = 4; /* shading bit depth = 10bit; shading line bit depth = 8bit */ 6700141cc406Sopenharmony_ci 6701141cc406Sopenharmony_ci if (ms->dark == 0) /* white shading data */ 6702141cc406Sopenharmony_ci { 6703141cc406Sopenharmony_ci if ( md->shading_table_w ) 6704141cc406Sopenharmony_ci free( (void *)md->shading_table_w ); 6705141cc406Sopenharmony_ci md->shading_table_w = (uint8_t *) malloc(shading_line_bytes); 6706141cc406Sopenharmony_ci DBG(100, "calc_cx_shading: md->shading_table_w=%p, malloc'd %d bytes\n", 6707141cc406Sopenharmony_ci (void *) md->shading_table_w, shading_line_bytes); 6708141cc406Sopenharmony_ci if ( md->shading_table_w == NULL ) 6709141cc406Sopenharmony_ci { 6710141cc406Sopenharmony_ci DBG(100, "calc_cx_shading: malloc for white shadingtable failed\n"); 6711141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 6712141cc406Sopenharmony_ci cleanup_scanner(ms); 6713141cc406Sopenharmony_ci } 6714141cc406Sopenharmony_ci 6715141cc406Sopenharmony_ci shading_table_pointer = md->shading_table_w; 6716141cc406Sopenharmony_ci } 6717141cc406Sopenharmony_ci 6718141cc406Sopenharmony_ci else /* dark shading data */ 6719141cc406Sopenharmony_ci { 6720141cc406Sopenharmony_ci if ( md->shading_table_d ) 6721141cc406Sopenharmony_ci free( (void *)md->shading_table_d); 6722141cc406Sopenharmony_ci md->shading_table_d = (uint8_t *) malloc(shading_line_bytes); 6723141cc406Sopenharmony_ci DBG(100, "calc_cx_shading: md->shading_table_d=%p, malloc'd %d bytes\n", 6724141cc406Sopenharmony_ci (void *) md->shading_table_d, shading_line_bytes); 6725141cc406Sopenharmony_ci 6726141cc406Sopenharmony_ci if ( md->shading_table_d == NULL ) 6727141cc406Sopenharmony_ci { 6728141cc406Sopenharmony_ci DBG(1, "calc_cx_shading: malloc for dark shading table failed\n"); 6729141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 6730141cc406Sopenharmony_ci cleanup_scanner(ms); 6731141cc406Sopenharmony_ci } 6732141cc406Sopenharmony_ci 6733141cc406Sopenharmony_ci shading_table_pointer = md->shading_table_d; 6734141cc406Sopenharmony_ci } 6735141cc406Sopenharmony_ci 6736141cc406Sopenharmony_ci DBG(30, "calc_cx_shading_line: ms=%p\n" 6737141cc406Sopenharmony_ci "md->shading_table_w=%p\n" 6738141cc406Sopenharmony_ci "md->shading_table_d=%p\n" 6739141cc406Sopenharmony_ci "shading_line_bytes=%d\n" 6740141cc406Sopenharmony_ci "shading_line_pixels=%d\n" 6741141cc406Sopenharmony_ci "shading_table_pointer=%p\n", 6742141cc406Sopenharmony_ci (void *) ms, (void *) md->shading_table_w, 6743141cc406Sopenharmony_ci (void *) md->shading_table_d, shading_line_bytes, 6744141cc406Sopenharmony_ci shading_line_pixels, (void *) shading_table_pointer); 6745141cc406Sopenharmony_ci 6746141cc406Sopenharmony_ci /* calculating the median pixel values over the shading lines */ 6747141cc406Sopenharmony_ci /* and write them to the shading table */ 6748141cc406Sopenharmony_ci for (color = 0; color < 3; color++) 6749141cc406Sopenharmony_ci { 6750141cc406Sopenharmony_ci color_offset = color * shading_line_pixels; 6751141cc406Sopenharmony_ci if ( ms->word == 1 ) 6752141cc406Sopenharmony_ci color_offset *=2; 6753141cc406Sopenharmony_ci 6754141cc406Sopenharmony_ci for (i = 0; i < shading_line_pixels; i++) 6755141cc406Sopenharmony_ci { 6756141cc406Sopenharmony_ci value = 0; 6757141cc406Sopenharmony_ci for (line = 0; line < md->shading_length; line++) 6758141cc406Sopenharmony_ci { 6759141cc406Sopenharmony_ci current_byte = buf + ( line * shading_data_bytes ) 6760141cc406Sopenharmony_ci + color_offset + i; 6761141cc406Sopenharmony_ci accu = *current_byte; 6762141cc406Sopenharmony_ci 6763141cc406Sopenharmony_ci /* word shading data: the lower bytes per line and color are */ 6764141cc406Sopenharmony_ci /* transferred first in one block and then the high bytes */ 6765141cc406Sopenharmony_ci /* in one block */ 6766141cc406Sopenharmony_ci /* the dark shading data is also 10 bit, but only the */ 6767141cc406Sopenharmony_ci /* low byte is transferred (ms->word = 0) */ 6768141cc406Sopenharmony_ci if ( ms->word == 1 ) 6769141cc406Sopenharmony_ci { 6770141cc406Sopenharmony_ci current_byte = buf + ( line * shading_data_bytes ) 6771141cc406Sopenharmony_ci + color_offset + shading_line_pixels + i; 6772141cc406Sopenharmony_ci accu += ( *current_byte * 256 ); 6773141cc406Sopenharmony_ci } 6774141cc406Sopenharmony_ci *( sortbuf + line ) = accu; 6775141cc406Sopenharmony_ci } 6776141cc406Sopenharmony_ci/* this is the Median filter: sort the values ascending and take the middlest */ 6777141cc406Sopenharmony_ci qsort(sortbuf, md->shading_length, sizeof(float), 6778141cc406Sopenharmony_ci (qsortfunc)compare_func_16); 6779141cc406Sopenharmony_ci value = *( sortbuf + ( md->shading_length - 1 ) / 2 ); 6780141cc406Sopenharmony_ci *shading_table_pointer = (uint8_t) (value / factor); 6781141cc406Sopenharmony_ci shading_table_pointer++; 6782141cc406Sopenharmony_ci } 6783141cc406Sopenharmony_ci if ( ms->mode != MS_MODE_COLOR ) 6784141cc406Sopenharmony_ci break; 6785141cc406Sopenharmony_ci } 6786141cc406Sopenharmony_ci return status; 6787141cc406Sopenharmony_ci} 6788141cc406Sopenharmony_ci 6789141cc406Sopenharmony_ci 6790141cc406Sopenharmony_ci 6791141cc406Sopenharmony_ci/*---------- get_lut_size() --------------------------------------------------*/ 6792141cc406Sopenharmony_ci 6793141cc406Sopenharmony_cistatic SANE_Status 6794141cc406Sopenharmony_ciget_lut_size(Microtek2_Info *mi, int *max_lut_size, int *lut_entry_size) 6795141cc406Sopenharmony_ci{ 6796141cc406Sopenharmony_ci /* returns the maximum lookup table size. A device might indicate */ 6797141cc406Sopenharmony_ci /* several lookup table sizes. */ 6798141cc406Sopenharmony_ci 6799141cc406Sopenharmony_ci DBG(30, "get_lut_size: mi=%p\n", (void *) mi); 6800141cc406Sopenharmony_ci 6801141cc406Sopenharmony_ci *max_lut_size = 0; 6802141cc406Sopenharmony_ci *lut_entry_size = 0; 6803141cc406Sopenharmony_ci 6804141cc406Sopenharmony_ci /* Normally this function is used for both gamma and shading tables */ 6805141cc406Sopenharmony_ci /* If, however, the device indicates, that it does not support */ 6806141cc406Sopenharmony_ci /* lookup tables, we set these values as if the device has a maximum */ 6807141cc406Sopenharmony_ci /* bitdepth of 12, and these values are only used to determine the */ 6808141cc406Sopenharmony_ci /* size of the shading table */ 6809141cc406Sopenharmony_ci if ( MI_LUTCAP_NONE(mi->lut_cap) ) 6810141cc406Sopenharmony_ci { 6811141cc406Sopenharmony_ci *max_lut_size = 4096; 6812141cc406Sopenharmony_ci *lut_entry_size = 2; 6813141cc406Sopenharmony_ci } 6814141cc406Sopenharmony_ci 6815141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_256B ) 6816141cc406Sopenharmony_ci { 6817141cc406Sopenharmony_ci *max_lut_size = 256; 6818141cc406Sopenharmony_ci *lut_entry_size = 1; 6819141cc406Sopenharmony_ci } 6820141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_1024B ) 6821141cc406Sopenharmony_ci { 6822141cc406Sopenharmony_ci *max_lut_size = 1024; 6823141cc406Sopenharmony_ci *lut_entry_size = 1; 6824141cc406Sopenharmony_ci } 6825141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_1024W ) 6826141cc406Sopenharmony_ci { 6827141cc406Sopenharmony_ci *max_lut_size = 1024; 6828141cc406Sopenharmony_ci *lut_entry_size = 2; 6829141cc406Sopenharmony_ci } 6830141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_4096B ) 6831141cc406Sopenharmony_ci { 6832141cc406Sopenharmony_ci *max_lut_size = 4096; 6833141cc406Sopenharmony_ci *lut_entry_size = 1; 6834141cc406Sopenharmony_ci } 6835141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_4096W ) 6836141cc406Sopenharmony_ci { 6837141cc406Sopenharmony_ci *max_lut_size = 4096; 6838141cc406Sopenharmony_ci *lut_entry_size = 2; 6839141cc406Sopenharmony_ci } 6840141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_64k_W ) 6841141cc406Sopenharmony_ci { 6842141cc406Sopenharmony_ci *max_lut_size = 65536; 6843141cc406Sopenharmony_ci *lut_entry_size = 2; 6844141cc406Sopenharmony_ci } 6845141cc406Sopenharmony_ci if ( mi->lut_cap & MI_LUTCAP_16k_W ) 6846141cc406Sopenharmony_ci { 6847141cc406Sopenharmony_ci *max_lut_size = 16384; 6848141cc406Sopenharmony_ci *lut_entry_size = 2; 6849141cc406Sopenharmony_ci } 6850141cc406Sopenharmony_ci DBG(30, "get_lut_size: mi=%p, lut_size=%d, lut_entry_size=%d\n", 6851141cc406Sopenharmony_ci (void *) mi, *max_lut_size, *lut_entry_size); 6852141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6853141cc406Sopenharmony_ci} 6854141cc406Sopenharmony_ci 6855141cc406Sopenharmony_ci 6856141cc406Sopenharmony_ci/*---------- calculate_gamma() -----------------------------------------------*/ 6857141cc406Sopenharmony_ci 6858141cc406Sopenharmony_cistatic SANE_Status 6859141cc406Sopenharmony_cicalculate_gamma(Microtek2_Scanner *ms, uint8_t *pos, int color, char *mode) 6860141cc406Sopenharmony_ci{ 6861141cc406Sopenharmony_ci Microtek2_Device *md; 6862141cc406Sopenharmony_ci Microtek2_Info *mi; 6863141cc406Sopenharmony_ci double exp; 6864141cc406Sopenharmony_ci double mult; 6865141cc406Sopenharmony_ci double steps; 6866141cc406Sopenharmony_ci unsigned int val; 6867141cc406Sopenharmony_ci int i; 6868141cc406Sopenharmony_ci int factor; /* take into account the differences between the */ 6869141cc406Sopenharmony_ci /* possible values for the color and the number */ 6870141cc406Sopenharmony_ci /* of bits the scanner works with internally. */ 6871141cc406Sopenharmony_ci /* If depth == 1 handle this as if the maximum */ 6872141cc406Sopenharmony_ci /* depth was chosen */ 6873141cc406Sopenharmony_ci 6874141cc406Sopenharmony_ci 6875141cc406Sopenharmony_ci DBG(30, "calculate_gamma: ms=%p, pos=%p, color=%d, mode=%s\n", 6876141cc406Sopenharmony_ci (void *) ms, (void *) pos, color, mode); 6877141cc406Sopenharmony_ci 6878141cc406Sopenharmony_ci md = ms->dev; 6879141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 6880141cc406Sopenharmony_ci 6881141cc406Sopenharmony_ci /* does this work everywhere ? */ 6882141cc406Sopenharmony_ci if ( md->model_flags & MD_NO_GAMMA ) 6883141cc406Sopenharmony_ci { 6884141cc406Sopenharmony_ci factor = 1; 6885141cc406Sopenharmony_ci mult = (double) (ms->lut_size - 1); 6886141cc406Sopenharmony_ci } 6887141cc406Sopenharmony_ci else 6888141cc406Sopenharmony_ci { 6889141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 6890141cc406Sopenharmony_ci { 6891141cc406Sopenharmony_ci factor = ms->lut_size / 65536; 6892141cc406Sopenharmony_ci mult = 65535.0; 6893141cc406Sopenharmony_ci } 6894141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_14 ) 6895141cc406Sopenharmony_ci { 6896141cc406Sopenharmony_ci factor = ms->lut_size / 16384; 6897141cc406Sopenharmony_ci mult = 16383.0; 6898141cc406Sopenharmony_ci } 6899141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_12 ) 6900141cc406Sopenharmony_ci { 6901141cc406Sopenharmony_ci factor = ms->lut_size / 4096; 6902141cc406Sopenharmony_ci mult = 4095.0; 6903141cc406Sopenharmony_ci } 6904141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_10 ) 6905141cc406Sopenharmony_ci { 6906141cc406Sopenharmony_ci factor = ms->lut_size / 1024; 6907141cc406Sopenharmony_ci mult = 1023.0; 6908141cc406Sopenharmony_ci } 6909141cc406Sopenharmony_ci else 6910141cc406Sopenharmony_ci { 6911141cc406Sopenharmony_ci factor = ms->lut_size / 256; 6912141cc406Sopenharmony_ci mult = 255.0; 6913141cc406Sopenharmony_ci } 6914141cc406Sopenharmony_ci } 6915141cc406Sopenharmony_ci 6916141cc406Sopenharmony_ci#if 0 6917141cc406Sopenharmony_ci factor = ms->lut_size / (int) pow(2.0, (double) ms->depth); 6918141cc406Sopenharmony_ci mult = pow(2.0, (double) ms->depth) - 1.0; /* depending on output size */ 6919141cc406Sopenharmony_ci#endif 6920141cc406Sopenharmony_ci 6921141cc406Sopenharmony_ci steps = (double) (ms->lut_size - 1); /* depending on input size */ 6922141cc406Sopenharmony_ci 6923141cc406Sopenharmony_ci DBG(30, "calculate_gamma: factor=%d, mult =%f, steps=%f, mode=%s\n", 6924141cc406Sopenharmony_ci factor, mult, steps, ms->val[OPT_GAMMA_MODE].s); 6925141cc406Sopenharmony_ci 6926141cc406Sopenharmony_ci 6927141cc406Sopenharmony_ci if ( strcmp(mode, MD_GAMMAMODE_SCALAR) == 0 ) 6928141cc406Sopenharmony_ci { 6929141cc406Sopenharmony_ci int option; 6930141cc406Sopenharmony_ci 6931141cc406Sopenharmony_ci option = OPT_GAMMA_SCALAR; 6932141cc406Sopenharmony_ci /* OPT_GAMMA_SCALAR_R follows OPT_GAMMA_SCALAR directly */ 6933141cc406Sopenharmony_ci if ( ms->val[OPT_GAMMA_BIND].w == SANE_TRUE ) 6934141cc406Sopenharmony_ci exp = 1.0 / SANE_UNFIX(ms->val[option].w); 6935141cc406Sopenharmony_ci else 6936141cc406Sopenharmony_ci exp = 1.0 / SANE_UNFIX(ms->val[option + color + 1].w); 6937141cc406Sopenharmony_ci 6938141cc406Sopenharmony_ci for ( i = 0; i < ms->lut_size; i++ ) 6939141cc406Sopenharmony_ci { 6940141cc406Sopenharmony_ci val = (unsigned int) (mult * pow((double) i / steps, exp) + .5); 6941141cc406Sopenharmony_ci 6942141cc406Sopenharmony_ci if ( ms->lut_entry_size == 2 ) 6943141cc406Sopenharmony_ci *((uint16_t *) pos + i) = (uint16_t) val; 6944141cc406Sopenharmony_ci else 6945141cc406Sopenharmony_ci *((uint8_t *) pos + i) = (uint8_t) val; 6946141cc406Sopenharmony_ci } 6947141cc406Sopenharmony_ci } 6948141cc406Sopenharmony_ci else if ( strcmp(mode, MD_GAMMAMODE_CUSTOM) == 0 ) 6949141cc406Sopenharmony_ci { 6950141cc406Sopenharmony_ci int option; 6951141cc406Sopenharmony_ci SANE_Int *src; 6952141cc406Sopenharmony_ci 6953141cc406Sopenharmony_ci option = OPT_GAMMA_CUSTOM; 6954141cc406Sopenharmony_ci if ( ms->val[OPT_GAMMA_BIND].w == SANE_TRUE ) 6955141cc406Sopenharmony_ci src = ms->val[option].wa; 6956141cc406Sopenharmony_ci else 6957141cc406Sopenharmony_ci src = ms->val[option + color + 1].wa; 6958141cc406Sopenharmony_ci 6959141cc406Sopenharmony_ci for ( i = 0; i < ms->lut_size; i++ ) 6960141cc406Sopenharmony_ci { 6961141cc406Sopenharmony_ci if ( ms->lut_entry_size == 2 ) 6962141cc406Sopenharmony_ci *((uint16_t *) pos + i) = (uint16_t) (src[i] / factor); 6963141cc406Sopenharmony_ci else 6964141cc406Sopenharmony_ci *((uint8_t *) pos + i) = (uint8_t) (src[i] / factor); 6965141cc406Sopenharmony_ci } 6966141cc406Sopenharmony_ci } 6967141cc406Sopenharmony_ci else if ( strcmp(mode, MD_GAMMAMODE_LINEAR) == 0 ) 6968141cc406Sopenharmony_ci { 6969141cc406Sopenharmony_ci for ( i = 0; i < ms->lut_size; i++ ) 6970141cc406Sopenharmony_ci { 6971141cc406Sopenharmony_ci if ( ms->lut_entry_size == 2 ) 6972141cc406Sopenharmony_ci *((uint16_t *) pos + i) = (uint16_t) (i / factor); 6973141cc406Sopenharmony_ci else 6974141cc406Sopenharmony_ci *((uint8_t *) pos + i) = (uint8_t) (i / factor); 6975141cc406Sopenharmony_ci } 6976141cc406Sopenharmony_ci } 6977141cc406Sopenharmony_ci 6978141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 6979141cc406Sopenharmony_ci} 6980141cc406Sopenharmony_ci 6981141cc406Sopenharmony_ci 6982141cc406Sopenharmony_ci/*---------- shading_function() ----------------------------------------------*/ 6983141cc406Sopenharmony_ci 6984141cc406Sopenharmony_cistatic SANE_Status 6985141cc406Sopenharmony_cishading_function(Microtek2_Scanner *ms, uint8_t *data) 6986141cc406Sopenharmony_ci{ 6987141cc406Sopenharmony_ci Microtek2_Device *md; 6988141cc406Sopenharmony_ci Microtek2_Info *mi; 6989141cc406Sopenharmony_ci uint32_t value; 6990141cc406Sopenharmony_ci int color; 6991141cc406Sopenharmony_ci int i; 6992141cc406Sopenharmony_ci 6993141cc406Sopenharmony_ci 6994141cc406Sopenharmony_ci DBG(40, "shading_function: ms=%p, data=%p\n", (void *) ms, (void *) data); 6995141cc406Sopenharmony_ci 6996141cc406Sopenharmony_ci md = ms->dev; 6997141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 6998141cc406Sopenharmony_ci/* mi = &md->info[MD_SOURCE_FLATBED]; */ 6999141cc406Sopenharmony_ci 7000141cc406Sopenharmony_ci if ( ms->lut_entry_size == 1 ) 7001141cc406Sopenharmony_ci { 7002141cc406Sopenharmony_ci DBG(1, "shading_function: wordsize = 1 unsupported\n"); 7003141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7004141cc406Sopenharmony_ci } 7005141cc406Sopenharmony_ci 7006141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7007141cc406Sopenharmony_ci { 7008141cc406Sopenharmony_ci for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++) 7009141cc406Sopenharmony_ci { 7010141cc406Sopenharmony_ci value = *((uint16_t *) data 7011141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i); 7012141cc406Sopenharmony_ci switch ( mi->shtrnsferequ ) 7013141cc406Sopenharmony_ci { 7014141cc406Sopenharmony_ci case 0x00: 7015141cc406Sopenharmony_ci /* output == input */ 7016141cc406Sopenharmony_ci break; 7017141cc406Sopenharmony_ci 7018141cc406Sopenharmony_ci case 0x01: 7019141cc406Sopenharmony_ci value = (ms->lut_size * ms->lut_size) / value; 7020141cc406Sopenharmony_ci *((uint16_t *) data 7021141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = 7022141cc406Sopenharmony_ci (uint16_t) MIN(0xffff, value); 7023141cc406Sopenharmony_ci break; 7024141cc406Sopenharmony_ci 7025141cc406Sopenharmony_ci case 0x11: 7026141cc406Sopenharmony_ci value = (ms->lut_size * ms->lut_size) 7027141cc406Sopenharmony_ci / (uint32_t) ( (double) value 7028141cc406Sopenharmony_ci * ((double) mi->balance[color] 7029141cc406Sopenharmony_ci / 255.0)); 7030141cc406Sopenharmony_ci *((uint16_t *) data 7031141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = 7032141cc406Sopenharmony_ci (uint16_t) MIN(0xffff, value); 7033141cc406Sopenharmony_ci break; 7034141cc406Sopenharmony_ci case 0x15: 7035141cc406Sopenharmony_ci value = (uint32_t) ( ( 1073741824 / (double) value ) 7036141cc406Sopenharmony_ci * ( (double) mi->balance[color] 7037141cc406Sopenharmony_ci / 256.0) ); 7038141cc406Sopenharmony_ci value = MIN(value, (uint32_t)65535); 7039141cc406Sopenharmony_ci *((uint16_t *) data 7040141cc406Sopenharmony_ci + color * ( mi->geo_width / mi->calib_divisor ) + i) = 7041141cc406Sopenharmony_ci (uint16_t) MIN(0xffff, value); 7042141cc406Sopenharmony_ci break; 7043141cc406Sopenharmony_ci 7044141cc406Sopenharmony_ci default: 7045141cc406Sopenharmony_ci DBG(1, "Unsupported shading transfer function 0x%02x\n", 7046141cc406Sopenharmony_ci mi->shtrnsferequ ); 7047141cc406Sopenharmony_ci break; 7048141cc406Sopenharmony_ci } 7049141cc406Sopenharmony_ci } 7050141cc406Sopenharmony_ci } 7051141cc406Sopenharmony_ci 7052141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7053141cc406Sopenharmony_ci} 7054141cc406Sopenharmony_ci 7055141cc406Sopenharmony_ci 7056141cc406Sopenharmony_ci/*---------- set_exposure() --------------------------------------------------*/ 7057141cc406Sopenharmony_ci 7058141cc406Sopenharmony_cistatic void 7059141cc406Sopenharmony_ciset_exposure(Microtek2_Scanner *ms) 7060141cc406Sopenharmony_ci{ 7061141cc406Sopenharmony_ci /* This function manipulates the colors according to the exposure time */ 7062141cc406Sopenharmony_ci /* settings on models where they are ignored. Currently this seems to */ 7063141cc406Sopenharmony_ci /* be the case for all models with the data format chunky data. They */ 7064141cc406Sopenharmony_ci /* all have tables with two byte gamma output, so for now we ignore */ 7065141cc406Sopenharmony_ci /* gamma tables with one byte output */ 7066141cc406Sopenharmony_ci 7067141cc406Sopenharmony_ci Microtek2_Device *md; 7068141cc406Sopenharmony_ci Microtek2_Info *mi; 7069141cc406Sopenharmony_ci int color; 7070141cc406Sopenharmony_ci int size; 7071141cc406Sopenharmony_ci int depth; 7072141cc406Sopenharmony_ci int maxval; 7073141cc406Sopenharmony_ci int byte; 7074141cc406Sopenharmony_ci uint32_t val32; 7075141cc406Sopenharmony_ci uint8_t *from; 7076141cc406Sopenharmony_ci uint8_t exposure; 7077141cc406Sopenharmony_ci uint8_t exposure_rgb[3]; 7078141cc406Sopenharmony_ci 7079141cc406Sopenharmony_ci 7080141cc406Sopenharmony_ci DBG(30, "set_exposure: ms=%p\n", (void *) ms); 7081141cc406Sopenharmony_ci 7082141cc406Sopenharmony_ci md = ms->dev; 7083141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 7084141cc406Sopenharmony_ci 7085141cc406Sopenharmony_ci if ( ms->lut_entry_size == 1 ) 7086141cc406Sopenharmony_ci { 7087141cc406Sopenharmony_ci DBG(1, "set_exposure: 1 byte gamma output tables currently ignored\n"); 7088141cc406Sopenharmony_ci return; 7089141cc406Sopenharmony_ci } 7090141cc406Sopenharmony_ci 7091141cc406Sopenharmony_ci if ( mi->depth & MI_HASDEPTH_16 ) 7092141cc406Sopenharmony_ci depth = 16; 7093141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_14 ) 7094141cc406Sopenharmony_ci depth = 14; 7095141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_12 ) 7096141cc406Sopenharmony_ci depth = 12; 7097141cc406Sopenharmony_ci else if ( mi->depth & MI_HASDEPTH_10 ) 7098141cc406Sopenharmony_ci depth = 10; 7099141cc406Sopenharmony_ci else 7100141cc406Sopenharmony_ci depth = 8; 7101141cc406Sopenharmony_ci 7102141cc406Sopenharmony_ci maxval = ( 1 << depth ) - 1; 7103141cc406Sopenharmony_ci 7104141cc406Sopenharmony_ci from = ms->gamma_table; 7105141cc406Sopenharmony_ci size = ms->lut_size; 7106141cc406Sopenharmony_ci 7107141cc406Sopenharmony_ci /* first master channel, apply transformation to all colors */ 7108141cc406Sopenharmony_ci exposure = ms->exposure_m; 7109141cc406Sopenharmony_ci for ( byte = 0; byte < ms->lut_size; byte++ ) 7110141cc406Sopenharmony_ci { 7111141cc406Sopenharmony_ci for ( color = 0; color < 3; color++) 7112141cc406Sopenharmony_ci { 7113141cc406Sopenharmony_ci val32 = (uint32_t) *((uint16_t *) from + color * size + byte); 7114141cc406Sopenharmony_ci val32 = MIN(val32 + val32 7115141cc406Sopenharmony_ci * (2 * (uint32_t) exposure / 100), (uint32_t) maxval); 7116141cc406Sopenharmony_ci *((uint16_t *) from + color * size + byte) = (uint16_t) val32; 7117141cc406Sopenharmony_ci } 7118141cc406Sopenharmony_ci } 7119141cc406Sopenharmony_ci 7120141cc406Sopenharmony_ci /* and now apply transformation to each channel */ 7121141cc406Sopenharmony_ci 7122141cc406Sopenharmony_ci exposure_rgb[0] = ms->exposure_r; 7123141cc406Sopenharmony_ci exposure_rgb[1] = ms->exposure_g; 7124141cc406Sopenharmony_ci exposure_rgb[2] = ms->exposure_b; 7125141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7126141cc406Sopenharmony_ci { 7127141cc406Sopenharmony_ci for ( byte = 0; byte < size; byte++ ) 7128141cc406Sopenharmony_ci { 7129141cc406Sopenharmony_ci val32 = (uint32_t) *((uint16_t *) from + color * size + byte); 7130141cc406Sopenharmony_ci val32 = MIN(val32 + val32 7131141cc406Sopenharmony_ci * (2 * (uint32_t) exposure_rgb[color] / 100), 7132141cc406Sopenharmony_ci (uint32_t) maxval); 7133141cc406Sopenharmony_ci *((uint16_t *) from + color * size + byte) = (uint16_t) val32; 7134141cc406Sopenharmony_ci } 7135141cc406Sopenharmony_ci } 7136141cc406Sopenharmony_ci 7137141cc406Sopenharmony_ci return; 7138141cc406Sopenharmony_ci} 7139141cc406Sopenharmony_ci 7140141cc406Sopenharmony_ci 7141141cc406Sopenharmony_ci/*---------- reader_process() ------------------------------------------------*/ 7142141cc406Sopenharmony_ci 7143141cc406Sopenharmony_cistatic int 7144141cc406Sopenharmony_cireader_process(void *data) 7145141cc406Sopenharmony_ci{ 7146141cc406Sopenharmony_ci Microtek2_Scanner *ms = (Microtek2_Scanner *) data; 7147141cc406Sopenharmony_ci 7148141cc406Sopenharmony_ci SANE_Status status; 7149141cc406Sopenharmony_ci Microtek2_Info *mi; 7150141cc406Sopenharmony_ci Microtek2_Device *md; 7151141cc406Sopenharmony_ci struct SIGACTION act; 7152141cc406Sopenharmony_ci sigset_t sigterm_set; 7153141cc406Sopenharmony_ci static uint8_t *temp_current = NULL; 7154141cc406Sopenharmony_ci 7155141cc406Sopenharmony_ci DBG(30, "reader_process: ms=%p\n", (void *) ms); 7156141cc406Sopenharmony_ci 7157141cc406Sopenharmony_ci md = ms->dev; 7158141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 7159141cc406Sopenharmony_ci 7160141cc406Sopenharmony_ci if (sanei_thread_is_forked()) close(ms->fd[0]); 7161141cc406Sopenharmony_ci 7162141cc406Sopenharmony_ci sigemptyset (&sigterm_set); 7163141cc406Sopenharmony_ci sigaddset (&sigterm_set, SIGTERM); 7164141cc406Sopenharmony_ci memset (&act, 0, sizeof (act)); 7165141cc406Sopenharmony_ci act.sa_handler = signal_handler; 7166141cc406Sopenharmony_ci sigaction (SIGTERM, &act, 0); 7167141cc406Sopenharmony_ci 7168141cc406Sopenharmony_ci ms->fp = fdopen(ms->fd[1], "w"); 7169141cc406Sopenharmony_ci if ( ms->fp == NULL ) 7170141cc406Sopenharmony_ci { 7171141cc406Sopenharmony_ci DBG(1, "reader_process: fdopen() failed, errno=%d\n", errno); 7172141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7173141cc406Sopenharmony_ci } 7174141cc406Sopenharmony_ci 7175141cc406Sopenharmony_ci if ( ms->auto_adjust == 1 ) 7176141cc406Sopenharmony_ci { 7177141cc406Sopenharmony_ci if ( temp_current == NULL ) 7178141cc406Sopenharmony_ci temp_current = ms->temporary_buffer; 7179141cc406Sopenharmony_ci } 7180141cc406Sopenharmony_ci 7181141cc406Sopenharmony_ci while ( ms->src_remaining_lines > 0 ) 7182141cc406Sopenharmony_ci { 7183141cc406Sopenharmony_ci 7184141cc406Sopenharmony_ci ms->src_lines_to_read = MIN(ms->src_remaining_lines, ms->src_max_lines); 7185141cc406Sopenharmony_ci ms->transfer_length = ms->src_lines_to_read * ms->bpl; 7186141cc406Sopenharmony_ci 7187141cc406Sopenharmony_ci DBG(30, "reader_process: transferlength=%d, lines=%d, linelength=%d, " 7188141cc406Sopenharmony_ci "real_bpl=%d, srcbuf=%p\n", 7189141cc406Sopenharmony_ci ms->transfer_length, ms->src_lines_to_read, ms->bpl, 7190141cc406Sopenharmony_ci ms->real_bpl, (void *) ms->buf.src_buf); 7191141cc406Sopenharmony_ci 7192141cc406Sopenharmony_ci sigprocmask (SIG_BLOCK, &sigterm_set, 0); 7193141cc406Sopenharmony_ci status = scsi_read_image(ms, ms->buf.src_buf, (ms->depth > 8) ? 2 : 1); 7194141cc406Sopenharmony_ci sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); 7195141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7196141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7197141cc406Sopenharmony_ci 7198141cc406Sopenharmony_ci ms->src_remaining_lines -= ms->src_lines_to_read; 7199141cc406Sopenharmony_ci 7200141cc406Sopenharmony_ci /* prepare data for frontend */ 7201141cc406Sopenharmony_ci switch (ms->mode) 7202141cc406Sopenharmony_ci { 7203141cc406Sopenharmony_ci case MS_MODE_COLOR: 7204141cc406Sopenharmony_ci if ( ! mi->onepass ) 7205141cc406Sopenharmony_ci /* TODO */ 7206141cc406Sopenharmony_ci { 7207141cc406Sopenharmony_ci DBG(1, "reader_process: 3 pass not yet supported\n"); 7208141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7209141cc406Sopenharmony_ci } 7210141cc406Sopenharmony_ci else 7211141cc406Sopenharmony_ci { 7212141cc406Sopenharmony_ci switch ( mi->data_format ) 7213141cc406Sopenharmony_ci { 7214141cc406Sopenharmony_ci case MI_DATAFMT_CHUNKY: 7215141cc406Sopenharmony_ci case MI_DATAFMT_9800: 7216141cc406Sopenharmony_ci status = chunky_proc_data(ms); 7217141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7218141cc406Sopenharmony_ci return status; 7219141cc406Sopenharmony_ci break; 7220141cc406Sopenharmony_ci case MI_DATAFMT_LPLCONCAT: 7221141cc406Sopenharmony_ci status = lplconcat_proc_data(ms); 7222141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7223141cc406Sopenharmony_ci return status; 7224141cc406Sopenharmony_ci break; 7225141cc406Sopenharmony_ci case MI_DATAFMT_LPLSEGREG: 7226141cc406Sopenharmony_ci status = segreg_proc_data(ms); 7227141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7228141cc406Sopenharmony_ci return status; 7229141cc406Sopenharmony_ci break; 7230141cc406Sopenharmony_ci case MI_DATAFMT_WORDCHUNKY: 7231141cc406Sopenharmony_ci status = wordchunky_proc_data(ms); 7232141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7233141cc406Sopenharmony_ci return status; 7234141cc406Sopenharmony_ci break; 7235141cc406Sopenharmony_ci default: 7236141cc406Sopenharmony_ci DBG(1, "reader_process: format %d\n", mi->data_format); 7237141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7238141cc406Sopenharmony_ci } 7239141cc406Sopenharmony_ci } 7240141cc406Sopenharmony_ci break; 7241141cc406Sopenharmony_ci case MS_MODE_GRAY: 7242141cc406Sopenharmony_ci status = gray_proc_data(ms); 7243141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7244141cc406Sopenharmony_ci return status; 7245141cc406Sopenharmony_ci break; 7246141cc406Sopenharmony_ci case MS_MODE_HALFTONE: 7247141cc406Sopenharmony_ci case MS_MODE_LINEART: 7248141cc406Sopenharmony_ci status = proc_onebit_data(ms); 7249141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7250141cc406Sopenharmony_ci return status; 7251141cc406Sopenharmony_ci break; 7252141cc406Sopenharmony_ci case MS_MODE_LINEARTFAKE: 7253141cc406Sopenharmony_ci if ( ms->auto_adjust == 1 ) 7254141cc406Sopenharmony_ci status = auto_adjust_proc_data(ms, &temp_current); 7255141cc406Sopenharmony_ci else 7256141cc406Sopenharmony_ci status = lineartfake_proc_data(ms); 7257141cc406Sopenharmony_ci 7258141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7259141cc406Sopenharmony_ci return status; 7260141cc406Sopenharmony_ci break; 7261141cc406Sopenharmony_ci default: 7262141cc406Sopenharmony_ci DBG(1, "reader_process: Unknown scan mode %d\n", ms->mode); 7263141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7264141cc406Sopenharmony_ci } 7265141cc406Sopenharmony_ci } 7266141cc406Sopenharmony_ci 7267141cc406Sopenharmony_ci fclose(ms->fp); 7268141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7269141cc406Sopenharmony_ci} 7270141cc406Sopenharmony_ci 7271141cc406Sopenharmony_ci/*---------- chunky_proc_data() ----------------------------------------------*/ 7272141cc406Sopenharmony_ci 7273141cc406Sopenharmony_cistatic SANE_Status 7274141cc406Sopenharmony_cichunky_proc_data(Microtek2_Scanner *ms) 7275141cc406Sopenharmony_ci{ 7276141cc406Sopenharmony_ci SANE_Status status; 7277141cc406Sopenharmony_ci Microtek2_Device *md; 7278141cc406Sopenharmony_ci uint32_t line; 7279141cc406Sopenharmony_ci uint8_t *from; 7280141cc406Sopenharmony_ci int pad; 7281141cc406Sopenharmony_ci int bpp; /* bytes per pixel */ 7282141cc406Sopenharmony_ci int bits_pp_in; /* bits per pixel input */ 7283141cc406Sopenharmony_ci int bits_pp_out; /* bits per pixel output */ 7284141cc406Sopenharmony_ci int bpl_ppl_diff; 7285141cc406Sopenharmony_ci 7286141cc406Sopenharmony_ci 7287141cc406Sopenharmony_ci DBG(30, "chunky_proc_data: ms=%p\n", (void *) ms); 7288141cc406Sopenharmony_ci 7289141cc406Sopenharmony_ci md = ms->dev; 7290141cc406Sopenharmony_ci bits_pp_in = ms->bits_per_pixel_in; 7291141cc406Sopenharmony_ci bits_pp_out = ms->bits_per_pixel_out; 7292141cc406Sopenharmony_ci pad = (int) ceil( (double) (ms->ppl * bits_pp_in) / 8.0 ) % 2; 7293141cc406Sopenharmony_ci bpp = bits_pp_out / 8; 7294141cc406Sopenharmony_ci 7295141cc406Sopenharmony_ci /* Some models have 3 * ppl + 6 bytes per line if the number of pixels */ 7296141cc406Sopenharmony_ci /* per line is even and 3 * ppl + 3 bytes per line if the number of */ 7297141cc406Sopenharmony_ci /* pixels per line is odd. According to the documentation it should be */ 7298141cc406Sopenharmony_ci /* bpl = 3*ppl (even number of pixels) or bpl=3*ppl+1 (odd number of */ 7299141cc406Sopenharmony_ci /* pixels. Even worse: On different models it is different at which */ 7300141cc406Sopenharmony_ci /* position in a scanline the image data starts. bpl_ppl_diff tries */ 7301141cc406Sopenharmony_ci /* to fix this. */ 7302141cc406Sopenharmony_ci 7303141cc406Sopenharmony_ci if ( (md->model_flags & MD_OFFSET_2) && pad == 1 ) 7304141cc406Sopenharmony_ci bpl_ppl_diff = 2; 7305141cc406Sopenharmony_ci else 7306141cc406Sopenharmony_ci bpl_ppl_diff = 0; 7307141cc406Sopenharmony_ci 7308141cc406Sopenharmony_ci#if 0 7309141cc406Sopenharmony_ci if ( md->revision == 1.00 && mi->model_code != 0x81 ) 7310141cc406Sopenharmony_ci bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ) - pad; 7311141cc406Sopenharmony_ci else 7312141cc406Sopenharmony_ci bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ); 7313141cc406Sopenharmony_ci 7314141cc406Sopenharmony_ci if ( md->revision > 1.00 ) 7315141cc406Sopenharmony_ci bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ); 7316141cc406Sopenharmony_ci else 7317141cc406Sopenharmony_ci bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ) - pad; 7318141cc406Sopenharmony_ci#endif 7319141cc406Sopenharmony_ci 7320141cc406Sopenharmony_ci from = ms->buf.src_buf; 7321141cc406Sopenharmony_ci from += bpl_ppl_diff; 7322141cc406Sopenharmony_ci 7323141cc406Sopenharmony_ci DBG(30, "chunky_proc_data: lines=%d, bpl=%d, ppl=%d, bpp=%d, depth=%d" 7324141cc406Sopenharmony_ci " junk=%d\n", ms->src_lines_to_read, ms->bpl, ms->ppl, 7325141cc406Sopenharmony_ci bpp, ms->depth, bpl_ppl_diff); 7326141cc406Sopenharmony_ci 7327141cc406Sopenharmony_ci for ( line = 0; line < (uint32_t) ms->src_lines_to_read; line++ ) 7328141cc406Sopenharmony_ci { 7329141cc406Sopenharmony_ci status = chunky_copy_pixels(ms, from); 7330141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7331141cc406Sopenharmony_ci return status; 7332141cc406Sopenharmony_ci from += ms->bpl; 7333141cc406Sopenharmony_ci } 7334141cc406Sopenharmony_ci 7335141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7336141cc406Sopenharmony_ci} 7337141cc406Sopenharmony_ci 7338141cc406Sopenharmony_ci/*---------- chunky_copy_pixels() --------------------------------------------*/ 7339141cc406Sopenharmony_ci 7340141cc406Sopenharmony_cistatic SANE_Status 7341141cc406Sopenharmony_cichunky_copy_pixels(Microtek2_Scanner *ms, uint8_t *from) 7342141cc406Sopenharmony_ci{ 7343141cc406Sopenharmony_ci Microtek2_Device *md; 7344141cc406Sopenharmony_ci uint32_t pixel; 7345141cc406Sopenharmony_ci int color; 7346141cc406Sopenharmony_ci 7347141cc406Sopenharmony_ci DBG(30, "chunky_copy_pixels: from=%p, pixels=%d, fp=%p, depth=%d\n", 7348141cc406Sopenharmony_ci (void *) from, ms->ppl, (void *) ms->fp, ms->depth); 7349141cc406Sopenharmony_ci 7350141cc406Sopenharmony_ci md = ms->dev; 7351141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7352141cc406Sopenharmony_ci { 7353141cc406Sopenharmony_ci if ( !( md->model_flags & MD_16BIT_TRANSFER ) ) 7354141cc406Sopenharmony_ci { 7355141cc406Sopenharmony_ci int scale1; 7356141cc406Sopenharmony_ci int scale2; 7357141cc406Sopenharmony_ci uint16_t val16; 7358141cc406Sopenharmony_ci 7359141cc406Sopenharmony_ci scale1 = 16 - ms->depth; 7360141cc406Sopenharmony_ci scale2 = 2 * ms->depth - 16; 7361141cc406Sopenharmony_ci for ( pixel = 0; pixel < ms->ppl; pixel++ ) 7362141cc406Sopenharmony_ci { 7363141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7364141cc406Sopenharmony_ci { 7365141cc406Sopenharmony_ci val16 = *( (uint16_t *) from + 3 * pixel + color ); 7366141cc406Sopenharmony_ci val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); 7367141cc406Sopenharmony_ci fwrite((void *) &val16, 2, 1, ms->fp); 7368141cc406Sopenharmony_ci } 7369141cc406Sopenharmony_ci } 7370141cc406Sopenharmony_ci } 7371141cc406Sopenharmony_ci else 7372141cc406Sopenharmony_ci { 7373141cc406Sopenharmony_ci fwrite((void *) from, 2, 3 * ms->ppl, ms->fp); 7374141cc406Sopenharmony_ci } 7375141cc406Sopenharmony_ci } 7376141cc406Sopenharmony_ci else if ( ms->depth == 8 ) 7377141cc406Sopenharmony_ci { 7378141cc406Sopenharmony_ci fwrite((void *) from, 1, 3 * ms->ppl, ms->fp); 7379141cc406Sopenharmony_ci } 7380141cc406Sopenharmony_ci else 7381141cc406Sopenharmony_ci { 7382141cc406Sopenharmony_ci DBG(1, "chunky_copy_pixels: Unknown depth %d\n", ms->depth); 7383141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7384141cc406Sopenharmony_ci } 7385141cc406Sopenharmony_ci 7386141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7387141cc406Sopenharmony_ci} 7388141cc406Sopenharmony_ci 7389141cc406Sopenharmony_ci/*---------- segreg_proc_data() ----------------------------------------------*/ 7390141cc406Sopenharmony_ci 7391141cc406Sopenharmony_cistatic SANE_Status 7392141cc406Sopenharmony_cisegreg_proc_data(Microtek2_Scanner *ms) 7393141cc406Sopenharmony_ci{ 7394141cc406Sopenharmony_ci SANE_Status status; 7395141cc406Sopenharmony_ci Microtek2_Device *md; 7396141cc406Sopenharmony_ci Microtek2_Info *mi; 7397141cc406Sopenharmony_ci char colormap[] = "RGB"; 7398141cc406Sopenharmony_ci uint8_t *from; 7399141cc406Sopenharmony_ci uint32_t lines_to_deliver; 7400141cc406Sopenharmony_ci int bpp; /* bytes per pixel */ 7401141cc406Sopenharmony_ci int bpf; /* bytes per frame including color indicator */ 7402141cc406Sopenharmony_ci int pad; 7403141cc406Sopenharmony_ci int colseq2; 7404141cc406Sopenharmony_ci int color; 7405141cc406Sopenharmony_ci int save_current_src; 7406141cc406Sopenharmony_ci int frame; 7407141cc406Sopenharmony_ci 7408141cc406Sopenharmony_ci DBG(30, "segreg_proc_data: ms=%p\n", (void *) ms); 7409141cc406Sopenharmony_ci 7410141cc406Sopenharmony_ci md = ms->dev; 7411141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 7412141cc406Sopenharmony_ci /* take a trailing junk byte into account */ 7413141cc406Sopenharmony_ci pad = (int) ceil( (double) (ms->ppl * ms->bits_per_pixel_in) / 8.0 ) % 2; 7414141cc406Sopenharmony_ci bpp = ms->bits_per_pixel_out / 8; /* bits_per_pixel_out is either 8 or 16 */ 7415141cc406Sopenharmony_ci bpf = ms->bpl / 3; 7416141cc406Sopenharmony_ci 7417141cc406Sopenharmony_ci DBG(30, "segreg_proc_data: lines=%d, bpl=%d, ppl=%d, bpf=%d, bpp=%d,\n" 7418141cc406Sopenharmony_ci "depth=%d, pad=%d, freelines=%d, calib_backend=%d\n", 7419141cc406Sopenharmony_ci ms->src_lines_to_read, ms->bpl, ms->ppl, bpf, bpp, 7420141cc406Sopenharmony_ci ms->depth, pad, ms->buf.free_lines, ms->calib_backend); 7421141cc406Sopenharmony_ci 7422141cc406Sopenharmony_ci /* determine how many planes of each color are in the source buffer */ 7423141cc406Sopenharmony_ci from = ms->buf.src_buf; 7424141cc406Sopenharmony_ci for ( frame = 0; frame < 3 * ms->src_lines_to_read; frame++, from += bpf ) 7425141cc406Sopenharmony_ci { 7426141cc406Sopenharmony_ci switch ( *from ) 7427141cc406Sopenharmony_ci { 7428141cc406Sopenharmony_ci case 'R': 7429141cc406Sopenharmony_ci ++ms->buf.planes[0][MS_COLOR_RED]; 7430141cc406Sopenharmony_ci break; 7431141cc406Sopenharmony_ci case 'G': 7432141cc406Sopenharmony_ci ++ms->buf.planes[0][MS_COLOR_GREEN]; 7433141cc406Sopenharmony_ci break; 7434141cc406Sopenharmony_ci case 'B': 7435141cc406Sopenharmony_ci ++ms->buf.planes[0][MS_COLOR_BLUE]; 7436141cc406Sopenharmony_ci break; 7437141cc406Sopenharmony_ci default: 7438141cc406Sopenharmony_ci DBG(1, "segreg_proc_data: unknown color indicator (1) " 7439141cc406Sopenharmony_ci "0x%02x\n", *from); 7440141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7441141cc406Sopenharmony_ci } 7442141cc406Sopenharmony_ci } 7443141cc406Sopenharmony_ci 7444141cc406Sopenharmony_ci ms->buf.free_lines -= ms->src_lines_to_read; 7445141cc406Sopenharmony_ci save_current_src = ms->buf.current_src; 7446141cc406Sopenharmony_ci if ( ms->buf.free_lines < ms->src_max_lines ) 7447141cc406Sopenharmony_ci { 7448141cc406Sopenharmony_ci ms->buf.current_src = !ms->buf.current_src; 7449141cc406Sopenharmony_ci ms->buf.src_buf = ms->buf.src_buffer[ms->buf.current_src]; 7450141cc406Sopenharmony_ci ms->buf.free_lines = ms->buf.free_max_lines; 7451141cc406Sopenharmony_ci } 7452141cc406Sopenharmony_ci else 7453141cc406Sopenharmony_ci ms->buf.src_buf += ms->src_lines_to_read * ms->bpl; 7454141cc406Sopenharmony_ci 7455141cc406Sopenharmony_ci colseq2 = mi->color_sequence[2]; 7456141cc406Sopenharmony_ci lines_to_deliver = ms->buf.planes[0][colseq2] + ms->buf.planes[1][colseq2]; 7457141cc406Sopenharmony_ci if ( lines_to_deliver == 0 ) 7458141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7459141cc406Sopenharmony_ci 7460141cc406Sopenharmony_ci DBG(30, "segreg_proc_data: planes[0][0]=%d, planes[0][1]=%d, " 7461141cc406Sopenharmony_ci "planes[0][2]=%d\n", ms->buf.planes[0][0], ms->buf.planes[0][1], 7462141cc406Sopenharmony_ci ms->buf.planes[0][2] ); 7463141cc406Sopenharmony_ci DBG(30, "segreg_proc_data: planes[1][0]=%d, planes[1][1]=%d, " 7464141cc406Sopenharmony_ci "planes[1][2]=%d\n", ms->buf.planes[1][0], ms->buf.planes[1][1], 7465141cc406Sopenharmony_ci ms->buf.planes[1][2] ); 7466141cc406Sopenharmony_ci 7467141cc406Sopenharmony_ci while ( lines_to_deliver > 0 ) 7468141cc406Sopenharmony_ci { 7469141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7470141cc406Sopenharmony_ci { 7471141cc406Sopenharmony_ci /* get the position of the next plane for each color */ 7472141cc406Sopenharmony_ci do 7473141cc406Sopenharmony_ci { 7474141cc406Sopenharmony_ci if ( *ms->buf.current_pos[color] == colormap[color] ) 7475141cc406Sopenharmony_ci break; 7476141cc406Sopenharmony_ci ms->buf.current_pos[color] += bpf; 7477141cc406Sopenharmony_ci } while ( 1 ); 7478141cc406Sopenharmony_ci 7479141cc406Sopenharmony_ci ms->buf.current_pos[color] += 2; /* skip color indicator */ 7480141cc406Sopenharmony_ci } 7481141cc406Sopenharmony_ci 7482141cc406Sopenharmony_ci status = segreg_copy_pixels(ms); 7483141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7484141cc406Sopenharmony_ci { 7485141cc406Sopenharmony_ci DBG(1, "segreg_copy_pixels:status %d\n", status); 7486141cc406Sopenharmony_ci return status; 7487141cc406Sopenharmony_ci } 7488141cc406Sopenharmony_ci 7489141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7490141cc406Sopenharmony_ci { 7491141cc406Sopenharmony_ci /* skip a padding byte at the end, if present */ 7492141cc406Sopenharmony_ci ms->buf.current_pos[color] += pad; 7493141cc406Sopenharmony_ci 7494141cc406Sopenharmony_ci if ( ms->buf.planes[1][color] > 0 ) 7495141cc406Sopenharmony_ci { 7496141cc406Sopenharmony_ci --ms->buf.planes[1][color]; 7497141cc406Sopenharmony_ci if ( ms->buf.planes[1][color] == 0 ) 7498141cc406Sopenharmony_ci /* we have copied from the prehold buffer and are */ 7499141cc406Sopenharmony_ci /* done now, we continue with the source buffer */ 7500141cc406Sopenharmony_ci ms->buf.current_pos[color] = 7501141cc406Sopenharmony_ci ms->buf.src_buffer[save_current_src]; 7502141cc406Sopenharmony_ci } 7503141cc406Sopenharmony_ci else 7504141cc406Sopenharmony_ci { 7505141cc406Sopenharmony_ci --ms->buf.planes[0][color]; 7506141cc406Sopenharmony_ci if ( ms->buf.planes[0][color] == 0 7507141cc406Sopenharmony_ci && ms->buf.current_src != save_current_src ) 7508141cc406Sopenharmony_ci 7509141cc406Sopenharmony_ci ms->buf.current_pos[color] = 7510141cc406Sopenharmony_ci ms->buf.src_buffer[ms->buf.current_src]; 7511141cc406Sopenharmony_ci } 7512141cc406Sopenharmony_ci } 7513141cc406Sopenharmony_ci DBG(100, "planes_to_deliver=%d\n", lines_to_deliver); 7514141cc406Sopenharmony_ci --lines_to_deliver; 7515141cc406Sopenharmony_ci } 7516141cc406Sopenharmony_ci 7517141cc406Sopenharmony_ci if ( ms->buf.current_src != save_current_src ) 7518141cc406Sopenharmony_ci { 7519141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7520141cc406Sopenharmony_ci { 7521141cc406Sopenharmony_ci ms->buf.planes[1][color] += ms->buf.planes[0][color]; 7522141cc406Sopenharmony_ci ms->buf.planes[0][color] = 0; 7523141cc406Sopenharmony_ci } 7524141cc406Sopenharmony_ci } 7525141cc406Sopenharmony_ci 7526141cc406Sopenharmony_ci DBG(30, "segreg_proc_data: src_buf=%p, free_lines=%d\n", 7527141cc406Sopenharmony_ci (void *) ms->buf.src_buf, ms->buf.free_lines); 7528141cc406Sopenharmony_ci 7529141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7530141cc406Sopenharmony_ci} 7531141cc406Sopenharmony_ci 7532141cc406Sopenharmony_ci/*---------- segreg_copy_pixels() --------------------------------------------*/ 7533141cc406Sopenharmony_ci 7534141cc406Sopenharmony_cistatic SANE_Status 7535141cc406Sopenharmony_cisegreg_copy_pixels(Microtek2_Scanner *ms) 7536141cc406Sopenharmony_ci{ 7537141cc406Sopenharmony_ci Microtek2_Device *md; 7538141cc406Sopenharmony_ci Microtek2_Info *mi; 7539141cc406Sopenharmony_ci uint32_t pixel; 7540141cc406Sopenharmony_ci int color, i, gamma_by_backend, right_to_left, scale1, scale2, bpp_in; 7541141cc406Sopenharmony_ci float s_w, s_d; /* shading byte from condensed_shading */ 7542141cc406Sopenharmony_ci float val, maxval = 0, shading_factor = 0; 7543141cc406Sopenharmony_ci uint16_t val16 = 0; 7544141cc406Sopenharmony_ci uint8_t val8 = 0; 7545141cc406Sopenharmony_ci uint8_t *from_effective; 7546141cc406Sopenharmony_ci uint8_t *gamma[3]; 7547141cc406Sopenharmony_ci float f[3]; /* color balance factor */ 7548141cc406Sopenharmony_ci 7549141cc406Sopenharmony_ci md = ms->dev; 7550141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 7551141cc406Sopenharmony_ci gamma_by_backend = md->model_flags & MD_NO_GAMMA ? 1 : 0; 7552141cc406Sopenharmony_ci right_to_left = mi->direction & MI_DATSEQ_RTOL; 7553141cc406Sopenharmony_ci scale1 = 16 - ms->depth; 7554141cc406Sopenharmony_ci scale2 = 2 * ms->depth - 16; 7555141cc406Sopenharmony_ci bpp_in = ( ms->bits_per_pixel_in + 7 ) / 8; /*Bytes per pixel from scanner*/ 7556141cc406Sopenharmony_ci 7557141cc406Sopenharmony_ci if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend) 7558141cc406Sopenharmony_ci { 7559141cc406Sopenharmony_ci maxval = (float) pow(2.0, (float) ms->depth) - 1.0; 7560141cc406Sopenharmony_ci s_w = maxval; 7561141cc406Sopenharmony_ci s_d = 0.0; 7562141cc406Sopenharmony_ci shading_factor = (float) pow(2.0, (double) (md->shading_depth 7563141cc406Sopenharmony_ci - ms->depth) ); 7564141cc406Sopenharmony_ci } 7565141cc406Sopenharmony_ci 7566141cc406Sopenharmony_ci if ( gamma_by_backend ) 7567141cc406Sopenharmony_ci { 7568141cc406Sopenharmony_ci i = (ms->depth > 8) ? 2 : 1; 7569141cc406Sopenharmony_ci for ( color = 0; color < 3; color++) 7570141cc406Sopenharmony_ci gamma[color] = ms->gamma_table 7571141cc406Sopenharmony_ci + i * (int) pow(2.0, (double)ms->depth); 7572141cc406Sopenharmony_ci } 7573141cc406Sopenharmony_ci 7574141cc406Sopenharmony_ci DBG(30, "segreg_copy_pixels: pixels=%d\n", ms->ppl); 7575141cc406Sopenharmony_ci DBG(100, "segreg_copy_pixels: buffer 0x%p, right_to_left=%d, depth=%d\n", 7576141cc406Sopenharmony_ci (void *) ms->buf.current_pos, right_to_left, ms->depth); 7577141cc406Sopenharmony_ci 7578141cc406Sopenharmony_ci for (color = 0; color < 3; color++ ) 7579141cc406Sopenharmony_ci f[color] = (float) ms->balance[color] / 100.0; 7580141cc406Sopenharmony_ci 7581141cc406Sopenharmony_ci DBG(100, "segreg_copy_pixels: color balance:\n" 7582141cc406Sopenharmony_ci " ms->balance[R]=%d, ms->balance[G]=%d, ms->balance[B]=%d\n", 7583141cc406Sopenharmony_ci ms->balance[0], ms->balance[1], ms->balance[2]); 7584141cc406Sopenharmony_ci 7585141cc406Sopenharmony_ci for ( pixel = 0; pixel < ms->ppl; pixel++ ) 7586141cc406Sopenharmony_ci { 7587141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7588141cc406Sopenharmony_ci { 7589141cc406Sopenharmony_ci if ( right_to_left ) 7590141cc406Sopenharmony_ci from_effective = ms->buf.current_pos[color] 7591141cc406Sopenharmony_ci + ( ms->ppl - 1 - pixel ) * bpp_in; 7592141cc406Sopenharmony_ci else 7593141cc406Sopenharmony_ci from_effective = ms->buf.current_pos[color] + pixel * bpp_in; 7594141cc406Sopenharmony_ci 7595141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7596141cc406Sopenharmony_ci val = (float) *(uint16_t *)from_effective; 7597141cc406Sopenharmony_ci else if ( ms->depth == 8 ) 7598141cc406Sopenharmony_ci val = (float) *from_effective; 7599141cc406Sopenharmony_ci else 7600141cc406Sopenharmony_ci { 7601141cc406Sopenharmony_ci DBG(1, "segreg_copy_pixels: Unknown depth %d\n", ms->depth); 7602141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7603141cc406Sopenharmony_ci } 7604141cc406Sopenharmony_ci 7605141cc406Sopenharmony_ci if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend 7606141cc406Sopenharmony_ci && ( ms->condensed_shading_w != NULL )) 7607141cc406Sopenharmony_ci /* apply shading by backend */ 7608141cc406Sopenharmony_ci { 7609141cc406Sopenharmony_ci get_cshading_values(ms, 7610141cc406Sopenharmony_ci color, 7611141cc406Sopenharmony_ci pixel, 7612141cc406Sopenharmony_ci shading_factor, 7613141cc406Sopenharmony_ci right_to_left, 7614141cc406Sopenharmony_ci &s_d, 7615141cc406Sopenharmony_ci &s_w); 7616141cc406Sopenharmony_ci 7617141cc406Sopenharmony_ci 7618141cc406Sopenharmony_ci if ( s_w == s_d ) s_w = s_d + 1; 7619141cc406Sopenharmony_ci if ( val < s_d ) val = s_d; 7620141cc406Sopenharmony_ci val = maxval *( val - s_d ) / ( s_w - s_d ); 7621141cc406Sopenharmony_ci 7622141cc406Sopenharmony_ci val *= f[color]; 7623141cc406Sopenharmony_ci 7624141cc406Sopenharmony_ci /* if scanner doesn't support brightness, contrast */ 7625141cc406Sopenharmony_ci if ( md->model_flags & MD_NO_ENHANCEMENTS ) 7626141cc406Sopenharmony_ci { 7627141cc406Sopenharmony_ci val += ( ( ms->brightness_m - 128 ) * 2 ); 7628141cc406Sopenharmony_ci val = ( val - 128 ) * ( ms->contrast_m / 128 ) + 128; 7629141cc406Sopenharmony_ci } 7630141cc406Sopenharmony_ci 7631141cc406Sopenharmony_ci val = MAX( 0.0, val); 7632141cc406Sopenharmony_ci val = MIN( maxval, val ); 7633141cc406Sopenharmony_ci } 7634141cc406Sopenharmony_ci 7635141cc406Sopenharmony_ci val16 = (uint16_t) val; 7636141cc406Sopenharmony_ci val8 = (uint8_t) val; 7637141cc406Sopenharmony_ci 7638141cc406Sopenharmony_ci /* apply gamma correction if needed */ 7639141cc406Sopenharmony_ci if ( gamma_by_backend ) 7640141cc406Sopenharmony_ci { 7641141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7642141cc406Sopenharmony_ci val16 = *((uint16_t *) gamma[color] + val16); 7643141cc406Sopenharmony_ci else 7644141cc406Sopenharmony_ci val8 = gamma[color][val8]; 7645141cc406Sopenharmony_ci } 7646141cc406Sopenharmony_ci 7647141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7648141cc406Sopenharmony_ci { 7649141cc406Sopenharmony_ci val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); 7650141cc406Sopenharmony_ci fwrite((void *) &val16, 2, 1, ms->fp); 7651141cc406Sopenharmony_ci } 7652141cc406Sopenharmony_ci else 7653141cc406Sopenharmony_ci { 7654141cc406Sopenharmony_ci fputc((unsigned char) val8, ms->fp); 7655141cc406Sopenharmony_ci } 7656141cc406Sopenharmony_ci 7657141cc406Sopenharmony_ci } 7658141cc406Sopenharmony_ci } 7659141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7660141cc406Sopenharmony_ci { 7661141cc406Sopenharmony_ci ms->buf.current_pos[color] += ms->ppl; 7662141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7663141cc406Sopenharmony_ci ms->buf.current_pos[color] += ms->ppl; 7664141cc406Sopenharmony_ci } 7665141cc406Sopenharmony_ci 7666141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7667141cc406Sopenharmony_ci 7668141cc406Sopenharmony_ci} 7669141cc406Sopenharmony_ci 7670141cc406Sopenharmony_ci 7671141cc406Sopenharmony_ci/*---------- lplconcat_proc_data() -------------------------------------------*/ 7672141cc406Sopenharmony_cistatic SANE_Status 7673141cc406Sopenharmony_cilplconcat_proc_data(Microtek2_Scanner *ms) 7674141cc406Sopenharmony_ci{ 7675141cc406Sopenharmony_ci SANE_Status status; 7676141cc406Sopenharmony_ci Microtek2_Device *md; 7677141cc406Sopenharmony_ci Microtek2_Info *mi; 7678141cc406Sopenharmony_ci uint32_t line; 7679141cc406Sopenharmony_ci uint8_t *from[3]; 7680141cc406Sopenharmony_ci uint8_t *save_from[3]; 7681141cc406Sopenharmony_ci int color; 7682141cc406Sopenharmony_ci int bpp; 7683141cc406Sopenharmony_ci int gamma_by_backend; 7684141cc406Sopenharmony_ci int right_to_left; /* 0=left to right, 1=right to left */ 7685141cc406Sopenharmony_ci 7686141cc406Sopenharmony_ci 7687141cc406Sopenharmony_ci DBG(30, "lplconcat_proc_data: ms=%p\n", (void *) ms); 7688141cc406Sopenharmony_ci 7689141cc406Sopenharmony_ci /* This data format seems to honour the color sequence indicator */ 7690141cc406Sopenharmony_ci 7691141cc406Sopenharmony_ci md = ms->dev; 7692141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 7693141cc406Sopenharmony_ci 7694141cc406Sopenharmony_ci bpp = ms->bits_per_pixel_out / 8; /* ms->bits_per_pixel_out is 8 or 16 */ 7695141cc406Sopenharmony_ci right_to_left = mi->direction & MI_DATSEQ_RTOL; 7696141cc406Sopenharmony_ci gamma_by_backend = md->model_flags & MD_NO_GAMMA ? 1 : 0; 7697141cc406Sopenharmony_ci 7698141cc406Sopenharmony_ci if ( right_to_left == 1 ) 7699141cc406Sopenharmony_ci { 7700141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7701141cc406Sopenharmony_ci { 7702141cc406Sopenharmony_ci from[color] = ms->buf.src_buf 7703141cc406Sopenharmony_ci + ( mi->color_sequence[color] + 1 ) * ( ms->bpl / 3 ) 7704141cc406Sopenharmony_ci - bpp - (ms->bpl - 3 * ms->ppl * bpp) / 3; 7705141cc406Sopenharmony_ci } 7706141cc406Sopenharmony_ci } 7707141cc406Sopenharmony_ci else 7708141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7709141cc406Sopenharmony_ci from[color] = ms->buf.src_buf 7710141cc406Sopenharmony_ci + mi->color_sequence[color] * ( ms->bpl / 3 ); 7711141cc406Sopenharmony_ci 7712141cc406Sopenharmony_ci for ( line = 0; line < (uint32_t) ms->src_lines_to_read; line++ ) 7713141cc406Sopenharmony_ci { 7714141cc406Sopenharmony_ci for ( color = 0 ; color < 3; color++ ) 7715141cc406Sopenharmony_ci save_from[color] = from[color]; 7716141cc406Sopenharmony_ci 7717141cc406Sopenharmony_ci status = lplconcat_copy_pixels(ms, 7718141cc406Sopenharmony_ci from, 7719141cc406Sopenharmony_ci right_to_left, 7720141cc406Sopenharmony_ci gamma_by_backend); 7721141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7722141cc406Sopenharmony_ci return status; 7723141cc406Sopenharmony_ci 7724141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7725141cc406Sopenharmony_ci from[color] = save_from[color] + ms->bpl; 7726141cc406Sopenharmony_ci } 7727141cc406Sopenharmony_ci 7728141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7729141cc406Sopenharmony_ci} 7730141cc406Sopenharmony_ci 7731141cc406Sopenharmony_ci 7732141cc406Sopenharmony_ci/*---------- lplconcat_copy_pixels() -----------------------------------------*/ 7733141cc406Sopenharmony_ci 7734141cc406Sopenharmony_cistatic SANE_Status 7735141cc406Sopenharmony_cilplconcat_copy_pixels(Microtek2_Scanner *ms, 7736141cc406Sopenharmony_ci uint8_t **from, 7737141cc406Sopenharmony_ci int right_to_left, 7738141cc406Sopenharmony_ci int gamma_by_backend) 7739141cc406Sopenharmony_ci{ 7740141cc406Sopenharmony_ci Microtek2_Device *md; 7741141cc406Sopenharmony_ci Microtek2_Info *mi; 7742141cc406Sopenharmony_ci uint32_t pixel; 7743141cc406Sopenharmony_ci uint16_t val16 = 0; 7744141cc406Sopenharmony_ci uint8_t val8 = 0; 7745141cc406Sopenharmony_ci uint8_t *gamma[3]; 7746141cc406Sopenharmony_ci float s_d; /* dark shading pixel */ 7747141cc406Sopenharmony_ci float s_w; /* white shading pixel */ 7748141cc406Sopenharmony_ci float shading_factor = 0; 7749141cc406Sopenharmony_ci float f[3]; /* color balance factor */ 7750141cc406Sopenharmony_ci float val, maxval = 0; 7751141cc406Sopenharmony_ci int color; 7752141cc406Sopenharmony_ci int step, scale1, scale2; 7753141cc406Sopenharmony_ci int i; 7754141cc406Sopenharmony_ci 7755141cc406Sopenharmony_ci 7756141cc406Sopenharmony_ci DBG(30, "lplconcat_copy_pixels: ms=%p, righttoleft=%d, gamma=%d,\n", 7757141cc406Sopenharmony_ci (void *) ms, right_to_left, gamma_by_backend); 7758141cc406Sopenharmony_ci 7759141cc406Sopenharmony_ci md = ms->dev; 7760141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 7761141cc406Sopenharmony_ci 7762141cc406Sopenharmony_ci if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend) 7763141cc406Sopenharmony_ci { 7764141cc406Sopenharmony_ci shading_factor = (float) pow(2.0,(double)(md->shading_depth - ms->depth)); 7765141cc406Sopenharmony_ci maxval = (float) pow(2.0, (double) ms->depth) - 1.0; 7766141cc406Sopenharmony_ci s_w = maxval; 7767141cc406Sopenharmony_ci s_d = 0.0; 7768141cc406Sopenharmony_ci } 7769141cc406Sopenharmony_ci 7770141cc406Sopenharmony_ci step = ( right_to_left == 1 ) ? -1 : 1; 7771141cc406Sopenharmony_ci if ( ms->depth > 8 ) step *= 2; 7772141cc406Sopenharmony_ci scale1 = 16 - ms->depth; 7773141cc406Sopenharmony_ci scale2 = 2 * ms->depth - 16; 7774141cc406Sopenharmony_ci 7775141cc406Sopenharmony_ci if ( gamma_by_backend ) 7776141cc406Sopenharmony_ci { 7777141cc406Sopenharmony_ci i = ( ms->depth > 8 ) ? 2 : 1; 7778141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7779141cc406Sopenharmony_ci gamma[color] = ms->gamma_table + i * (int) pow(2.0,(double)ms->depth); 7780141cc406Sopenharmony_ci } 7781141cc406Sopenharmony_ci 7782141cc406Sopenharmony_ci for (color = 0; color < 3; color++ ) 7783141cc406Sopenharmony_ci f[color] = (float)ms->balance[color] / 100.0; 7784141cc406Sopenharmony_ci 7785141cc406Sopenharmony_ci DBG(100, "lplconcat_copy_pixels: color balance:\n" 7786141cc406Sopenharmony_ci " ms->balance[R]=%d, ms->balance[G]=%d, ms->balance[B]=%d\n", 7787141cc406Sopenharmony_ci ms->balance[0], ms->balance[1], ms->balance[2]); 7788141cc406Sopenharmony_ci 7789141cc406Sopenharmony_ci for ( pixel = 0; pixel < ms->ppl; pixel++ ) 7790141cc406Sopenharmony_ci { 7791141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7792141cc406Sopenharmony_ci { 7793141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7794141cc406Sopenharmony_ci val = (float) *(uint16_t *) from[color]; 7795141cc406Sopenharmony_ci else if ( ms->depth == 8 ) 7796141cc406Sopenharmony_ci val = (float) *from[color]; 7797141cc406Sopenharmony_ci else 7798141cc406Sopenharmony_ci { 7799141cc406Sopenharmony_ci DBG(1, "lplconcat_copy_pixels: Unknown depth %d\n", ms->depth); 7800141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7801141cc406Sopenharmony_ci } 7802141cc406Sopenharmony_ci 7803141cc406Sopenharmony_ci if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend 7804141cc406Sopenharmony_ci && ( ms->condensed_shading_w != NULL )) 7805141cc406Sopenharmony_ci /* apply shading by backend */ 7806141cc406Sopenharmony_ci { 7807141cc406Sopenharmony_ci get_cshading_values(ms, 7808141cc406Sopenharmony_ci mi->color_sequence[color], 7809141cc406Sopenharmony_ci pixel, 7810141cc406Sopenharmony_ci shading_factor, 7811141cc406Sopenharmony_ci right_to_left, 7812141cc406Sopenharmony_ci &s_d, 7813141cc406Sopenharmony_ci &s_w); 7814141cc406Sopenharmony_ci 7815141cc406Sopenharmony_ci if ( val < s_d ) val = s_d; 7816141cc406Sopenharmony_ci if ( s_w == s_d ) s_w = s_d + 1; 7817141cc406Sopenharmony_ci val = ( maxval * ( val - s_d ) ) / (s_w - s_d); 7818141cc406Sopenharmony_ci 7819141cc406Sopenharmony_ci val *= f[color]; /* apply color balance */ 7820141cc406Sopenharmony_ci 7821141cc406Sopenharmony_ci /* if scanner doesn't support brightness, contrast ... */ 7822141cc406Sopenharmony_ci if ( md->model_flags & MD_NO_ENHANCEMENTS ) 7823141cc406Sopenharmony_ci { 7824141cc406Sopenharmony_ci val += ( ( ms->brightness_m - 128 ) * 2 ); 7825141cc406Sopenharmony_ci val = ( val - 128 ) * ( ms->contrast_m / 128 ) + 128; 7826141cc406Sopenharmony_ci } 7827141cc406Sopenharmony_ci 7828141cc406Sopenharmony_ci if ( val > maxval ) val = maxval; 7829141cc406Sopenharmony_ci if ( val < 0.0 ) val = 0.0; 7830141cc406Sopenharmony_ci } 7831141cc406Sopenharmony_ci 7832141cc406Sopenharmony_ci val16 = (uint16_t) val; 7833141cc406Sopenharmony_ci val8 = (uint8_t) val; 7834141cc406Sopenharmony_ci 7835141cc406Sopenharmony_ci /* apply gamma correction if needed */ 7836141cc406Sopenharmony_ci if ( gamma_by_backend ) 7837141cc406Sopenharmony_ci { 7838141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7839141cc406Sopenharmony_ci val16 = *((uint16_t *) gamma[color] + val16); 7840141cc406Sopenharmony_ci else 7841141cc406Sopenharmony_ci val8 = gamma[color][val8]; 7842141cc406Sopenharmony_ci } 7843141cc406Sopenharmony_ci 7844141cc406Sopenharmony_ci if ( ms->depth > 8 ) 7845141cc406Sopenharmony_ci { 7846141cc406Sopenharmony_ci val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); 7847141cc406Sopenharmony_ci fwrite((void *) &val16, 2, 1, ms->fp); 7848141cc406Sopenharmony_ci } 7849141cc406Sopenharmony_ci else 7850141cc406Sopenharmony_ci { 7851141cc406Sopenharmony_ci fputc((unsigned char) val8, ms->fp); 7852141cc406Sopenharmony_ci } 7853141cc406Sopenharmony_ci from[color] += step; 7854141cc406Sopenharmony_ci } 7855141cc406Sopenharmony_ci } 7856141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7857141cc406Sopenharmony_ci} 7858141cc406Sopenharmony_ci 7859141cc406Sopenharmony_ci 7860141cc406Sopenharmony_ci 7861141cc406Sopenharmony_ci 7862141cc406Sopenharmony_ci/*---------- wordchunky_proc_data() ------------------------------------------*/ 7863141cc406Sopenharmony_ci 7864141cc406Sopenharmony_cistatic SANE_Status 7865141cc406Sopenharmony_ciwordchunky_proc_data(Microtek2_Scanner *ms) 7866141cc406Sopenharmony_ci{ 7867141cc406Sopenharmony_ci SANE_Status status; 7868141cc406Sopenharmony_ci uint8_t *from; 7869141cc406Sopenharmony_ci uint32_t line; 7870141cc406Sopenharmony_ci 7871141cc406Sopenharmony_ci 7872141cc406Sopenharmony_ci DBG(30, "wordchunky_proc_data: ms=%p\n", (void *) ms); 7873141cc406Sopenharmony_ci 7874141cc406Sopenharmony_ci from = ms->buf.src_buf; 7875141cc406Sopenharmony_ci for ( line = 0; line < (uint32_t) ms->src_lines_to_read; line++ ) 7876141cc406Sopenharmony_ci { 7877141cc406Sopenharmony_ci status = wordchunky_copy_pixels(from, ms->ppl, ms->depth, ms->fp); 7878141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7879141cc406Sopenharmony_ci return status; 7880141cc406Sopenharmony_ci from += ms->bpl; 7881141cc406Sopenharmony_ci } 7882141cc406Sopenharmony_ci 7883141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7884141cc406Sopenharmony_ci} 7885141cc406Sopenharmony_ci 7886141cc406Sopenharmony_ci 7887141cc406Sopenharmony_ci/*---------- wordchunky_copy_pixels() ----------------------------------------*/ 7888141cc406Sopenharmony_ci 7889141cc406Sopenharmony_cistatic SANE_Status 7890141cc406Sopenharmony_ciwordchunky_copy_pixels(uint8_t *from, uint32_t pixels, int depth, FILE *fp) 7891141cc406Sopenharmony_ci{ 7892141cc406Sopenharmony_ci uint32_t pixel; 7893141cc406Sopenharmony_ci int color; 7894141cc406Sopenharmony_ci 7895141cc406Sopenharmony_ci DBG(30, "wordchunky_copy_pixels: from=%p, pixels=%d, depth=%d\n", 7896141cc406Sopenharmony_ci (void *) from, pixels, depth); 7897141cc406Sopenharmony_ci 7898141cc406Sopenharmony_ci if ( depth > 8 ) 7899141cc406Sopenharmony_ci { 7900141cc406Sopenharmony_ci int scale1; 7901141cc406Sopenharmony_ci int scale2; 7902141cc406Sopenharmony_ci uint16_t val16; 7903141cc406Sopenharmony_ci 7904141cc406Sopenharmony_ci scale1 = 16 - depth; 7905141cc406Sopenharmony_ci scale2 = 2 * depth - 16; 7906141cc406Sopenharmony_ci for ( pixel = 0; pixel < pixels; pixel++ ) 7907141cc406Sopenharmony_ci { 7908141cc406Sopenharmony_ci for ( color = 0; color < 3; color++ ) 7909141cc406Sopenharmony_ci { 7910141cc406Sopenharmony_ci val16 = *(uint16_t *) from; 7911141cc406Sopenharmony_ci val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); 7912141cc406Sopenharmony_ci fwrite((void *) &val16, 2, 1, fp); 7913141cc406Sopenharmony_ci from += 2; 7914141cc406Sopenharmony_ci } 7915141cc406Sopenharmony_ci } 7916141cc406Sopenharmony_ci } 7917141cc406Sopenharmony_ci else if ( depth == 8 ) 7918141cc406Sopenharmony_ci { 7919141cc406Sopenharmony_ci pixel = 0; 7920141cc406Sopenharmony_ci do 7921141cc406Sopenharmony_ci { 7922141cc406Sopenharmony_ci fputc((char ) *from, fp); 7923141cc406Sopenharmony_ci fputc((char) *(from + 2), fp); 7924141cc406Sopenharmony_ci fputc((char) *(from + 4), fp); 7925141cc406Sopenharmony_ci ++pixel; 7926141cc406Sopenharmony_ci if ( pixel < pixels ) 7927141cc406Sopenharmony_ci { 7928141cc406Sopenharmony_ci fputc((char) *(from + 1), fp); 7929141cc406Sopenharmony_ci fputc((char) *(from + 3), fp); 7930141cc406Sopenharmony_ci fputc((char) *(from + 5), fp); 7931141cc406Sopenharmony_ci ++pixel; 7932141cc406Sopenharmony_ci } 7933141cc406Sopenharmony_ci from += 6; 7934141cc406Sopenharmony_ci } while ( pixel < pixels ); 7935141cc406Sopenharmony_ci } 7936141cc406Sopenharmony_ci else 7937141cc406Sopenharmony_ci { 7938141cc406Sopenharmony_ci DBG(1, "wordchunky_copy_pixels: Unknown depth %d\n", depth); 7939141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7940141cc406Sopenharmony_ci } 7941141cc406Sopenharmony_ci 7942141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7943141cc406Sopenharmony_ci} 7944141cc406Sopenharmony_ci 7945141cc406Sopenharmony_ci 7946141cc406Sopenharmony_ci/*---------- gray_proc_data() ------------------------------------------------*/ 7947141cc406Sopenharmony_ci 7948141cc406Sopenharmony_cistatic SANE_Status 7949141cc406Sopenharmony_cigray_proc_data(Microtek2_Scanner *ms) 7950141cc406Sopenharmony_ci{ 7951141cc406Sopenharmony_ci SANE_Status status; 7952141cc406Sopenharmony_ci Microtek2_Device *md; 7953141cc406Sopenharmony_ci Microtek2_Info *mi; 7954141cc406Sopenharmony_ci uint8_t *from; 7955141cc406Sopenharmony_ci int gamma_by_backend, bpp; 7956141cc406Sopenharmony_ci int right_to_left; /* for scanning direction */ 7957141cc406Sopenharmony_ci 7958141cc406Sopenharmony_ci 7959141cc406Sopenharmony_ci DBG(30, "gray_proc_data: lines=%d, bpl=%d, ppl=%d, depth=%d\n", 7960141cc406Sopenharmony_ci ms->src_lines_to_read, ms->bpl, ms->ppl, ms->depth); 7961141cc406Sopenharmony_ci 7962141cc406Sopenharmony_ci md = ms->dev; 7963141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 7964141cc406Sopenharmony_ci 7965141cc406Sopenharmony_ci gamma_by_backend = md->model_flags & MD_NO_GAMMA ? 1 : 0; 7966141cc406Sopenharmony_ci right_to_left = mi->direction & MI_DATSEQ_RTOL; 7967141cc406Sopenharmony_ci bpp = ( ms->bits_per_pixel_in + 7 ) / 8; 7968141cc406Sopenharmony_ci 7969141cc406Sopenharmony_ci if ( right_to_left == 1 ) 7970141cc406Sopenharmony_ci from = ms->buf.src_buf + ms->ppl * bpp - bpp; 7971141cc406Sopenharmony_ci else 7972141cc406Sopenharmony_ci from = ms->buf.src_buf; 7973141cc406Sopenharmony_ci 7974141cc406Sopenharmony_ci do 7975141cc406Sopenharmony_ci { 7976141cc406Sopenharmony_ci status = gray_copy_pixels(ms, 7977141cc406Sopenharmony_ci from, 7978141cc406Sopenharmony_ci right_to_left, 7979141cc406Sopenharmony_ci gamma_by_backend); 7980141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 7981141cc406Sopenharmony_ci return status; 7982141cc406Sopenharmony_ci 7983141cc406Sopenharmony_ci from += ms->bpl; 7984141cc406Sopenharmony_ci --ms->src_lines_to_read; 7985141cc406Sopenharmony_ci } while ( ms->src_lines_to_read > 0 ); 7986141cc406Sopenharmony_ci 7987141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 7988141cc406Sopenharmony_ci} 7989141cc406Sopenharmony_ci 7990141cc406Sopenharmony_ci 7991141cc406Sopenharmony_ci/*---------- gray_copy_pixels() ----------------------------------------------*/ 7992141cc406Sopenharmony_ci 7993141cc406Sopenharmony_cistatic SANE_Status 7994141cc406Sopenharmony_cigray_copy_pixels(Microtek2_Scanner *ms, 7995141cc406Sopenharmony_ci uint8_t *from, 7996141cc406Sopenharmony_ci int right_to_left, 7997141cc406Sopenharmony_ci int gamma_by_backend) 7998141cc406Sopenharmony_ci{ 7999141cc406Sopenharmony_ci Microtek2_Device *md; 8000141cc406Sopenharmony_ci uint32_t pixel; 8001141cc406Sopenharmony_ci uint16_t val16; 8002141cc406Sopenharmony_ci uint8_t val8; 8003141cc406Sopenharmony_ci int step, scale1, scale2; 8004141cc406Sopenharmony_ci float val, maxval = 0; 8005141cc406Sopenharmony_ci float s_w, s_d, shading_factor = 0; 8006141cc406Sopenharmony_ci 8007141cc406Sopenharmony_ci DBG(30, "gray_copy_pixels: pixels=%d, from=%p, fp=%p, depth=%d\n", 8008141cc406Sopenharmony_ci ms->ppl, (void *) from, (void *) ms->fp, ms->depth); 8009141cc406Sopenharmony_ci 8010141cc406Sopenharmony_ci md = ms->dev; 8011141cc406Sopenharmony_ci step = right_to_left == 1 ? -1 : 1; 8012141cc406Sopenharmony_ci if ( ms->depth > 8 ) step *= 2; 8013141cc406Sopenharmony_ci val = 0; 8014141cc406Sopenharmony_ci scale1 = 16 - ms->depth; 8015141cc406Sopenharmony_ci scale2 = 2 * ms->depth - 16; 8016141cc406Sopenharmony_ci 8017141cc406Sopenharmony_ci if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend) 8018141cc406Sopenharmony_ci { 8019141cc406Sopenharmony_ci maxval = (float) pow(2.0, (float) ms->depth) - 1.0; 8020141cc406Sopenharmony_ci s_w = maxval; 8021141cc406Sopenharmony_ci s_d = 0.0; 8022141cc406Sopenharmony_ci shading_factor = (float) pow(2.0, (double) (md->shading_depth - ms->depth) ); 8023141cc406Sopenharmony_ci } 8024141cc406Sopenharmony_ci 8025141cc406Sopenharmony_ci if ( ms->depth >= 8 ) 8026141cc406Sopenharmony_ci { 8027141cc406Sopenharmony_ci for ( pixel = 0; pixel < ms->ppl; pixel++ ) 8028141cc406Sopenharmony_ci { 8029141cc406Sopenharmony_ci if ( ms->depth > 8 ) 8030141cc406Sopenharmony_ci val = (float) *(uint16_t *) from; 8031141cc406Sopenharmony_ci if ( ms->depth == 8 ) 8032141cc406Sopenharmony_ci val = (float) *from; 8033141cc406Sopenharmony_ci 8034141cc406Sopenharmony_ci if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend 8035141cc406Sopenharmony_ci && ( ms->condensed_shading_w != NULL )) 8036141cc406Sopenharmony_ci /* apply shading by backend */ 8037141cc406Sopenharmony_ci { 8038141cc406Sopenharmony_ci get_cshading_values(ms, 8039141cc406Sopenharmony_ci 0, 8040141cc406Sopenharmony_ci pixel, 8041141cc406Sopenharmony_ci shading_factor, 8042141cc406Sopenharmony_ci right_to_left, 8043141cc406Sopenharmony_ci &s_d, 8044141cc406Sopenharmony_ci &s_w); 8045141cc406Sopenharmony_ci 8046141cc406Sopenharmony_ci if ( val < s_d ) val = s_d; 8047141cc406Sopenharmony_ci val = ( val - s_d ) * maxval / (s_w - s_d ); 8048141cc406Sopenharmony_ci val = MAX( 0.0, val ); 8049141cc406Sopenharmony_ci val = MIN( maxval, val ); 8050141cc406Sopenharmony_ci } 8051141cc406Sopenharmony_ci 8052141cc406Sopenharmony_ci if ( ms->depth > 8 ) 8053141cc406Sopenharmony_ci { 8054141cc406Sopenharmony_ci val16 = (uint16_t) val; 8055141cc406Sopenharmony_ci if ( gamma_by_backend ) 8056141cc406Sopenharmony_ci val16 = *((uint16_t *) ms->gamma_table + val16); 8057141cc406Sopenharmony_ci if ( !( md->model_flags & MD_16BIT_TRANSFER ) ) 8058141cc406Sopenharmony_ci val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); 8059141cc406Sopenharmony_ci fwrite((void *) &val16, 2, 1, ms->fp); 8060141cc406Sopenharmony_ci } 8061141cc406Sopenharmony_ci 8062141cc406Sopenharmony_ci if ( ms->depth == 8 ) 8063141cc406Sopenharmony_ci { 8064141cc406Sopenharmony_ci val8 = (uint8_t) val; 8065141cc406Sopenharmony_ci if ( gamma_by_backend ) 8066141cc406Sopenharmony_ci val8 = ms->gamma_table[(int)val8]; 8067141cc406Sopenharmony_ci fputc((char)val8, ms->fp); 8068141cc406Sopenharmony_ci } 8069141cc406Sopenharmony_ci from += step; 8070141cc406Sopenharmony_ci } 8071141cc406Sopenharmony_ci } 8072141cc406Sopenharmony_ci else if ( ms->depth == 4 ) 8073141cc406Sopenharmony_ci { 8074141cc406Sopenharmony_ci pixel = 0; 8075141cc406Sopenharmony_ci while ( pixel < ms->ppl ) 8076141cc406Sopenharmony_ci { 8077141cc406Sopenharmony_ci fputc((char) ( ((*from >> 4) & 0x0f) | (*from & 0xf0) ), ms->fp); 8078141cc406Sopenharmony_ci ++pixel; 8079141cc406Sopenharmony_ci if ( pixel < ms->ppl ) 8080141cc406Sopenharmony_ci fputc((char) ((*from & 0x0f) | ((*from << 4) & 0xf0)), ms->fp); 8081141cc406Sopenharmony_ci from += step; 8082141cc406Sopenharmony_ci ++pixel; 8083141cc406Sopenharmony_ci } 8084141cc406Sopenharmony_ci } 8085141cc406Sopenharmony_ci else 8086141cc406Sopenharmony_ci { 8087141cc406Sopenharmony_ci DBG(1, "gray_copy_pixels: Unknown depth %d\n", ms->depth); 8088141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 8089141cc406Sopenharmony_ci } 8090141cc406Sopenharmony_ci 8091141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 8092141cc406Sopenharmony_ci} 8093141cc406Sopenharmony_ci 8094141cc406Sopenharmony_ci/*---------- proc_onebit_data() ----------------------------------------------*/ 8095141cc406Sopenharmony_ci 8096141cc406Sopenharmony_cistatic SANE_Status 8097141cc406Sopenharmony_ciproc_onebit_data(Microtek2_Scanner *ms) 8098141cc406Sopenharmony_ci{ 8099141cc406Sopenharmony_ci Microtek2_Device *md; 8100141cc406Sopenharmony_ci Microtek2_Info *mi; 8101141cc406Sopenharmony_ci uint32_t bytes_to_copy; /* bytes per line to copy */ 8102141cc406Sopenharmony_ci uint32_t line; 8103141cc406Sopenharmony_ci uint32_t byte; 8104141cc406Sopenharmony_ci uint32_t ppl; 8105141cc406Sopenharmony_ci uint8_t *from; 8106141cc406Sopenharmony_ci uint8_t to; 8107141cc406Sopenharmony_ci int right_to_left; 8108141cc406Sopenharmony_ci int bit; 8109141cc406Sopenharmony_ci int toindex; 8110141cc406Sopenharmony_ci 8111141cc406Sopenharmony_ci 8112141cc406Sopenharmony_ci DBG(30, "proc_onebit_data: ms=%p\n", (void *) ms); 8113141cc406Sopenharmony_ci 8114141cc406Sopenharmony_ci md = ms->dev; 8115141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 8116141cc406Sopenharmony_ci from = ms->buf.src_buf; 8117141cc406Sopenharmony_ci bytes_to_copy = ( ms->ppl + 7 ) / 8 ; 8118141cc406Sopenharmony_ci right_to_left = mi->direction & MI_DATSEQ_RTOL; 8119141cc406Sopenharmony_ci 8120141cc406Sopenharmony_ci DBG(30, "proc_onebit_data: bytes_to_copy=%d, lines=%d\n", 8121141cc406Sopenharmony_ci bytes_to_copy, ms->src_lines_to_read); 8122141cc406Sopenharmony_ci 8123141cc406Sopenharmony_ci line = 0; 8124141cc406Sopenharmony_ci to = 0; 8125141cc406Sopenharmony_ci do 8126141cc406Sopenharmony_ci { 8127141cc406Sopenharmony_ci /* in onebit mode black and white colors are inverted */ 8128141cc406Sopenharmony_ci if ( right_to_left ) 8129141cc406Sopenharmony_ci { 8130141cc406Sopenharmony_ci /* If the direction is right_to_left, we must skip some */ 8131141cc406Sopenharmony_ci /* trailing bits at the end of the scan line and invert the */ 8132141cc406Sopenharmony_ci /* bit sequence. We copy 8 bits into a byte, but these bits */ 8133141cc406Sopenharmony_ci /* are normally not byte aligned. */ 8134141cc406Sopenharmony_ci 8135141cc406Sopenharmony_ci /* Determine the position of the first bit to copy */ 8136141cc406Sopenharmony_ci ppl = ms->ppl; 8137141cc406Sopenharmony_ci byte = ( ppl + 7 ) / 8 - 1; 8138141cc406Sopenharmony_ci bit = ppl % 8 - 1; 8139141cc406Sopenharmony_ci to = 0; 8140141cc406Sopenharmony_ci toindex = 8; 8141141cc406Sopenharmony_ci 8142141cc406Sopenharmony_ci while ( ppl > 0 ) 8143141cc406Sopenharmony_ci { 8144141cc406Sopenharmony_ci to |= ( ( from[byte] >> (7 - bit) ) & 0x01); 8145141cc406Sopenharmony_ci --toindex; 8146141cc406Sopenharmony_ci if ( toindex == 0 ) 8147141cc406Sopenharmony_ci { 8148141cc406Sopenharmony_ci fputc( (char) ~to, ms->fp); 8149141cc406Sopenharmony_ci toindex = 8; 8150141cc406Sopenharmony_ci to = 0; 8151141cc406Sopenharmony_ci } 8152141cc406Sopenharmony_ci else 8153141cc406Sopenharmony_ci to <<= 1; 8154141cc406Sopenharmony_ci 8155141cc406Sopenharmony_ci --bit; 8156141cc406Sopenharmony_ci if ( bit < 0 ) 8157141cc406Sopenharmony_ci { 8158141cc406Sopenharmony_ci bit = 7; 8159141cc406Sopenharmony_ci --byte; 8160141cc406Sopenharmony_ci } 8161141cc406Sopenharmony_ci --ppl; 8162141cc406Sopenharmony_ci } 8163141cc406Sopenharmony_ci /* print the last byte of the line, if it was not */ 8164141cc406Sopenharmony_ci /* completely filled */ 8165141cc406Sopenharmony_ci bit = ms->ppl % 8; 8166141cc406Sopenharmony_ci if ( bit != 0 ) 8167141cc406Sopenharmony_ci fputc( (char) ~(to << (7 - bit)), ms->fp); 8168141cc406Sopenharmony_ci } 8169141cc406Sopenharmony_ci else 8170141cc406Sopenharmony_ci for ( byte = 0; byte < bytes_to_copy; byte++ ) 8171141cc406Sopenharmony_ci fputc( (char) ~from[byte], ms->fp); 8172141cc406Sopenharmony_ci 8173141cc406Sopenharmony_ci from += ms->bpl; 8174141cc406Sopenharmony_ci 8175141cc406Sopenharmony_ci } while ( ++line < (uint32_t) ms->src_lines_to_read ); 8176141cc406Sopenharmony_ci 8177141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 8178141cc406Sopenharmony_ci} 8179141cc406Sopenharmony_ci 8180141cc406Sopenharmony_ci 8181141cc406Sopenharmony_ci/*---------- lineartfake_proc_data() -----------------------------------------*/ 8182141cc406Sopenharmony_ci 8183141cc406Sopenharmony_cistatic SANE_Status 8184141cc406Sopenharmony_cilineartfake_proc_data(Microtek2_Scanner *ms) 8185141cc406Sopenharmony_ci{ 8186141cc406Sopenharmony_ci Microtek2_Device *md; 8187141cc406Sopenharmony_ci Microtek2_Info *mi; 8188141cc406Sopenharmony_ci SANE_Status status; 8189141cc406Sopenharmony_ci uint8_t *from; 8190141cc406Sopenharmony_ci int right_to_left; 8191141cc406Sopenharmony_ci 8192141cc406Sopenharmony_ci 8193141cc406Sopenharmony_ci DBG(30, "lineartfake_proc_data: lines=%d, bpl=%d, ppl=%d, depth=%d\n", 8194141cc406Sopenharmony_ci ms->src_lines_to_read, ms->bpl, ms->ppl, ms->depth); 8195141cc406Sopenharmony_ci 8196141cc406Sopenharmony_ci md = ms->dev; 8197141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 8198141cc406Sopenharmony_ci right_to_left = mi->direction & MI_DATSEQ_RTOL; 8199141cc406Sopenharmony_ci 8200141cc406Sopenharmony_ci if ( right_to_left == 1 ) 8201141cc406Sopenharmony_ci from = ms->buf.src_buf + ms->ppl - 1; 8202141cc406Sopenharmony_ci else 8203141cc406Sopenharmony_ci from = ms->buf.src_buf; 8204141cc406Sopenharmony_ci 8205141cc406Sopenharmony_ci do 8206141cc406Sopenharmony_ci { 8207141cc406Sopenharmony_ci status = lineartfake_copy_pixels(ms, 8208141cc406Sopenharmony_ci from, 8209141cc406Sopenharmony_ci ms->ppl, 8210141cc406Sopenharmony_ci ms->threshold, 8211141cc406Sopenharmony_ci right_to_left, 8212141cc406Sopenharmony_ci ms->fp); 8213141cc406Sopenharmony_ci if ( status != SANE_STATUS_GOOD ) 8214141cc406Sopenharmony_ci return status; 8215141cc406Sopenharmony_ci 8216141cc406Sopenharmony_ci from += ms->bpl; 8217141cc406Sopenharmony_ci --ms->src_lines_to_read; 8218141cc406Sopenharmony_ci } while ( ms->src_lines_to_read > 0 ); 8219141cc406Sopenharmony_ci 8220141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 8221141cc406Sopenharmony_ci} 8222141cc406Sopenharmony_ci 8223141cc406Sopenharmony_ci/*---------- lineartfake_copy_pixels() ---------------------------------------*/ 8224141cc406Sopenharmony_ci 8225141cc406Sopenharmony_cistatic SANE_Status 8226141cc406Sopenharmony_cilineartfake_copy_pixels(Microtek2_Scanner *ms, 8227141cc406Sopenharmony_ci uint8_t *from, 8228141cc406Sopenharmony_ci uint32_t pixels, 8229141cc406Sopenharmony_ci uint8_t threshold, 8230141cc406Sopenharmony_ci int right_to_left, 8231141cc406Sopenharmony_ci FILE *fp) 8232141cc406Sopenharmony_ci{ 8233141cc406Sopenharmony_ci Microtek2_Device *md; 8234141cc406Sopenharmony_ci uint32_t pixel; 8235141cc406Sopenharmony_ci uint32_t bit; 8236141cc406Sopenharmony_ci uint8_t dest; 8237141cc406Sopenharmony_ci uint8_t val; 8238141cc406Sopenharmony_ci float s_d, s_w, maxval, shading_factor, grayval; 8239141cc406Sopenharmony_ci int step; 8240141cc406Sopenharmony_ci 8241141cc406Sopenharmony_ci 8242141cc406Sopenharmony_ci DBG(30, "lineartfake_copy_pixels: from=%p,pixels=%d,threshold=%d,file=%p\n", 8243141cc406Sopenharmony_ci (void *) from, pixels, threshold, (void *) fp); 8244141cc406Sopenharmony_ci md = ms->dev; 8245141cc406Sopenharmony_ci bit = 0; 8246141cc406Sopenharmony_ci dest = 0; 8247141cc406Sopenharmony_ci step = right_to_left == 1 ? -1 : 1; 8248141cc406Sopenharmony_ci maxval = 255.0; 8249141cc406Sopenharmony_ci s_w = maxval; 8250141cc406Sopenharmony_ci s_d = 0.0; 8251141cc406Sopenharmony_ci shading_factor = (float) pow(2.0, (double) (md->shading_depth - 8) ); 8252141cc406Sopenharmony_ci 8253141cc406Sopenharmony_ci for ( pixel = 0; pixel < pixels; pixel++ ) 8254141cc406Sopenharmony_ci { 8255141cc406Sopenharmony_ci if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend 8256141cc406Sopenharmony_ci && ( ms->condensed_shading_w != NULL )) 8257141cc406Sopenharmony_ci /* apply shading by backend */ 8258141cc406Sopenharmony_ci { 8259141cc406Sopenharmony_ci get_cshading_values(ms, 8260141cc406Sopenharmony_ci 0, 8261141cc406Sopenharmony_ci pixel, 8262141cc406Sopenharmony_ci shading_factor, 8263141cc406Sopenharmony_ci right_to_left, 8264141cc406Sopenharmony_ci &s_d, 8265141cc406Sopenharmony_ci &s_w); 8266141cc406Sopenharmony_ci } 8267141cc406Sopenharmony_ci else /* no shading */ 8268141cc406Sopenharmony_ci { 8269141cc406Sopenharmony_ci s_w = maxval; 8270141cc406Sopenharmony_ci s_d = 0.0; 8271141cc406Sopenharmony_ci } 8272141cc406Sopenharmony_ci 8273141cc406Sopenharmony_ci grayval = (float) *from; 8274141cc406Sopenharmony_ci 8275141cc406Sopenharmony_ci if ( grayval < s_d ) grayval = s_d; 8276141cc406Sopenharmony_ci grayval = ( grayval - s_d ) * maxval / (s_w - s_d ); 8277141cc406Sopenharmony_ci grayval = MAX( 0.0, grayval ); 8278141cc406Sopenharmony_ci grayval = MIN( maxval, grayval ); 8279141cc406Sopenharmony_ci 8280141cc406Sopenharmony_ci if ( (uint8_t)grayval < threshold ) val = 1; else val = 0; 8281141cc406Sopenharmony_ci dest = ( dest << 1 ) | val; 8282141cc406Sopenharmony_ci bit = ( bit + 1 ) % 8; 8283141cc406Sopenharmony_ci if ( bit == 0 ) /* 8 input bytes processed */ 8284141cc406Sopenharmony_ci { 8285141cc406Sopenharmony_ci fputc((char) dest, fp); 8286141cc406Sopenharmony_ci dest = 0; 8287141cc406Sopenharmony_ci } 8288141cc406Sopenharmony_ci from += step; 8289141cc406Sopenharmony_ci } 8290141cc406Sopenharmony_ci 8291141cc406Sopenharmony_ci if ( bit != 0 ) 8292141cc406Sopenharmony_ci { 8293141cc406Sopenharmony_ci dest <<= 7 - bit; 8294141cc406Sopenharmony_ci fputc((char) dest, fp); 8295141cc406Sopenharmony_ci } 8296141cc406Sopenharmony_ci 8297141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 8298141cc406Sopenharmony_ci} 8299141cc406Sopenharmony_ci 8300141cc406Sopenharmony_ci/*---------- auto_adjust_proc_data() -----------------------------------------*/ 8301141cc406Sopenharmony_ci 8302141cc406Sopenharmony_cistatic SANE_Status 8303141cc406Sopenharmony_ciauto_adjust_proc_data(Microtek2_Scanner *ms, uint8_t **temp_current) 8304141cc406Sopenharmony_ci{ 8305141cc406Sopenharmony_ci Microtek2_Device *md; 8306141cc406Sopenharmony_ci Microtek2_Info *mi; 8307141cc406Sopenharmony_ci SANE_Status status; 8308141cc406Sopenharmony_ci uint8_t *from; 8309141cc406Sopenharmony_ci uint32_t line; 8310141cc406Sopenharmony_ci uint32_t lines; 8311141cc406Sopenharmony_ci uint32_t pixel; 8312141cc406Sopenharmony_ci uint32_t threshold; 8313141cc406Sopenharmony_ci int right_to_left; 8314141cc406Sopenharmony_ci 8315141cc406Sopenharmony_ci 8316141cc406Sopenharmony_ci DBG(30, "auto_adjust_proc_data: ms=%p, temp_current=%p\n", 8317141cc406Sopenharmony_ci (void *) ms, (void *) *temp_current); 8318141cc406Sopenharmony_ci 8319141cc406Sopenharmony_ci md = ms->dev; 8320141cc406Sopenharmony_ci mi = &md->info[md->scan_source]; 8321141cc406Sopenharmony_ci right_to_left = mi->direction & MI_DATSEQ_RTOL; 8322141cc406Sopenharmony_ci 8323141cc406Sopenharmony_ci memcpy(*temp_current, ms->buf.src_buf, ms->transfer_length); 8324141cc406Sopenharmony_ci *temp_current += ms->transfer_length; 8325141cc406Sopenharmony_ci threshold = 0; 8326141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 8327141cc406Sopenharmony_ci 8328141cc406Sopenharmony_ci if ( ms->src_remaining_lines == 0 ) /* we have read all the image data, */ 8329141cc406Sopenharmony_ci { /* calculate threshold value */ 8330141cc406Sopenharmony_ci for ( pixel = 0; pixel < ms->remaining_bytes; pixel++ ) 8331141cc406Sopenharmony_ci threshold += *(ms->temporary_buffer + pixel); 8332141cc406Sopenharmony_ci 8333141cc406Sopenharmony_ci threshold /= ms->remaining_bytes; 8334141cc406Sopenharmony_ci lines = ms->remaining_bytes / ms->bpl; 8335141cc406Sopenharmony_ci for ( line = 0; line < lines; line++ ) 8336141cc406Sopenharmony_ci { 8337141cc406Sopenharmony_ci from = ms->temporary_buffer + line * ms->bpl; 8338141cc406Sopenharmony_ci if ( right_to_left == 1 ) 8339141cc406Sopenharmony_ci from += ms->ppl - 1; 8340141cc406Sopenharmony_ci status = lineartfake_copy_pixels(ms, 8341141cc406Sopenharmony_ci from, 8342141cc406Sopenharmony_ci ms->ppl, 8343141cc406Sopenharmony_ci (uint8_t) threshold, 8344141cc406Sopenharmony_ci right_to_left, 8345141cc406Sopenharmony_ci ms->fp); 8346141cc406Sopenharmony_ci } 8347141cc406Sopenharmony_ci *temp_current = NULL; 8348141cc406Sopenharmony_ci } 8349141cc406Sopenharmony_ci 8350141cc406Sopenharmony_ci return status; 8351141cc406Sopenharmony_ci} 8352141cc406Sopenharmony_ci 8353141cc406Sopenharmony_ci/*-------------- get_cshading_values -----------------------------------------*/ 8354141cc406Sopenharmony_ci 8355141cc406Sopenharmony_cistatic SANE_Status 8356141cc406Sopenharmony_ciget_cshading_values(Microtek2_Scanner *ms, 8357141cc406Sopenharmony_ci uint8_t color, 8358141cc406Sopenharmony_ci uint32_t pixel, 8359141cc406Sopenharmony_ci float shading_factor, 8360141cc406Sopenharmony_ci int right_to_left, 8361141cc406Sopenharmony_ci float *s_d, 8362141cc406Sopenharmony_ci float *s_w) 8363141cc406Sopenharmony_ci{ 8364141cc406Sopenharmony_ci Microtek2_Device *md; 8365141cc406Sopenharmony_ci uint32_t csh_offset; 8366141cc406Sopenharmony_ci 8367141cc406Sopenharmony_ci md = ms->dev; 8368141cc406Sopenharmony_ci 8369141cc406Sopenharmony_ci if ( right_to_left == 1 ) 8370141cc406Sopenharmony_ci csh_offset = (color + 1) * ms->ppl - 1 - pixel; 8371141cc406Sopenharmony_ci else 8372141cc406Sopenharmony_ci csh_offset = color * ms->ppl + pixel; 8373141cc406Sopenharmony_ci 8374141cc406Sopenharmony_ci if ( ( md->shading_depth > 8 ) && ( ms->lut_entry_size == 2) ) 8375141cc406Sopenharmony_ci /* condensed shading is 2 byte color data */ 8376141cc406Sopenharmony_ci { 8377141cc406Sopenharmony_ci if ( ms->condensed_shading_d != NULL ) 8378141cc406Sopenharmony_ci *s_d = (float) *( (uint16_t *)ms->condensed_shading_d 8379141cc406Sopenharmony_ci + csh_offset ); 8380141cc406Sopenharmony_ci else 8381141cc406Sopenharmony_ci *s_d = 0.0; 8382141cc406Sopenharmony_ci 8383141cc406Sopenharmony_ci *s_w = (float) *( (uint16_t *)ms->condensed_shading_w 8384141cc406Sopenharmony_ci + csh_offset ); 8385141cc406Sopenharmony_ci *s_w /= shading_factor; 8386141cc406Sopenharmony_ci *s_d /= shading_factor; 8387141cc406Sopenharmony_ci } 8388141cc406Sopenharmony_ci 8389141cc406Sopenharmony_ci else 8390141cc406Sopenharmony_ci /* condensed shading is 8 bit data */ 8391141cc406Sopenharmony_ci { 8392141cc406Sopenharmony_ci *s_w = (float) *( ms->condensed_shading_w + csh_offset ); 8393141cc406Sopenharmony_ci if ( ms->condensed_shading_d != NULL ) 8394141cc406Sopenharmony_ci *s_d = (float) *( ms->condensed_shading_d + csh_offset ); 8395141cc406Sopenharmony_ci else 8396141cc406Sopenharmony_ci *s_d = 0.0; 8397141cc406Sopenharmony_ci } 8398141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 8399141cc406Sopenharmony_ci} 8400