1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci ScanMaker 3840 Backend 4141cc406Sopenharmony_ci Copyright (C) 2005-7 Earle F. Philhower, III 5141cc406Sopenharmony_ci earle@ziplabel.com - http://www.ziplabel.com 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 8141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 9141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 10141cc406Sopenharmony_ci License, or (at your option) any later version. 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 13141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 14141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15141cc406Sopenharmony_ci General Public License for more details. 16141cc406Sopenharmony_ci 17141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 18141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 21141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 24141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 25141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 26141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 27141cc406Sopenharmony_ci account of linking the SANE library code into it. 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 30141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 31141cc406Sopenharmony_ci License. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 34141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 35141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 38141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 39141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci*/ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci#include "../include/sane/config.h" 47141cc406Sopenharmony_ci#include <string.h> 48141cc406Sopenharmony_ci#include <stdio.h> 49141cc406Sopenharmony_ci#include <stdlib.h> 50141cc406Sopenharmony_ci#include <unistd.h> 51141cc406Sopenharmony_ci#include <ctype.h> 52141cc406Sopenharmony_ci#include <limits.h> 53141cc406Sopenharmony_ci#include <stdarg.h> 54141cc406Sopenharmony_ci#include <string.h> 55141cc406Sopenharmony_ci#include <signal.h> 56141cc406Sopenharmony_ci#include <sys/stat.h> 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#include "../include/sane/sane.h" 59141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci#define BACKENDNAME sm3840 62141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 63141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 64141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci#include "sm3840.h" 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci#include "sm3840_scan.c" 69141cc406Sopenharmony_ci#include "sm3840_lib.c" 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_cistatic double sm3840_unit_convert (SANE_Int val); 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_cistatic int num_devices; 74141cc406Sopenharmony_cistatic SM3840_Device *first_dev; 75141cc406Sopenharmony_cistatic SM3840_Scan *first_handle; 76141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] = { 79141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 80141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 81141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 82141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_HALFTONE, 83141cc406Sopenharmony_ci 0 84141cc406Sopenharmony_ci}; 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_cistatic const SANE_Word resolution_list[] = { 87141cc406Sopenharmony_ci 4, 1200, 600, 300, 150 88141cc406Sopenharmony_ci}; 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_cistatic const SANE_Word bpp_list[] = { 91141cc406Sopenharmony_ci 2, 8, 16 92141cc406Sopenharmony_ci}; 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_cistatic const SANE_Range x_range = { 95141cc406Sopenharmony_ci SANE_FIX (0), 96141cc406Sopenharmony_ci SANE_FIX (215.91), /* 8.5 inches */ 97141cc406Sopenharmony_ci SANE_FIX (0) 98141cc406Sopenharmony_ci}; 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_cistatic const SANE_Range y_range = { 101141cc406Sopenharmony_ci SANE_FIX (0), 102141cc406Sopenharmony_ci SANE_FIX (297.19), /* 11.7 inches */ 103141cc406Sopenharmony_ci SANE_FIX (0) 104141cc406Sopenharmony_ci}; 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_cistatic const SANE_Range brightness_range = { 107141cc406Sopenharmony_ci 1, 108141cc406Sopenharmony_ci 4096, 109141cc406Sopenharmony_ci 1.0 110141cc406Sopenharmony_ci}; 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_cistatic const SANE_Range contrast_range = { 113141cc406Sopenharmony_ci SANE_FIX (0.1), 114141cc406Sopenharmony_ci SANE_FIX (9.9), 115141cc406Sopenharmony_ci SANE_FIX (0.1) 116141cc406Sopenharmony_ci}; 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_cistatic const SANE_Range lamp_range = { 119141cc406Sopenharmony_ci 1, 120141cc406Sopenharmony_ci 15, 121141cc406Sopenharmony_ci 1 122141cc406Sopenharmony_ci}; 123141cc406Sopenharmony_ci 124141cc406Sopenharmony_cistatic const SANE_Range threshold_range = { 125141cc406Sopenharmony_ci 0, 126141cc406Sopenharmony_ci 255, 127141cc406Sopenharmony_ci 1 128141cc406Sopenharmony_ci}; 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 131141cc406Sopenharmony_cistatic int 132141cc406Sopenharmony_cimin (int a, int b) 133141cc406Sopenharmony_ci{ 134141cc406Sopenharmony_ci if (a < b) 135141cc406Sopenharmony_ci return a; 136141cc406Sopenharmony_ci else 137141cc406Sopenharmony_ci return b; 138141cc406Sopenharmony_ci} 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_ciSANE_Status 141141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 142141cc406Sopenharmony_ci SANE_Int * len) 143141cc406Sopenharmony_ci{ 144141cc406Sopenharmony_ci SM3840_Scan *s = handle; 145141cc406Sopenharmony_ci unsigned char c, d; 146141cc406Sopenharmony_ci int i; 147141cc406Sopenharmony_ci 148141cc406Sopenharmony_ci DBG (2, "+sane-read:%p %p %d %p\n", (void *) s, (void *) buf, max_len, 149141cc406Sopenharmony_ci (void *) len); 150141cc406Sopenharmony_ci DBG (2, 151141cc406Sopenharmony_ci "+sane-read:remain:%lu offset:%lu linesleft:%d linebuff:%p linesread:%d\n", 152141cc406Sopenharmony_ci (u_long) s->remaining, (u_long) s->offset, s->linesleft, 153141cc406Sopenharmony_ci (void *) s->line_buffer, s->linesread); 154141cc406Sopenharmony_ci 155141cc406Sopenharmony_ci if (!s->scanning) 156141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 157141cc406Sopenharmony_ci 158141cc406Sopenharmony_ci if (!s->remaining) 159141cc406Sopenharmony_ci { 160141cc406Sopenharmony_ci if (!s->linesleft) 161141cc406Sopenharmony_ci { 162141cc406Sopenharmony_ci *len = 0; 163141cc406Sopenharmony_ci s->scanning = 0; 164141cc406Sopenharmony_ci /* Move to home position */ 165141cc406Sopenharmony_ci reset_scanner ((p_usb_dev_handle)s->udev); 166141cc406Sopenharmony_ci /* Send lamp timeout */ 167141cc406Sopenharmony_ci set_lamp_timer ((p_usb_dev_handle)s->udev, s->sm3840_params.lamp); 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci /* Free memory */ 170141cc406Sopenharmony_ci if (s->save_scan_line) 171141cc406Sopenharmony_ci free (s->save_scan_line); 172141cc406Sopenharmony_ci s->save_scan_line = NULL; 173141cc406Sopenharmony_ci if (s->save_dpi1200_remap) 174141cc406Sopenharmony_ci free (s->save_dpi1200_remap); 175141cc406Sopenharmony_ci s->save_dpi1200_remap = NULL; 176141cc406Sopenharmony_ci if (s->save_color_remap) 177141cc406Sopenharmony_ci free (s->save_color_remap); 178141cc406Sopenharmony_ci s->save_color_remap = NULL; 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_ci return SANE_STATUS_EOF; 181141cc406Sopenharmony_ci } 182141cc406Sopenharmony_ci 183141cc406Sopenharmony_ci record_line ((s->linesread == 0) ? 1 : 0, 184141cc406Sopenharmony_ci (p_usb_dev_handle) s->udev, 185141cc406Sopenharmony_ci s->line_buffer, 186141cc406Sopenharmony_ci s->sm3840_params.dpi, 187141cc406Sopenharmony_ci s->sm3840_params.scanpix, 188141cc406Sopenharmony_ci s->sm3840_params.gray, 189141cc406Sopenharmony_ci (s->sm3840_params.bpp == 16) ? 1 : 0, 190141cc406Sopenharmony_ci &s->save_i, 191141cc406Sopenharmony_ci &s->save_scan_line, 192141cc406Sopenharmony_ci &s->save_dpi1200_remap, &s->save_color_remap); 193141cc406Sopenharmony_ci s->remaining = s->sm3840_params.linelen; 194141cc406Sopenharmony_ci s->offset = 0; 195141cc406Sopenharmony_ci s->linesread++; 196141cc406Sopenharmony_ci s->linesleft--; 197141cc406Sopenharmony_ci } 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci /* Need to software emulate 1-bpp modes, simple threshold and error */ 200141cc406Sopenharmony_ci /* diffusion dither implemented. */ 201141cc406Sopenharmony_ci if (s->sm3840_params.lineart || s->sm3840_params.halftone) 202141cc406Sopenharmony_ci { 203141cc406Sopenharmony_ci d = 0; 204141cc406Sopenharmony_ci for (i = 0; i < min (max_len * 8, s->remaining); i++) 205141cc406Sopenharmony_ci { 206141cc406Sopenharmony_ci d = d << 1; 207141cc406Sopenharmony_ci if (s->sm3840_params.halftone) 208141cc406Sopenharmony_ci { 209141cc406Sopenharmony_ci c = (*(unsigned char *) (s->offset + s->line_buffer + i)); 210141cc406Sopenharmony_ci if (c + s->save_dither_err < 128) 211141cc406Sopenharmony_ci { 212141cc406Sopenharmony_ci d |= 1; 213141cc406Sopenharmony_ci s->save_dither_err += c; 214141cc406Sopenharmony_ci } 215141cc406Sopenharmony_ci else 216141cc406Sopenharmony_ci { 217141cc406Sopenharmony_ci s->save_dither_err += c - 255; 218141cc406Sopenharmony_ci } 219141cc406Sopenharmony_ci } 220141cc406Sopenharmony_ci else 221141cc406Sopenharmony_ci { 222141cc406Sopenharmony_ci if ((*(unsigned char *) (s->offset + s->line_buffer + i)) < s->threshold ) 223141cc406Sopenharmony_ci d |= 1; 224141cc406Sopenharmony_ci } 225141cc406Sopenharmony_ci if (i % 8 == 7) 226141cc406Sopenharmony_ci *(buf++) = d; 227141cc406Sopenharmony_ci } 228141cc406Sopenharmony_ci *len = i / 8; 229141cc406Sopenharmony_ci s->offset += i; 230141cc406Sopenharmony_ci s->remaining -= i; 231141cc406Sopenharmony_ci } 232141cc406Sopenharmony_ci else 233141cc406Sopenharmony_ci { 234141cc406Sopenharmony_ci memcpy (buf, s->offset + s->line_buffer, min (max_len, s->remaining)); 235141cc406Sopenharmony_ci *len = min (max_len, s->remaining); 236141cc406Sopenharmony_ci s->offset += min (max_len, s->remaining); 237141cc406Sopenharmony_ci s->remaining -= min (max_len, s->remaining); 238141cc406Sopenharmony_ci } 239141cc406Sopenharmony_ci 240141cc406Sopenharmony_ci DBG (2, "-sane_read\n"); 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 243141cc406Sopenharmony_ci} 244141cc406Sopenharmony_ci 245141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 246141cc406Sopenharmony_civoid 247141cc406Sopenharmony_cisane_cancel (SANE_Handle h) 248141cc406Sopenharmony_ci{ 249141cc406Sopenharmony_ci SM3840_Scan *s = h; 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci DBG (2, "trying to cancel...\n"); 252141cc406Sopenharmony_ci if (s->scanning) 253141cc406Sopenharmony_ci { 254141cc406Sopenharmony_ci if (!s->cancelled) 255141cc406Sopenharmony_ci { 256141cc406Sopenharmony_ci /* Move to home position */ 257141cc406Sopenharmony_ci reset_scanner ((p_usb_dev_handle) s->udev); 258141cc406Sopenharmony_ci /* Send lamp timeout */ 259141cc406Sopenharmony_ci set_lamp_timer ((p_usb_dev_handle) s->udev, s->sm3840_params.lamp); 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci /* Free memory */ 262141cc406Sopenharmony_ci if (s->save_scan_line) 263141cc406Sopenharmony_ci free (s->save_scan_line); 264141cc406Sopenharmony_ci s->save_scan_line = NULL; 265141cc406Sopenharmony_ci if (s->save_dpi1200_remap) 266141cc406Sopenharmony_ci free (s->save_dpi1200_remap); 267141cc406Sopenharmony_ci s->save_dpi1200_remap = NULL; 268141cc406Sopenharmony_ci if (s->save_color_remap) 269141cc406Sopenharmony_ci free (s->save_color_remap); 270141cc406Sopenharmony_ci s->save_color_remap = NULL; 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_ci s->scanning = 0; 273141cc406Sopenharmony_ci s->cancelled = SANE_TRUE; 274141cc406Sopenharmony_ci } 275141cc406Sopenharmony_ci } 276141cc406Sopenharmony_ci} 277141cc406Sopenharmony_ci 278141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 279141cc406Sopenharmony_ciSANE_Status 280141cc406Sopenharmony_cisane_start (SANE_Handle handle) 281141cc406Sopenharmony_ci{ 282141cc406Sopenharmony_ci SM3840_Scan *s = handle; 283141cc406Sopenharmony_ci SANE_Status status; 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci /* First make sure we have a current parameter set. Some of the 286141cc406Sopenharmony_ci * parameters will be overwritten below, but that's OK. */ 287141cc406Sopenharmony_ci DBG (2, "sane_start\n"); 288141cc406Sopenharmony_ci status = sane_get_parameters (s, 0); 289141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 290141cc406Sopenharmony_ci return status; 291141cc406Sopenharmony_ci DBG (1, "Got params again...\n"); 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 294141cc406Sopenharmony_ci s->cancelled = 0; 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci s->line_buffer = malloc (s->sm3840_params.linelen); 297141cc406Sopenharmony_ci s->remaining = 0; 298141cc406Sopenharmony_ci s->offset = 0; 299141cc406Sopenharmony_ci s->linesleft = s->sm3840_params.scanlines; 300141cc406Sopenharmony_ci s->linesread = 0; 301141cc406Sopenharmony_ci 302141cc406Sopenharmony_ci s->save_i = 0; 303141cc406Sopenharmony_ci s->save_scan_line = NULL; 304141cc406Sopenharmony_ci s->save_dpi1200_remap = NULL; 305141cc406Sopenharmony_ci s->save_color_remap = NULL; 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci s->save_dither_err = 0; 308141cc406Sopenharmony_ci s->threshold = s->sm3840_params.threshold; 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci setup_scan ((p_usb_dev_handle) s->udev, &(s->sm3840_params)); 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 313141cc406Sopenharmony_ci} 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_cistatic double 316141cc406Sopenharmony_cism3840_unit_convert (SANE_Int val) 317141cc406Sopenharmony_ci{ 318141cc406Sopenharmony_ci double d; 319141cc406Sopenharmony_ci d = SANE_UNFIX (val); 320141cc406Sopenharmony_ci d /= MM_PER_INCH; 321141cc406Sopenharmony_ci return d; 322141cc406Sopenharmony_ci} 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 325141cc406Sopenharmony_ciSANE_Status 326141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 327141cc406Sopenharmony_ci{ 328141cc406Sopenharmony_ci SM3840_Scan *s = handle; 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci DBG (2, "sane_get_parameters\n"); 331141cc406Sopenharmony_ci if (!s->scanning) 332141cc406Sopenharmony_ci { 333141cc406Sopenharmony_ci memset (&s->sane_params, 0, sizeof (s->sane_params)); 334141cc406Sopenharmony_ci /* Copy from options to sm3840_params */ 335141cc406Sopenharmony_ci s->sm3840_params.gray = 336141cc406Sopenharmony_ci (!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) ? 1 : 0; 337141cc406Sopenharmony_ci s->sm3840_params.halftone = 338141cc406Sopenharmony_ci (!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_HALFTONE)) ? 1 : 0; 339141cc406Sopenharmony_ci s->sm3840_params.lineart = 340141cc406Sopenharmony_ci (!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) ? 1 : 0; 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci s->sm3840_params.dpi = s->value[OPT_RESOLUTION].w; 343141cc406Sopenharmony_ci s->sm3840_params.bpp = s->value[OPT_BIT_DEPTH].w; 344141cc406Sopenharmony_ci s->sm3840_params.gain = SANE_UNFIX (s->value[OPT_CONTRAST].w); 345141cc406Sopenharmony_ci s->sm3840_params.offset = s->value[OPT_BRIGHTNESS].w; 346141cc406Sopenharmony_ci s->sm3840_params.lamp = s->value[OPT_LAMP_TIMEOUT].w; 347141cc406Sopenharmony_ci s->sm3840_params.threshold = s->value[OPT_THRESHOLD].w; 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_ci if (s->sm3840_params.lineart || s->sm3840_params.halftone) 350141cc406Sopenharmony_ci { 351141cc406Sopenharmony_ci s->sm3840_params.gray = 1; 352141cc406Sopenharmony_ci s->sm3840_params.bpp = 8; 353141cc406Sopenharmony_ci } 354141cc406Sopenharmony_ci 355141cc406Sopenharmony_ci s->sm3840_params.top = sm3840_unit_convert (s->value[OPT_TL_Y].w); 356141cc406Sopenharmony_ci s->sm3840_params.left = sm3840_unit_convert (s->value[OPT_TL_X].w); 357141cc406Sopenharmony_ci s->sm3840_params.width = 358141cc406Sopenharmony_ci sm3840_unit_convert (s->value[OPT_BR_X].w) - s->sm3840_params.left; 359141cc406Sopenharmony_ci s->sm3840_params.height = 360141cc406Sopenharmony_ci sm3840_unit_convert (s->value[OPT_BR_Y].w) - s->sm3840_params.top; 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci /* Legalize and calculate pixel sizes */ 363141cc406Sopenharmony_ci prepare_params (&(s->sm3840_params)); 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci /* Copy into sane_params */ 366141cc406Sopenharmony_ci s->sane_params.pixels_per_line = s->sm3840_params.scanpix; 367141cc406Sopenharmony_ci s->sane_params.lines = s->sm3840_params.scanlines; 368141cc406Sopenharmony_ci s->sane_params.format = 369141cc406Sopenharmony_ci s->sm3840_params.gray ? SANE_FRAME_GRAY : SANE_FRAME_RGB; 370141cc406Sopenharmony_ci s->sane_params.bytes_per_line = s->sm3840_params.linelen; 371141cc406Sopenharmony_ci s->sane_params.depth = s->sm3840_params.bpp; 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci if (s->sm3840_params.lineart || s->sm3840_params.halftone) 374141cc406Sopenharmony_ci { 375141cc406Sopenharmony_ci s->sane_params.bytes_per_line += 7; 376141cc406Sopenharmony_ci s->sane_params.bytes_per_line /= 8; 377141cc406Sopenharmony_ci s->sane_params.depth = 1; 378141cc406Sopenharmony_ci s->sane_params.pixels_per_line = s->sane_params.bytes_per_line * 8; 379141cc406Sopenharmony_ci } 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci s->sane_params.last_frame = SANE_TRUE; 382141cc406Sopenharmony_ci } /*!scanning */ 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci if (params) 385141cc406Sopenharmony_ci *params = s->sane_params; 386141cc406Sopenharmony_ci 387141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 388141cc406Sopenharmony_ci} 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 391141cc406Sopenharmony_ciSANE_Status 392141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 393141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 394141cc406Sopenharmony_ci{ 395141cc406Sopenharmony_ci SM3840_Scan *s = handle; 396141cc406Sopenharmony_ci SANE_Status status = 0; 397141cc406Sopenharmony_ci SANE_Word cap; 398141cc406Sopenharmony_ci DBG (2, "sane_control_option\n"); 399141cc406Sopenharmony_ci if (info) 400141cc406Sopenharmony_ci *info = 0; 401141cc406Sopenharmony_ci if (s->scanning) 402141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 403141cc406Sopenharmony_ci if (option >= NUM_OPTIONS) 404141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 405141cc406Sopenharmony_ci cap = s->options_list[option].cap; 406141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 407141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 408141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 409141cc406Sopenharmony_ci { 410141cc406Sopenharmony_ci DBG (1, "sane_control_option %d, get value\n", option); 411141cc406Sopenharmony_ci switch (option) 412141cc406Sopenharmony_ci { 413141cc406Sopenharmony_ci /* word options: */ 414141cc406Sopenharmony_ci case OPT_RESOLUTION: 415141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 416141cc406Sopenharmony_ci case OPT_TL_X: 417141cc406Sopenharmony_ci case OPT_TL_Y: 418141cc406Sopenharmony_ci case OPT_BR_X: 419141cc406Sopenharmony_ci case OPT_BR_Y: 420141cc406Sopenharmony_ci case OPT_NUM_OPTS: 421141cc406Sopenharmony_ci case OPT_CONTRAST: 422141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 423141cc406Sopenharmony_ci case OPT_LAMP_TIMEOUT: 424141cc406Sopenharmony_ci case OPT_THRESHOLD: 425141cc406Sopenharmony_ci *(SANE_Word *) val = s->value[option].w; 426141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 427141cc406Sopenharmony_ci /* string options: */ 428141cc406Sopenharmony_ci case OPT_MODE: 429141cc406Sopenharmony_ci strcpy (val, s->value[option].s); 430141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 431141cc406Sopenharmony_ci } 432141cc406Sopenharmony_ci } 433141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 434141cc406Sopenharmony_ci { 435141cc406Sopenharmony_ci DBG (1, "sane_control_option %d, set value\n", option); 436141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 437141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 438141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 439141cc406Sopenharmony_ci return (status); 440141cc406Sopenharmony_ci status = sanei_constrain_value (s->options_list + option, val, info); 441141cc406Sopenharmony_ci switch (option) 442141cc406Sopenharmony_ci { 443141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 444141cc406Sopenharmony_ci case OPT_RESOLUTION: 445141cc406Sopenharmony_ci case OPT_BIT_DEPTH: 446141cc406Sopenharmony_ci case OPT_BR_X: 447141cc406Sopenharmony_ci case OPT_BR_Y: 448141cc406Sopenharmony_ci case OPT_TL_X: 449141cc406Sopenharmony_ci case OPT_TL_Y: 450141cc406Sopenharmony_ci if (info) 451141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 452141cc406Sopenharmony_ci /* fall through */ 453141cc406Sopenharmony_ci case OPT_NUM_OPTS: 454141cc406Sopenharmony_ci case OPT_CONTRAST: 455141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 456141cc406Sopenharmony_ci case OPT_LAMP_TIMEOUT: 457141cc406Sopenharmony_ci case OPT_THRESHOLD: 458141cc406Sopenharmony_ci s->value[option].w = *(SANE_Word *) val; 459141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 460141cc406Sopenharmony_ci case OPT_MODE: 461141cc406Sopenharmony_ci if (s->value[option].s) 462141cc406Sopenharmony_ci free (s->value[option].s); 463141cc406Sopenharmony_ci s->value[option].s = strdup (val); 464141cc406Sopenharmony_ci 465141cc406Sopenharmony_ci if (info) 466141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 467141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 468141cc406Sopenharmony_ci } 469141cc406Sopenharmony_ci } 470141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 471141cc406Sopenharmony_ci} 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 474141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 475141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 476141cc406Sopenharmony_ci{ 477141cc406Sopenharmony_ci SM3840_Scan *s = handle; 478141cc406Sopenharmony_ci DBG (2, "sane_get_option_descriptor\n"); 479141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 480141cc406Sopenharmony_ci return (0); 481141cc406Sopenharmony_ci return (&s->options_list[option]); 482141cc406Sopenharmony_ci} 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_civoid 487141cc406Sopenharmony_cisane_close (SANE_Handle handle) 488141cc406Sopenharmony_ci{ 489141cc406Sopenharmony_ci SM3840_Scan *prev, *s; 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_ci DBG (2, "sane_close\n"); 492141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 493141cc406Sopenharmony_ci prev = 0; 494141cc406Sopenharmony_ci for (s = first_handle; s; s = s->next) 495141cc406Sopenharmony_ci { 496141cc406Sopenharmony_ci if (s == handle) 497141cc406Sopenharmony_ci break; 498141cc406Sopenharmony_ci prev = s; 499141cc406Sopenharmony_ci } 500141cc406Sopenharmony_ci if (!s) 501141cc406Sopenharmony_ci { 502141cc406Sopenharmony_ci DBG (1, "close: invalid handle %p\n", handle); 503141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 504141cc406Sopenharmony_ci } 505141cc406Sopenharmony_ci 506141cc406Sopenharmony_ci if (s->scanning) 507141cc406Sopenharmony_ci { 508141cc406Sopenharmony_ci sane_cancel (handle); 509141cc406Sopenharmony_ci } 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci sanei_usb_close (s->udev); 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci if (s->line_buffer) 514141cc406Sopenharmony_ci free (s->line_buffer); 515141cc406Sopenharmony_ci if (s->save_scan_line) 516141cc406Sopenharmony_ci free (s->save_scan_line); 517141cc406Sopenharmony_ci if (s->save_dpi1200_remap) 518141cc406Sopenharmony_ci free (s->save_dpi1200_remap); 519141cc406Sopenharmony_ci if (s->save_color_remap) 520141cc406Sopenharmony_ci free (s->save_color_remap); 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci if (prev) 523141cc406Sopenharmony_ci prev->next = s->next; 524141cc406Sopenharmony_ci else 525141cc406Sopenharmony_ci first_handle = s; 526141cc406Sopenharmony_ci free (handle); 527141cc406Sopenharmony_ci} 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 530141cc406Sopenharmony_civoid 531141cc406Sopenharmony_cisane_exit (void) 532141cc406Sopenharmony_ci{ 533141cc406Sopenharmony_ci SM3840_Device *next; 534141cc406Sopenharmony_ci DBG (2, "sane_exit\n"); 535141cc406Sopenharmony_ci while (first_dev != NULL) 536141cc406Sopenharmony_ci { 537141cc406Sopenharmony_ci next = first_dev->next; 538141cc406Sopenharmony_ci free (first_dev); 539141cc406Sopenharmony_ci first_dev = next; 540141cc406Sopenharmony_ci } 541141cc406Sopenharmony_ci if (devlist) 542141cc406Sopenharmony_ci free (devlist); 543141cc406Sopenharmony_ci} 544141cc406Sopenharmony_ci 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_ci 547141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 548141cc406Sopenharmony_ciSANE_Status 549141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 550141cc406Sopenharmony_ci{ 551141cc406Sopenharmony_ci DBG_INIT (); 552141cc406Sopenharmony_ci if (version_code) 553141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 554141cc406Sopenharmony_ci if (authorize) 555141cc406Sopenharmony_ci DBG (2, "Unused authorize\n"); 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci sanei_usb_init (); 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 560141cc406Sopenharmony_ci} 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci 565141cc406Sopenharmony_cistatic SANE_Status 566141cc406Sopenharmony_ciadd_sm_device (SANE_String_Const devname, SANE_String_Const modname) 567141cc406Sopenharmony_ci{ 568141cc406Sopenharmony_ci SM3840_Device *dev; 569141cc406Sopenharmony_ci 570141cc406Sopenharmony_ci dev = calloc (sizeof (*dev), 1); 571141cc406Sopenharmony_ci if (!dev) 572141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 575141cc406Sopenharmony_ci dev->sane.name = strdup (devname); 576141cc406Sopenharmony_ci dev->sane.model = modname; 577141cc406Sopenharmony_ci dev->sane.vendor = "Microtek"; 578141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 579141cc406Sopenharmony_ci ++num_devices; 580141cc406Sopenharmony_ci dev->next = first_dev; 581141cc406Sopenharmony_ci first_dev = dev; 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 584141cc406Sopenharmony_ci} 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_cistatic SANE_Status 587141cc406Sopenharmony_ciadd_sm3840_device (SANE_String_Const devname) 588141cc406Sopenharmony_ci{ 589141cc406Sopenharmony_ci return add_sm_device (devname, "ScanMaker 3840"); 590141cc406Sopenharmony_ci} 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_cistatic SANE_Status 593141cc406Sopenharmony_ciadd_sm4800_device (SANE_String_Const devname) 594141cc406Sopenharmony_ci{ 595141cc406Sopenharmony_ci return add_sm_device (devname, "ScanMaker 4800"); 596141cc406Sopenharmony_ci} 597141cc406Sopenharmony_ci 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 600141cc406Sopenharmony_ciSANE_Status 601141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 602141cc406Sopenharmony_ci{ 603141cc406Sopenharmony_ci static const SANE_Device **devlist = 0; 604141cc406Sopenharmony_ci SM3840_Device *dev; 605141cc406Sopenharmony_ci int i; 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci DBG (3, "sane_get_devices (local_only = %d)\n", local_only); 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci while (first_dev) 610141cc406Sopenharmony_ci { 611141cc406Sopenharmony_ci dev = first_dev->next; 612141cc406Sopenharmony_ci free (first_dev); 613141cc406Sopenharmony_ci first_dev = dev; 614141cc406Sopenharmony_ci } 615141cc406Sopenharmony_ci first_dev = NULL; 616141cc406Sopenharmony_ci num_devices = 0; 617141cc406Sopenharmony_ci 618141cc406Sopenharmony_ci /* If we get enough scanners should use an array, but for now */ 619141cc406Sopenharmony_ci /* do it one-by-one... */ 620141cc406Sopenharmony_ci sanei_usb_find_devices (0x05da, 0x30d4, add_sm3840_device); 621141cc406Sopenharmony_ci sanei_usb_find_devices (0x05da, 0x30cf, add_sm4800_device); 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci if (devlist) 624141cc406Sopenharmony_ci free (devlist); 625141cc406Sopenharmony_ci devlist = calloc ((num_devices + 1) * sizeof (devlist[0]), 1); 626141cc406Sopenharmony_ci if (!devlist) 627141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 628141cc406Sopenharmony_ci i = 0; 629141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 630141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 631141cc406Sopenharmony_ci devlist[i++] = 0; 632141cc406Sopenharmony_ci if (device_list) 633141cc406Sopenharmony_ci *device_list = devlist; 634141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 635141cc406Sopenharmony_ci} 636141cc406Sopenharmony_ci 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_cistatic size_t 641141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 642141cc406Sopenharmony_ci{ 643141cc406Sopenharmony_ci size_t size, max_size = 0; 644141cc406Sopenharmony_ci int i; 645141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 646141cc406Sopenharmony_ci { 647141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 648141cc406Sopenharmony_ci if (size > max_size) 649141cc406Sopenharmony_ci max_size = size; 650141cc406Sopenharmony_ci } 651141cc406Sopenharmony_ci 652141cc406Sopenharmony_ci return (max_size); 653141cc406Sopenharmony_ci} 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_cistatic void 658141cc406Sopenharmony_ciinitialize_options_list (SM3840_Scan * s) 659141cc406Sopenharmony_ci{ 660141cc406Sopenharmony_ci 661141cc406Sopenharmony_ci SANE_Int option; 662141cc406Sopenharmony_ci DBG (2, "initialize_options_list\n"); 663141cc406Sopenharmony_ci for (option = 0; option < NUM_OPTIONS; ++option) 664141cc406Sopenharmony_ci { 665141cc406Sopenharmony_ci s->options_list[option].size = sizeof (SANE_Word); 666141cc406Sopenharmony_ci s->options_list[option].cap = 667141cc406Sopenharmony_ci SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 668141cc406Sopenharmony_ci } 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 671141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 672141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 673141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].type = SANE_TYPE_INT; 674141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; 675141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].size = sizeof (SANE_Word); 676141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 677141cc406Sopenharmony_ci s->options_list[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; 678141cc406Sopenharmony_ci s->value[OPT_NUM_OPTS].w = NUM_OPTIONS; 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci s->options_list[OPT_MODE].name = SANE_NAME_SCAN_MODE; 681141cc406Sopenharmony_ci s->options_list[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 682141cc406Sopenharmony_ci s->options_list[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 683141cc406Sopenharmony_ci s->options_list[OPT_MODE].type = SANE_TYPE_STRING; 684141cc406Sopenharmony_ci s->options_list[OPT_MODE].size = max_string_size (mode_list); 685141cc406Sopenharmony_ci s->options_list[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 686141cc406Sopenharmony_ci s->options_list[OPT_MODE].constraint.string_list = mode_list; 687141cc406Sopenharmony_ci s->value[OPT_MODE].s = strdup (mode_list[1]); 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 690141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 691141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 692141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].type = SANE_TYPE_INT; 693141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 694141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 695141cc406Sopenharmony_ci s->options_list[OPT_RESOLUTION].constraint.word_list = resolution_list; 696141cc406Sopenharmony_ci s->value[OPT_RESOLUTION].w = 300; 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci s->options_list[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; 699141cc406Sopenharmony_ci s->options_list[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; 700141cc406Sopenharmony_ci s->options_list[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; 701141cc406Sopenharmony_ci s->options_list[OPT_BIT_DEPTH].type = SANE_TYPE_INT; 702141cc406Sopenharmony_ci s->options_list[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE; 703141cc406Sopenharmony_ci s->options_list[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; 704141cc406Sopenharmony_ci s->options_list[OPT_BIT_DEPTH].constraint.word_list = bpp_list; 705141cc406Sopenharmony_ci s->value[OPT_BIT_DEPTH].w = 8; 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci s->options_list[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 708141cc406Sopenharmony_ci s->options_list[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 709141cc406Sopenharmony_ci s->options_list[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 710141cc406Sopenharmony_ci s->options_list[OPT_TL_X].type = SANE_TYPE_FIXED; 711141cc406Sopenharmony_ci s->options_list[OPT_TL_X].unit = SANE_UNIT_MM; 712141cc406Sopenharmony_ci s->options_list[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 713141cc406Sopenharmony_ci s->options_list[OPT_TL_X].constraint.range = &x_range; 714141cc406Sopenharmony_ci s->value[OPT_TL_X].w = s->options_list[OPT_TL_X].constraint.range->min; 715141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 716141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 717141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 718141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].type = SANE_TYPE_FIXED; 719141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].unit = SANE_UNIT_MM; 720141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 721141cc406Sopenharmony_ci s->options_list[OPT_TL_Y].constraint.range = &y_range; 722141cc406Sopenharmony_ci s->value[OPT_TL_Y].w = s->options_list[OPT_TL_Y].constraint.range->min; 723141cc406Sopenharmony_ci s->options_list[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 724141cc406Sopenharmony_ci s->options_list[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 725141cc406Sopenharmony_ci s->options_list[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 726141cc406Sopenharmony_ci s->options_list[OPT_BR_X].type = SANE_TYPE_FIXED; 727141cc406Sopenharmony_ci s->options_list[OPT_BR_X].unit = SANE_UNIT_MM; 728141cc406Sopenharmony_ci s->options_list[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 729141cc406Sopenharmony_ci s->options_list[OPT_BR_X].constraint.range = &x_range; 730141cc406Sopenharmony_ci s->value[OPT_BR_X].w = s->options_list[OPT_BR_X].constraint.range->max; 731141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 732141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 733141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 734141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].type = SANE_TYPE_FIXED; 735141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].unit = SANE_UNIT_MM; 736141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 737141cc406Sopenharmony_ci s->options_list[OPT_BR_Y].constraint.range = &y_range; 738141cc406Sopenharmony_ci s->value[OPT_BR_Y].w = s->options_list[OPT_BR_Y].constraint.range->max; 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 741141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 742141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 743141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].type = SANE_TYPE_FIXED; 744141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].unit = SANE_UNIT_NONE; 745141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 746141cc406Sopenharmony_ci s->options_list[OPT_CONTRAST].constraint.range = &contrast_range; 747141cc406Sopenharmony_ci s->value[OPT_CONTRAST].w = SANE_FIX (3.5); 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 750141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 751141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 752141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 753141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 754141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 755141cc406Sopenharmony_ci s->options_list[OPT_BRIGHTNESS].constraint.range = &brightness_range; 756141cc406Sopenharmony_ci s->value[OPT_BRIGHTNESS].w = 1800; 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_ci s->options_list[OPT_LAMP_TIMEOUT].name = "lamp-timeout"; 759141cc406Sopenharmony_ci s->options_list[OPT_LAMP_TIMEOUT].title = SANE_I18N ("Lamp timeout"); 760141cc406Sopenharmony_ci s->options_list[OPT_LAMP_TIMEOUT].desc = 761141cc406Sopenharmony_ci SANE_I18N ("Minutes until lamp is turned off after scan"); 762141cc406Sopenharmony_ci s->options_list[OPT_LAMP_TIMEOUT].type = SANE_TYPE_INT; 763141cc406Sopenharmony_ci s->options_list[OPT_LAMP_TIMEOUT].unit = SANE_UNIT_NONE; 764141cc406Sopenharmony_ci s->options_list[OPT_LAMP_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE; 765141cc406Sopenharmony_ci s->options_list[OPT_LAMP_TIMEOUT].constraint.range = &lamp_range; 766141cc406Sopenharmony_ci s->value[OPT_LAMP_TIMEOUT].w = 15; 767141cc406Sopenharmony_ci 768141cc406Sopenharmony_ci s->options_list[OPT_THRESHOLD].name = "threshold"; 769141cc406Sopenharmony_ci s->options_list[OPT_THRESHOLD].title = SANE_I18N ("Threshold"); 770141cc406Sopenharmony_ci s->options_list[OPT_THRESHOLD].desc = 771141cc406Sopenharmony_ci SANE_I18N ("Threshold value for lineart mode"); 772141cc406Sopenharmony_ci s->options_list[OPT_THRESHOLD].type = SANE_TYPE_INT; 773141cc406Sopenharmony_ci s->options_list[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 774141cc406Sopenharmony_ci s->options_list[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 775141cc406Sopenharmony_ci s->options_list[OPT_THRESHOLD].constraint.range = &threshold_range; 776141cc406Sopenharmony_ci s->value[OPT_THRESHOLD].w = 128; 777141cc406Sopenharmony_ci 778141cc406Sopenharmony_ci} 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 781141cc406Sopenharmony_ciSANE_Status 782141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 783141cc406Sopenharmony_ci{ 784141cc406Sopenharmony_ci SANE_Status status; 785141cc406Sopenharmony_ci SM3840_Device *dev; 786141cc406Sopenharmony_ci SM3840_Scan *s; 787141cc406Sopenharmony_ci DBG (2, "sane_open\n"); 788141cc406Sopenharmony_ci 789141cc406Sopenharmony_ci /* Make sure we have first_dev */ 790141cc406Sopenharmony_ci sane_get_devices (NULL, 0); 791141cc406Sopenharmony_ci if (devicename[0]) 792141cc406Sopenharmony_ci { 793141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 794141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 795141cc406Sopenharmony_ci break; 796141cc406Sopenharmony_ci } 797141cc406Sopenharmony_ci else 798141cc406Sopenharmony_ci { 799141cc406Sopenharmony_ci /* empty devicename -> use first device */ 800141cc406Sopenharmony_ci dev = first_dev; 801141cc406Sopenharmony_ci } 802141cc406Sopenharmony_ci DBG (2, "using device: %s %p\n", dev->sane.name, (void *) dev); 803141cc406Sopenharmony_ci if (!dev) 804141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 805141cc406Sopenharmony_ci s = calloc (sizeof (*s), 1); 806141cc406Sopenharmony_ci if (!s) 807141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 808141cc406Sopenharmony_ci 809141cc406Sopenharmony_ci status = sanei_usb_open (dev->sane.name, &(s->udev)); 810141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 811141cc406Sopenharmony_ci return status; 812141cc406Sopenharmony_ci 813141cc406Sopenharmony_ci initialize_options_list (s); 814141cc406Sopenharmony_ci s->scanning = 0; 815141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles: */ 816141cc406Sopenharmony_ci s->next = first_handle; 817141cc406Sopenharmony_ci first_handle = s; 818141cc406Sopenharmony_ci *handle = s; 819141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 820141cc406Sopenharmony_ci} 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 823141cc406Sopenharmony_ciSANE_Status 824141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 825141cc406Sopenharmony_ci{ 826141cc406Sopenharmony_ci SM3840_Scan *s = handle; 827141cc406Sopenharmony_ci DBG (2, "sane_set_io_mode( %p, %d )\n", handle, non_blocking); 828141cc406Sopenharmony_ci if (s->scanning) 829141cc406Sopenharmony_ci { 830141cc406Sopenharmony_ci if (non_blocking == SANE_FALSE) 831141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 832141cc406Sopenharmony_ci else 833141cc406Sopenharmony_ci return (SANE_STATUS_UNSUPPORTED); 834141cc406Sopenharmony_ci } 835141cc406Sopenharmony_ci else 836141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 837141cc406Sopenharmony_ci} 838141cc406Sopenharmony_ci 839141cc406Sopenharmony_ci/*---------------------------------------------------------------------------*/ 840141cc406Sopenharmony_ciSANE_Status 841141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 842141cc406Sopenharmony_ci{ 843141cc406Sopenharmony_ci DBG (2, "sane_get_select_fd( %p, %p )\n", (void *) handle, (void *) fd); 844141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 845141cc406Sopenharmony_ci} 846