1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 1997-2005, 2013 Franck Schnefra, Michel Roelofs, 4141cc406Sopenharmony_ci Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, 5141cc406Sopenharmony_ci Simon Munton, Petter Reinholdtsen, Gary Plewa, Sebastien Sable, 6141cc406Sopenharmony_ci Mikael Magnusson, Max Ushakov, Andrew Goodbody, Oliver Schwartz 7141cc406Sopenharmony_ci and Kevin Charter 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 This file is a component of the implementation of a backend for many 46141cc406Sopenharmony_ci of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. 47141cc406Sopenharmony_ci*/ 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci/* 50141cc406Sopenharmony_ci SANE SnapScan backend 51141cc406Sopenharmony_ci*/ 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci#include "../include/sane/config.h" 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci#include <errno.h> 56141cc406Sopenharmony_ci#include <fcntl.h> 57141cc406Sopenharmony_ci#include <limits.h> 58141cc406Sopenharmony_ci#include <math.h> 59141cc406Sopenharmony_ci#include <signal.h> 60141cc406Sopenharmony_ci#include <stdio.h> 61141cc406Sopenharmony_ci#include <stdlib.h> 62141cc406Sopenharmony_ci#include <string.h> 63141cc406Sopenharmony_ci#include <unistd.h> 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci#include <sys/stat.h> 66141cc406Sopenharmony_ci#include <sys/time.h> 67141cc406Sopenharmony_ci#include <sys/types.h> 68141cc406Sopenharmony_ci#include <sys/wait.h> 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci#include "../include/sane/sane.h" 71141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 72141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 74141cc406Sopenharmony_ci#include "../include/sane/sanei_thread.h" 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci#ifndef PATH_MAX 77141cc406Sopenharmony_ci#define PATH_MAX 1024 78141cc406Sopenharmony_ci#endif 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci#define MINOR_VERSION 4 81141cc406Sopenharmony_ci#define BUILD 53 82141cc406Sopenharmony_ci#define BACKEND_NAME snapscan 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 85141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci#include "snapscan.h" 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci#define MIN(x,y) ((x)<(y) ? (x) : (y)) 90141cc406Sopenharmony_ci#define MAX(x,y) ((x)>(y) ? (x) : (y)) 91141cc406Sopenharmony_ci#define LIMIT(x,min,max) MIN(MAX(x, min), max) 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci#ifdef INOPERATIVE 94141cc406Sopenharmony_ci#define P_200_TO_255(per) SANE_UNFIX(255.0*((per + 100)/200.0)) 95141cc406Sopenharmony_ci#endif 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci/* debug levels */ 100141cc406Sopenharmony_ci#define DL_INFO 10 101141cc406Sopenharmony_ci#define DL_MINOR_INFO 15 102141cc406Sopenharmony_ci#define DL_MAJOR_ERROR 1 103141cc406Sopenharmony_ci#define DL_MINOR_ERROR 2 104141cc406Sopenharmony_ci#define DL_DATA_TRACE 50 105141cc406Sopenharmony_ci#define DL_OPTION_TRACE 70 106141cc406Sopenharmony_ci#define DL_CALL_TRACE 30 107141cc406Sopenharmony_ci#define DL_VERBOSE 20 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci#define CHECK_STATUS(s,caller,cmd) \ 110141cc406Sopenharmony_ciif ((s) != SANE_STATUS_GOOD) { DBG(DL_MAJOR_ERROR, "%s: %s command failed: %s\n", caller, (cmd), sane_strstatus(s)); return s; } 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci/*----- internal scanner operations -----*/ 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci/* hardware configuration byte masks */ 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci#define HCFG_ADC 0x80 /* AD converter 1 ==> 10bit, 0 ==> 8bit */ 117141cc406Sopenharmony_ci#define HCFG_ADF 0x40 /* automatic document feeder */ 118141cc406Sopenharmony_ci#define HCFG_TPO 0x20 /* transparency option */ 119141cc406Sopenharmony_ci#define HCFG_RB 0x10 /* ring buffer */ 120141cc406Sopenharmony_ci#define HCFG_HT16 0x08 /* 16x16 halftone matrices */ 121141cc406Sopenharmony_ci#define HCFG_HT8 0x04 /* 8x8 halftone matrices */ 122141cc406Sopenharmony_ci#define HCFG_SRA 0x02 /* scanline row average (high-speed colour) */ 123141cc406Sopenharmony_ci#define HCFG_CAL_ALLOWED 0x01 /* 1 ==> calibration allowed */ 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci#define HCFG_HT 0x0C /* support halftone matrices at all */ 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci#define MM_PER_IN 25.4 /* # millimetres per inch */ 128141cc406Sopenharmony_ci#define IN_PER_MM 0.03937 /* # inches per millimetre */ 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci#define GAMMA_8BIT 0 131141cc406Sopenharmony_ci#define GAMMA_16BIT 1 132141cc406Sopenharmony_ci#define GAMMA_12_16BIT 2 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_ci#ifndef SANE_I18N 135141cc406Sopenharmony_ci#define SANE_I18N(text) text 136141cc406Sopenharmony_ci#endif 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci/* authorization stuff */ 139141cc406Sopenharmony_cistatic SANE_Auth_Callback auth = NULL; 140141cc406Sopenharmony_ci#if UNUSED 141141cc406Sopenharmony_cistatic SANE_Char username[SANE_MAX_USERNAME_LEN]; 142141cc406Sopenharmony_cistatic SANE_Char password[SANE_MAX_PASSWORD_LEN]; 143141cc406Sopenharmony_ci#endif 144141cc406Sopenharmony_ci 145141cc406Sopenharmony_ci/* function prototypes */ 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_cistatic void gamma_n (double gamma, int brightness, int contrast, 148141cc406Sopenharmony_ci u_char *buf, int length, int gamma_mode); 149141cc406Sopenharmony_cistatic void gamma_to_sane (int length, u_char *in, SANE_Int *out); 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_cistatic size_t max_string_size(SANE_String_Const strings[]); 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_ci/* inline functions */ 154141cc406Sopenharmony_cistatic inline SnapScan_Mode actual_mode (SnapScan_Scanner *pss) 155141cc406Sopenharmony_ci{ 156141cc406Sopenharmony_ci if (pss->preview == SANE_TRUE) 157141cc406Sopenharmony_ci return pss->preview_mode; 158141cc406Sopenharmony_ci return pss->mode; 159141cc406Sopenharmony_ci} 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_cistatic inline int is_colour_mode (SnapScan_Mode m) 162141cc406Sopenharmony_ci{ 163141cc406Sopenharmony_ci return (m == MD_COLOUR) || (m == MD_BILEVELCOLOUR); 164141cc406Sopenharmony_ci} 165141cc406Sopenharmony_ci 166141cc406Sopenharmony_cistatic inline int calibration_line_length(SnapScan_Scanner *pss) 167141cc406Sopenharmony_ci{ 168141cc406Sopenharmony_ci int pos_factor; 169141cc406Sopenharmony_ci int pixel_length; 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci switch (pss->pdev->model) 172141cc406Sopenharmony_ci { 173141cc406Sopenharmony_ci case STYLUS_CX1500: 174141cc406Sopenharmony_ci case PRISA5000E: 175141cc406Sopenharmony_ci case PRISA5000: 176141cc406Sopenharmony_ci case PRISA5150: 177141cc406Sopenharmony_ci case PERFECTION1270: 178141cc406Sopenharmony_ci case PERFECTION1670: 179141cc406Sopenharmony_ci case PERFECTION2480: 180141cc406Sopenharmony_ci case PERFECTION3490: 181141cc406Sopenharmony_ci pos_factor = pss->actual_res / 2; 182141cc406Sopenharmony_ci pixel_length = pos_factor * 8.5; 183141cc406Sopenharmony_ci break; 184141cc406Sopenharmony_ci case SCANWIT2720S: 185141cc406Sopenharmony_ci pixel_length = 2550; 186141cc406Sopenharmony_ci break; 187141cc406Sopenharmony_ci default: 188141cc406Sopenharmony_ci pos_factor = pss->actual_res; 189141cc406Sopenharmony_ci pixel_length = pos_factor * 8.5; 190141cc406Sopenharmony_ci break; 191141cc406Sopenharmony_ci } 192141cc406Sopenharmony_ci 193141cc406Sopenharmony_ci if(is_colour_mode(actual_mode(pss))) { 194141cc406Sopenharmony_ci return 3 * pixel_length; 195141cc406Sopenharmony_ci } else { 196141cc406Sopenharmony_ci return pixel_length; 197141cc406Sopenharmony_ci } 198141cc406Sopenharmony_ci} 199141cc406Sopenharmony_ci 200141cc406Sopenharmony_ci/*----- global data structures and access utilities -----*/ 201141cc406Sopenharmony_ci 202141cc406Sopenharmony_ci/* available device list */ 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_cistatic SnapScan_Device *first_device = NULL; /* device list head */ 205141cc406Sopenharmony_cistatic SANE_Int n_devices = 0; /* the device count */ 206141cc406Sopenharmony_cistatic SANE_Char *default_firmware_filename; 207141cc406Sopenharmony_cistatic SANE_Bool cancelRead; 208141cc406Sopenharmony_ci 209141cc406Sopenharmony_ci/* list returned from sane_get_devices() */ 210141cc406Sopenharmony_cistatic const SANE_Device **get_devices_list = NULL; 211141cc406Sopenharmony_ci 212141cc406Sopenharmony_ci/* external routines */ 213141cc406Sopenharmony_ci#include "snapscan-scsi.c" 214141cc406Sopenharmony_ci#include "snapscan-sources.c" 215141cc406Sopenharmony_ci#include "snapscan-usb.c" 216141cc406Sopenharmony_ci#include "snapscan-options.c" 217141cc406Sopenharmony_ci 218141cc406Sopenharmony_ci/* Initialize gamma tables */ 219141cc406Sopenharmony_cistatic SANE_Status alloc_gamma_tables(SnapScan_Scanner * ps) 220141cc406Sopenharmony_ci{ 221141cc406Sopenharmony_ci static const char me[] = "alloc_gamma_tables"; 222141cc406Sopenharmony_ci 223141cc406Sopenharmony_ci ps->gamma_length = 1 << ps->bpp; 224141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: using 4*%d bytes for gamma table\n", 225141cc406Sopenharmony_ci me, 226141cc406Sopenharmony_ci ps->gamma_length); 227141cc406Sopenharmony_ci 228141cc406Sopenharmony_ci ps->gamma_tables = 229141cc406Sopenharmony_ci (SANE_Int *) malloc(4 * ps->gamma_length * sizeof(SANE_Int)); 230141cc406Sopenharmony_ci 231141cc406Sopenharmony_ci if (!ps->gamma_tables) 232141cc406Sopenharmony_ci { 233141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 234141cc406Sopenharmony_ci } 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci ps->gamma_table_gs = &ps->gamma_tables[0 * ps->gamma_length]; 237141cc406Sopenharmony_ci ps->gamma_table_r = &ps->gamma_tables[1 * ps->gamma_length]; 238141cc406Sopenharmony_ci ps->gamma_table_g = &ps->gamma_tables[2 * ps->gamma_length]; 239141cc406Sopenharmony_ci ps->gamma_table_b = &ps->gamma_tables[3 * ps->gamma_length]; 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 242141cc406Sopenharmony_ci} 243141cc406Sopenharmony_ci 244141cc406Sopenharmony_cistatic SANE_Status init_gamma(SnapScan_Scanner * ps) 245141cc406Sopenharmony_ci{ 246141cc406Sopenharmony_ci u_char *gamma; 247141cc406Sopenharmony_ci 248141cc406Sopenharmony_ci gamma = (u_char*) malloc(ps->gamma_length * sizeof(u_char) * 2); 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci if (!gamma) 251141cc406Sopenharmony_ci { 252141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 253141cc406Sopenharmony_ci } 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci /* Default tables */ 256141cc406Sopenharmony_ci gamma_n (SANE_UNFIX(ps->gamma_gs), ps->bright, ps->contrast, gamma, ps->bpp, 1); 257141cc406Sopenharmony_ci gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_gs); 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci gamma_n (SANE_UNFIX(ps->gamma_r), ps->bright, ps->contrast, gamma, ps->bpp, 1); 260141cc406Sopenharmony_ci gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_r); 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci gamma_n (SANE_UNFIX(ps->gamma_g), ps->bright, ps->contrast, gamma, ps->bpp, 1); 263141cc406Sopenharmony_ci gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_g); 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_ci gamma_n (SANE_UNFIX(ps->gamma_b), ps->bright, ps->contrast, gamma, ps->bpp, 1); 266141cc406Sopenharmony_ci gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_b); 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci free (gamma); 269141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 270141cc406Sopenharmony_ci} 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_ci/* Max string size */ 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_cistatic size_t max_string_size (SANE_String_Const strings[]) 275141cc406Sopenharmony_ci{ 276141cc406Sopenharmony_ci size_t size; 277141cc406Sopenharmony_ci size_t max_size = 0; 278141cc406Sopenharmony_ci int i; 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 281141cc406Sopenharmony_ci { 282141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 283141cc406Sopenharmony_ci if (size > max_size) 284141cc406Sopenharmony_ci max_size = size; 285141cc406Sopenharmony_ci } 286141cc406Sopenharmony_ci return max_size; 287141cc406Sopenharmony_ci} 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci/* gamma table computation */ 290141cc406Sopenharmony_cistatic void gamma_n (double gamma, int brightness, int contrast, 291141cc406Sopenharmony_ci u_char *buf, int bpp, int gamma_mode) 292141cc406Sopenharmony_ci{ 293141cc406Sopenharmony_ci int i; 294141cc406Sopenharmony_ci double i_gamma = 1.0/gamma; 295141cc406Sopenharmony_ci int length = 1 << bpp; 296141cc406Sopenharmony_ci int max = length - 1; 297141cc406Sopenharmony_ci double mid = max / 2.0; 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci for (i = 0; i < length; i++) 300141cc406Sopenharmony_ci { 301141cc406Sopenharmony_ci int x; 302141cc406Sopenharmony_ci double val = (i - mid) * (1.0 + contrast / 100.0) 303141cc406Sopenharmony_ci + (1.0 + brightness / 100.0) * mid; 304141cc406Sopenharmony_ci val = LIMIT(val, 0, max); 305141cc406Sopenharmony_ci switch (gamma_mode) 306141cc406Sopenharmony_ci { 307141cc406Sopenharmony_ci case GAMMA_16BIT: 308141cc406Sopenharmony_ci x = LIMIT(65535*pow ((double) val/max, i_gamma) + 0.5, 0, 65535); 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci buf[2*i] = (u_char) x; 311141cc406Sopenharmony_ci buf[2*i + 1] = (u_char) (x >> 8); 312141cc406Sopenharmony_ci break; 313141cc406Sopenharmony_ci case GAMMA_12_16BIT: 314141cc406Sopenharmony_ci buf[2*i] = (u_char) i; 315141cc406Sopenharmony_ci buf[2*i + 1] = (u_char) (i >> 8); 316141cc406Sopenharmony_ci break; 317141cc406Sopenharmony_ci case GAMMA_8BIT: 318141cc406Sopenharmony_ci buf[i] = 319141cc406Sopenharmony_ci (u_char) LIMIT(255*pow ((double) val/max, i_gamma) + 0.5, 0, 255); 320141cc406Sopenharmony_ci break; 321141cc406Sopenharmony_ci default: 322141cc406Sopenharmony_ci break; 323141cc406Sopenharmony_ci } 324141cc406Sopenharmony_ci } 325141cc406Sopenharmony_ci} 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_cistatic void gamma_from_sane (int length, SANE_Int *in, u_char *out, int gamma_mode) 328141cc406Sopenharmony_ci{ 329141cc406Sopenharmony_ci int i; 330141cc406Sopenharmony_ci for (i = 0; i < length; i++) 331141cc406Sopenharmony_ci if (gamma_mode != GAMMA_8BIT) 332141cc406Sopenharmony_ci { 333141cc406Sopenharmony_ci out[2*i] = (u_char) LIMIT(in[i], 0, 65535); 334141cc406Sopenharmony_ci out[2*i + 1] = (u_char) (LIMIT(in[i], 0, 65535) >> 8); 335141cc406Sopenharmony_ci } 336141cc406Sopenharmony_ci else 337141cc406Sopenharmony_ci out[i] = (u_char) LIMIT(in[i] / 256, 0, 255); 338141cc406Sopenharmony_ci} 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_cistatic void gamma_to_sane (int length, u_char *in, SANE_Int *out) 341141cc406Sopenharmony_ci{ 342141cc406Sopenharmony_ci int i; 343141cc406Sopenharmony_ci for (i = 0; i < length; i++) 344141cc406Sopenharmony_ci out[i] = in[2*i] + 256 * in[2*i + 1]; 345141cc406Sopenharmony_ci} 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci/* dispersed-dot dither matrices; this is discussed in Foley, Van Dam, 348141cc406Sopenharmony_ci Feiner and Hughes: Computer Graphics: principles and practice, 349141cc406Sopenharmony_ci 2nd ed. (Addison-Wesley), pp 570-571. 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ci The function mfDn computes the nth dispersed-dot dither matrix Dn 352141cc406Sopenharmony_ci given D(n/2) and n; n is presumed to be a power of 2. D8 and D16 353141cc406Sopenharmony_ci are the matrices of interest to us, since the SnapScan supports 354141cc406Sopenharmony_ci only 8x8 and 16x16 dither matrices. */ 355141cc406Sopenharmony_ci 356141cc406Sopenharmony_cistatic u_char D2[] ={0, 2, 3, 1}; 357141cc406Sopenharmony_ci 358141cc406Sopenharmony_cistatic u_char D4[16], D8[64], D16[256]; 359141cc406Sopenharmony_ci 360141cc406Sopenharmony_cistatic void mkDn (u_char *Dn, u_char *Dn_half, unsigned n) 361141cc406Sopenharmony_ci{ 362141cc406Sopenharmony_ci unsigned int x, y; 363141cc406Sopenharmony_ci for (y = 0; y < n; y++) { 364141cc406Sopenharmony_ci for (x = 0; x < n; x++) { 365141cc406Sopenharmony_ci /* Dn(x,y) = D2(2*x/n, 2*y/n) +4*Dn_half(x%(n/2), y%(n/2)) */ 366141cc406Sopenharmony_ci Dn[y*n + x] = D2[((int)(2*y/n))*2 + (int)(2*x/n)] 367141cc406Sopenharmony_ci + 4*Dn_half[(y%(n/2))*(n/2) + x%(n/2)]; 368141cc406Sopenharmony_ci } 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci} 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_cistatic SANE_Bool device_already_in_list (SnapScan_Device *current, 373141cc406Sopenharmony_ci SANE_String_Const name) 374141cc406Sopenharmony_ci{ 375141cc406Sopenharmony_ci for ( ; NULL != current; current = current->pnext) 376141cc406Sopenharmony_ci { 377141cc406Sopenharmony_ci if (0 == strcmp (name, current->dev.name)) 378141cc406Sopenharmony_ci return SANE_TRUE; 379141cc406Sopenharmony_ci } 380141cc406Sopenharmony_ci return SANE_FALSE; 381141cc406Sopenharmony_ci} 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_cistatic SANE_Char* get_driver_name(SnapScan_Model model_num) { 384141cc406Sopenharmony_ci SANE_Int i; 385141cc406Sopenharmony_ci for (i=0; i<known_drivers; i++) { 386141cc406Sopenharmony_ci if (drivers[i].id == model_num) break; 387141cc406Sopenharmony_ci } 388141cc406Sopenharmony_ci if (i == known_drivers) { 389141cc406Sopenharmony_ci DBG(0, "Implementation error: Driver name not found\n"); 390141cc406Sopenharmony_ci return ("Unknown"); 391141cc406Sopenharmony_ci } 392141cc406Sopenharmony_ci return (drivers[i].driver_name); 393141cc406Sopenharmony_ci} 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_cistatic SANE_Status snapscani_check_device( 396141cc406Sopenharmony_ci int fd, 397141cc406Sopenharmony_ci SnapScan_Bus bus_type, 398141cc406Sopenharmony_ci char* vendor, 399141cc406Sopenharmony_ci char* model, 400141cc406Sopenharmony_ci SnapScan_Model* model_num 401141cc406Sopenharmony_ci) { 402141cc406Sopenharmony_ci static const char me[] = "snapscani_check_device"; 403141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 404141cc406Sopenharmony_ci int supported_vendor = 0; 405141cc406Sopenharmony_ci int i; 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s()\n", me); 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci /* check that the device is legitimate */ 410141cc406Sopenharmony_ci if ((status = mini_inquiry (bus_type, fd, vendor, model)) != SANE_STATUS_GOOD) 411141cc406Sopenharmony_ci { 412141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 413141cc406Sopenharmony_ci "%s: mini_inquiry failed with %s.\n", 414141cc406Sopenharmony_ci me, 415141cc406Sopenharmony_ci sane_strstatus (status)); 416141cc406Sopenharmony_ci return status; 417141cc406Sopenharmony_ci } 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci DBG (DL_VERBOSE, 420141cc406Sopenharmony_ci "%s: Is vendor \"%s\" model \"%s\" a supported scanner?\n", 421141cc406Sopenharmony_ci me, 422141cc406Sopenharmony_ci vendor, 423141cc406Sopenharmony_ci model); 424141cc406Sopenharmony_ci 425141cc406Sopenharmony_ci /* check if this is one of our supported vendors */ 426141cc406Sopenharmony_ci for (i = 0; i < known_vendors; i++) 427141cc406Sopenharmony_ci { 428141cc406Sopenharmony_ci if (0 == strcasecmp (vendor, vendors[i])) 429141cc406Sopenharmony_ci { 430141cc406Sopenharmony_ci supported_vendor = 1; 431141cc406Sopenharmony_ci break; 432141cc406Sopenharmony_ci } 433141cc406Sopenharmony_ci } 434141cc406Sopenharmony_ci if (supported_vendor) 435141cc406Sopenharmony_ci { 436141cc406Sopenharmony_ci /* Known vendor. Check if it is one of our supported models */ 437141cc406Sopenharmony_ci *model_num = snapscani_get_model_id(model, fd, bus_type); 438141cc406Sopenharmony_ci } 439141cc406Sopenharmony_ci if (!supported_vendor || UNKNOWN == model_num) 440141cc406Sopenharmony_ci { 441141cc406Sopenharmony_ci DBG (DL_MINOR_ERROR, 442141cc406Sopenharmony_ci "%s: \"%s %s\" is not one of %s\n", 443141cc406Sopenharmony_ci me, 444141cc406Sopenharmony_ci vendor, 445141cc406Sopenharmony_ci model, 446141cc406Sopenharmony_ci "AGFA SnapScan 300, 310, 600, 1212, 1236, e10, e20, e25, e26, " 447141cc406Sopenharmony_ci "e40, e42, e50, e52 or e60\n" 448141cc406Sopenharmony_ci "Acer 300, 310, 610, 610+, " 449141cc406Sopenharmony_ci "620, 620+, 640, 1240, 3300, 4300 or 5300\n" 450141cc406Sopenharmony_ci "Guillemot MaxiScan A4 Deluxe"); 451141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 452141cc406Sopenharmony_ci } else { 453141cc406Sopenharmony_ci DBG(DL_VERBOSE, "%s: Autodetected driver: %s\n", me, get_driver_name(*model_num)); 454141cc406Sopenharmony_ci } 455141cc406Sopenharmony_ci return status; 456141cc406Sopenharmony_ci} 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_cistatic SANE_Status snapscani_init_device_structure( 459141cc406Sopenharmony_ci SnapScan_Device **pd, 460141cc406Sopenharmony_ci const SnapScan_Bus bus_type, 461141cc406Sopenharmony_ci SANE_String_Const name, 462141cc406Sopenharmony_ci const char* vendor, 463141cc406Sopenharmony_ci const char* model, 464141cc406Sopenharmony_ci const SnapScan_Model model_num 465141cc406Sopenharmony_ci) { 466141cc406Sopenharmony_ci static const char me[] = "snapscani_init_device_structure"; 467141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD;; 468141cc406Sopenharmony_ci 469141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s()\n", me); 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci (*pd) = (SnapScan_Device *) malloc (sizeof (SnapScan_Device)); 472141cc406Sopenharmony_ci if (!(*pd)) 473141cc406Sopenharmony_ci { 474141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: out of memory allocating device.", me); 475141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 476141cc406Sopenharmony_ci } 477141cc406Sopenharmony_ci (*pd)->dev.name = strdup (name); 478141cc406Sopenharmony_ci if (strcmp(vendor, "Color") == 0) { 479141cc406Sopenharmony_ci (*pd)->dev.vendor = strdup ("Acer"); 480141cc406Sopenharmony_ci } else { 481141cc406Sopenharmony_ci (*pd)->dev.vendor = strdup (vendor); 482141cc406Sopenharmony_ci } 483141cc406Sopenharmony_ci (*pd)->dev.model = strdup (model); 484141cc406Sopenharmony_ci if (model_num == SCANWIT2720S) 485141cc406Sopenharmony_ci { 486141cc406Sopenharmony_ci (*pd)->dev.type = strdup (SNAPSCAN_FS_TYPE); 487141cc406Sopenharmony_ci } 488141cc406Sopenharmony_ci else 489141cc406Sopenharmony_ci { 490141cc406Sopenharmony_ci (*pd)->dev.type = strdup (SNAPSCAN_TYPE); 491141cc406Sopenharmony_ci } 492141cc406Sopenharmony_ci (*pd)->bus = bus_type; 493141cc406Sopenharmony_ci (*pd)->model = model_num; 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci if (!(*pd)->dev.name || !(*pd)->dev.vendor || !(*pd)->dev.model || !(*pd)->dev.type) 496141cc406Sopenharmony_ci { 497141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 498141cc406Sopenharmony_ci "%s: out of memory allocating device descriptor strings.\n", 499141cc406Sopenharmony_ci me); 500141cc406Sopenharmony_ci free (*pd); 501141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 502141cc406Sopenharmony_ci } 503141cc406Sopenharmony_ci (*pd)->x_range.min = x_range_fb.min; 504141cc406Sopenharmony_ci (*pd)->x_range.quant = x_range_fb.quant; 505141cc406Sopenharmony_ci (*pd)->x_range.max = x_range_fb.max; 506141cc406Sopenharmony_ci (*pd)->y_range.min = y_range_fb.min; 507141cc406Sopenharmony_ci (*pd)->y_range.quant = y_range_fb.quant; 508141cc406Sopenharmony_ci (*pd)->y_range.max = y_range_fb.max; 509141cc406Sopenharmony_ci (*pd)->firmware_filename = NULL; 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci (*pd)->pnext = first_device; 512141cc406Sopenharmony_ci first_device = (*pd); 513141cc406Sopenharmony_ci n_devices++; 514141cc406Sopenharmony_ci return status; 515141cc406Sopenharmony_ci} 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_cistatic SANE_Status add_scsi_device (SANE_String_Const full_name) 518141cc406Sopenharmony_ci{ 519141cc406Sopenharmony_ci int fd; 520141cc406Sopenharmony_ci static const char me[] = "add_scsi_device"; 521141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 522141cc406Sopenharmony_ci SnapScan_Device *pd; 523141cc406Sopenharmony_ci SnapScan_Model model_num = UNKNOWN; 524141cc406Sopenharmony_ci SnapScan_Bus bus_type = SCSI; 525141cc406Sopenharmony_ci char vendor[8]; 526141cc406Sopenharmony_ci char model[17]; 527141cc406Sopenharmony_ci SANE_Char *name = NULL; 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s(%s)\n", me, full_name); 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci sanei_config_get_string(full_name, &name); 532141cc406Sopenharmony_ci if (!name) 533141cc406Sopenharmony_ci { 534141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 535141cc406Sopenharmony_ci } 536141cc406Sopenharmony_ci /* Avoid adding the same device more then once */ 537141cc406Sopenharmony_ci if (device_already_in_list (first_device, name)) { 538141cc406Sopenharmony_ci free(name); 539141cc406Sopenharmony_ci name = 0; 540141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 541141cc406Sopenharmony_ci } 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci vendor[0] = model[0] = '\0'; 544141cc406Sopenharmony_ci 545141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: Detected (kind of) a SCSI device\n", me); 546141cc406Sopenharmony_ci 547141cc406Sopenharmony_ci status = sanei_scsi_open (name, &fd, sense_handler, NULL); 548141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 549141cc406Sopenharmony_ci { 550141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 551141cc406Sopenharmony_ci "%s: error opening device %s: %s\n", 552141cc406Sopenharmony_ci me, 553141cc406Sopenharmony_ci name, 554141cc406Sopenharmony_ci sane_strstatus (status)); 555141cc406Sopenharmony_ci } else { 556141cc406Sopenharmony_ci status = snapscani_check_device(fd, bus_type, vendor, model, &model_num); 557141cc406Sopenharmony_ci sanei_scsi_close(fd); 558141cc406Sopenharmony_ci } 559141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) { 560141cc406Sopenharmony_ci status = snapscani_init_device_structure( 561141cc406Sopenharmony_ci &pd, 562141cc406Sopenharmony_ci bus_type, 563141cc406Sopenharmony_ci name, 564141cc406Sopenharmony_ci vendor, 565141cc406Sopenharmony_ci model, 566141cc406Sopenharmony_ci model_num 567141cc406Sopenharmony_ci ); 568141cc406Sopenharmony_ci } 569141cc406Sopenharmony_ci free(name); 570141cc406Sopenharmony_ci name = 0; 571141cc406Sopenharmony_ci return status; 572141cc406Sopenharmony_ci} 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_cistatic SANE_Status add_usb_device (SANE_String_Const full_name) { 575141cc406Sopenharmony_ci static const char me[] = "add_usb_device"; 576141cc406Sopenharmony_ci int fd; 577141cc406Sopenharmony_ci SnapScan_Device *pd; 578141cc406Sopenharmony_ci SnapScan_Model model_num = UNKNOWN; 579141cc406Sopenharmony_ci SANE_Word vendor_id, product_id; 580141cc406Sopenharmony_ci int supported_usb_vendor = 0; 581141cc406Sopenharmony_ci char vendor[8]; 582141cc406Sopenharmony_ci char model[17]; 583141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 584141cc406Sopenharmony_ci SnapScan_Bus bus_type = USB; 585141cc406Sopenharmony_ci int i; 586141cc406Sopenharmony_ci SANE_Char *name = NULL; 587141cc406Sopenharmony_ci 588141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s(%s)\n", me, full_name); 589141cc406Sopenharmony_ci sanei_config_get_string(full_name, &name); 590141cc406Sopenharmony_ci if (!name) 591141cc406Sopenharmony_ci { 592141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 593141cc406Sopenharmony_ci } 594141cc406Sopenharmony_ci /* Avoid adding the same device more then once */ 595141cc406Sopenharmony_ci if (device_already_in_list (first_device, name)) { 596141cc406Sopenharmony_ci free(name); 597141cc406Sopenharmony_ci name = 0; 598141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 599141cc406Sopenharmony_ci } 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci vendor[0] = model[0] = '\0'; 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: Detected (kind of) an USB device\n", me); 604141cc406Sopenharmony_ci bus_type = USB; 605141cc406Sopenharmony_ci status = snapscani_usb_shm_init(); 606141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 607141cc406Sopenharmony_ci { 608141cc406Sopenharmony_ci return status; 609141cc406Sopenharmony_ci } 610141cc406Sopenharmony_ci status = snapscani_usb_open (name, &fd, sense_handler, NULL); 611141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 612141cc406Sopenharmony_ci { 613141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 614141cc406Sopenharmony_ci "%s: error opening device %s: %s\n", 615141cc406Sopenharmony_ci me, 616141cc406Sopenharmony_ci name, 617141cc406Sopenharmony_ci sane_strstatus (status)); 618141cc406Sopenharmony_ci } else { 619141cc406Sopenharmony_ci if (sanei_usb_get_vendor_product(fd, &vendor_id, &product_id) == 620141cc406Sopenharmony_ci SANE_STATUS_GOOD) 621141cc406Sopenharmony_ci { 622141cc406Sopenharmony_ci /* check for known USB vendors to avoid hanging scanners by 623141cc406Sopenharmony_ci inquiry-command. 624141cc406Sopenharmony_ci */ 625141cc406Sopenharmony_ci DBG(DL_INFO, "%s: Checking if 0x%04x is a supported USB vendor ID\n", 626141cc406Sopenharmony_ci me, vendor_id); 627141cc406Sopenharmony_ci for (i = 0; i < known_usb_vendor_ids; i++) { 628141cc406Sopenharmony_ci if (vendor_id == usb_vendor_ids[i]) { 629141cc406Sopenharmony_ci supported_usb_vendor = 1; 630141cc406Sopenharmony_ci } 631141cc406Sopenharmony_ci } 632141cc406Sopenharmony_ci if (!supported_usb_vendor) { 633141cc406Sopenharmony_ci DBG(DL_MINOR_ERROR, 634141cc406Sopenharmony_ci "%s: USB vendor ID 0x%04x is currently NOT supported by the snapscan backend.\n", 635141cc406Sopenharmony_ci me, vendor_id); 636141cc406Sopenharmony_ci status=SANE_STATUS_INVAL; 637141cc406Sopenharmony_ci snapscani_usb_close(fd); 638141cc406Sopenharmony_ci } 639141cc406Sopenharmony_ci } 640141cc406Sopenharmony_ci } 641141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) { 642141cc406Sopenharmony_ci status = snapscani_check_device(fd, bus_type, vendor, model, &model_num); 643141cc406Sopenharmony_ci snapscani_usb_close(fd); 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci /* deinit shared memory, will be initialized again in open_scanner */ 646141cc406Sopenharmony_ci snapscani_usb_shm_exit(); 647141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) { 648141cc406Sopenharmony_ci status = snapscani_init_device_structure( 649141cc406Sopenharmony_ci &pd, 650141cc406Sopenharmony_ci bus_type, 651141cc406Sopenharmony_ci name, 652141cc406Sopenharmony_ci vendor, 653141cc406Sopenharmony_ci model, 654141cc406Sopenharmony_ci model_num 655141cc406Sopenharmony_ci ); 656141cc406Sopenharmony_ci } 657141cc406Sopenharmony_ci free(name); 658141cc406Sopenharmony_ci name = 0; 659141cc406Sopenharmony_ci return status; 660141cc406Sopenharmony_ci} 661141cc406Sopenharmony_ci 662141cc406Sopenharmony_ci/* find_device: find a device in the available list by name 663141cc406Sopenharmony_ci 664141cc406Sopenharmony_ci ARG: the device name 665141cc406Sopenharmony_ci 666141cc406Sopenharmony_ci RET: a pointer to the corresponding device record, or NULL if there 667141cc406Sopenharmony_ci is no such device */ 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_cistatic SnapScan_Device *find_device (SANE_String_Const name) 670141cc406Sopenharmony_ci{ 671141cc406Sopenharmony_ci static char me[] = "find_device"; 672141cc406Sopenharmony_ci SnapScan_Device *psd; 673141cc406Sopenharmony_ci 674141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 675141cc406Sopenharmony_ci 676141cc406Sopenharmony_ci for (psd = first_device; psd; psd = psd->pnext) 677141cc406Sopenharmony_ci { 678141cc406Sopenharmony_ci if (strcmp (psd->dev.name, name) == 0) 679141cc406Sopenharmony_ci return psd; 680141cc406Sopenharmony_ci } 681141cc406Sopenharmony_ci return NULL; 682141cc406Sopenharmony_ci} 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci/*----- functions in the scanner interface -----*/ 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_ciSANE_Status sane_init (SANE_Int *version_code, 687141cc406Sopenharmony_ci SANE_Auth_Callback authorize) 688141cc406Sopenharmony_ci{ 689141cc406Sopenharmony_ci static const char me[] = "sane_snapscan_init"; 690141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 691141cc406Sopenharmony_ci size_t len; 692141cc406Sopenharmony_ci FILE *fp; 693141cc406Sopenharmony_ci SANE_Status status; 694141cc406Sopenharmony_ci 695141cc406Sopenharmony_ci DBG_INIT (); 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 698141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: Snapscan backend version %d.%d.%d\n", 699141cc406Sopenharmony_ci me, 700141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, MINOR_VERSION, BUILD); 701141cc406Sopenharmony_ci 702141cc406Sopenharmony_ci if (version_code != NULL) 703141cc406Sopenharmony_ci { 704141cc406Sopenharmony_ci *version_code = 705141cc406Sopenharmony_ci SANE_VERSION_CODE (SANE_CURRENT_MAJOR, MINOR_VERSION, BUILD); 706141cc406Sopenharmony_ci } 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci auth = authorize; 709141cc406Sopenharmony_ci /* Initialize data structures */ 710141cc406Sopenharmony_ci default_firmware_filename = NULL; 711141cc406Sopenharmony_ci first_device = NULL; 712141cc406Sopenharmony_ci n_devices = 0; 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci sanei_usb_init(); 715141cc406Sopenharmony_ci sanei_thread_init(); 716141cc406Sopenharmony_ci /* build a device structure */ 717141cc406Sopenharmony_ci fp = sanei_config_open (SNAPSCAN_CONFIG_FILE); 718141cc406Sopenharmony_ci if (!fp) 719141cc406Sopenharmony_ci { 720141cc406Sopenharmony_ci /* default to DEFAULT_DEVICE instead of insisting on config file */ 721141cc406Sopenharmony_ci DBG (DL_INFO, 722141cc406Sopenharmony_ci "%s: configuration file not found, defaulting to %s.\n", 723141cc406Sopenharmony_ci me, 724141cc406Sopenharmony_ci DEFAULT_DEVICE); 725141cc406Sopenharmony_ci status = add_scsi_device (DEFAULT_DEVICE); 726141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 727141cc406Sopenharmony_ci { 728141cc406Sopenharmony_ci DBG (DL_MINOR_ERROR, 729141cc406Sopenharmony_ci "%s: failed to add device \"%s\"\n", 730141cc406Sopenharmony_ci me, 731141cc406Sopenharmony_ci dev_name); 732141cc406Sopenharmony_ci } 733141cc406Sopenharmony_ci } 734141cc406Sopenharmony_ci else 735141cc406Sopenharmony_ci { 736141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 737141cc406Sopenharmony_ci { 738141cc406Sopenharmony_ci len = strlen (dev_name); 739141cc406Sopenharmony_ci if (!len) 740141cc406Sopenharmony_ci continue; /* ignore empty lines */ 741141cc406Sopenharmony_ci if (dev_name[0] == '#') /* ignore line comments */ 742141cc406Sopenharmony_ci continue; 743141cc406Sopenharmony_ci if (strncasecmp(dev_name, FIRMWARE_KW, strlen(FIRMWARE_KW)) == 0) { 744141cc406Sopenharmony_ci if (!default_firmware_filename) { 745141cc406Sopenharmony_ci sanei_config_get_string(dev_name + strlen(FIRMWARE_KW), &default_firmware_filename); 746141cc406Sopenharmony_ci if (default_firmware_filename == NULL) { 747141cc406Sopenharmony_ci DBG (0, "%s: Illegal firmware entry %s.\n", me, dev_name); 748141cc406Sopenharmony_ci } 749141cc406Sopenharmony_ci } 750141cc406Sopenharmony_ci } 751141cc406Sopenharmony_ci else if (strncasecmp(dev_name, OPTIONS_KW, strlen(OPTIONS_KW)) == 0) 752141cc406Sopenharmony_ci continue; /* ignore options lines */ 753141cc406Sopenharmony_ci 754141cc406Sopenharmony_ci else if (strncmp(dev_name, "usb", 3) == 0) { 755141cc406Sopenharmony_ci sanei_usb_attach_matching_devices (dev_name, add_usb_device); 756141cc406Sopenharmony_ci } 757141cc406Sopenharmony_ci else if (strncmp(dev_name, "scsi", 4) == 0) { 758141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, add_scsi_device); 759141cc406Sopenharmony_ci } 760141cc406Sopenharmony_ci else if (strstr (dev_name, "usb")) { 761141cc406Sopenharmony_ci add_usb_device(dev_name); 762141cc406Sopenharmony_ci } 763141cc406Sopenharmony_ci else { 764141cc406Sopenharmony_ci add_scsi_device(dev_name); 765141cc406Sopenharmony_ci } 766141cc406Sopenharmony_ci } 767141cc406Sopenharmony_ci fclose (fp); 768141cc406Sopenharmony_ci } 769141cc406Sopenharmony_ci 770141cc406Sopenharmony_ci /* compute the dither matrices */ 771141cc406Sopenharmony_ci 772141cc406Sopenharmony_ci mkDn (D4, D2, 4); 773141cc406Sopenharmony_ci mkDn (D8, D4, 8); 774141cc406Sopenharmony_ci mkDn (D16, D8, 16); 775141cc406Sopenharmony_ci /* scale the D8 matrix from 0..63 to 0..255 */ 776141cc406Sopenharmony_ci { 777141cc406Sopenharmony_ci u_char i; 778141cc406Sopenharmony_ci for (i = 0; i < 64; i++) 779141cc406Sopenharmony_ci D8[i] = (u_char) (4 * D8[i] + 2); 780141cc406Sopenharmony_ci } 781141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 782141cc406Sopenharmony_ci} 783141cc406Sopenharmony_ci 784141cc406Sopenharmony_cistatic void free_device_list(SnapScan_Device *psd) { 785141cc406Sopenharmony_ci if (psd->pnext != NULL) { 786141cc406Sopenharmony_ci free_device_list(psd->pnext); 787141cc406Sopenharmony_ci } 788141cc406Sopenharmony_ci free(psd); 789141cc406Sopenharmony_ci} 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_civoid sane_exit (void) 792141cc406Sopenharmony_ci{ 793141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "sane_snapscan_exit\n"); 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_ci if (get_devices_list) 796141cc406Sopenharmony_ci free (get_devices_list); 797141cc406Sopenharmony_ci get_devices_list = NULL; 798141cc406Sopenharmony_ci 799141cc406Sopenharmony_ci /* just for safety, reset things to known values */ 800141cc406Sopenharmony_ci auth = NULL; 801141cc406Sopenharmony_ci 802141cc406Sopenharmony_ci if (first_device) { 803141cc406Sopenharmony_ci free_device_list(first_device); 804141cc406Sopenharmony_ci first_device = NULL; 805141cc406Sopenharmony_ci } 806141cc406Sopenharmony_ci n_devices = 0; 807141cc406Sopenharmony_ci} 808141cc406Sopenharmony_ci 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ciSANE_Status sane_get_devices (const SANE_Device ***device_list, 811141cc406Sopenharmony_ci SANE_Bool local_only) 812141cc406Sopenharmony_ci{ 813141cc406Sopenharmony_ci static const char *me = "sane_snapscan_get_devices"; 814141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, 815141cc406Sopenharmony_ci "%s (%p, %ld)\n", 816141cc406Sopenharmony_ci me, 817141cc406Sopenharmony_ci (const void *) device_list, 818141cc406Sopenharmony_ci (long) local_only); 819141cc406Sopenharmony_ci 820141cc406Sopenharmony_ci /* Waste the last list returned from this function */ 821141cc406Sopenharmony_ci if (NULL != get_devices_list) 822141cc406Sopenharmony_ci free (get_devices_list); 823141cc406Sopenharmony_ci 824141cc406Sopenharmony_ci *device_list = 825141cc406Sopenharmony_ci (const SANE_Device **) malloc ((n_devices + 1) * sizeof (SANE_Device *)); 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci if (*device_list) 828141cc406Sopenharmony_ci { 829141cc406Sopenharmony_ci int i; 830141cc406Sopenharmony_ci SnapScan_Device *pdev; 831141cc406Sopenharmony_ci for (i = 0, pdev = first_device; pdev; i++, pdev = pdev->pnext) 832141cc406Sopenharmony_ci (*device_list)[i] = &(pdev->dev); 833141cc406Sopenharmony_ci (*device_list)[i] = 0x0000 /*NULL */; 834141cc406Sopenharmony_ci } 835141cc406Sopenharmony_ci else 836141cc406Sopenharmony_ci { 837141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: out of memory\n", me); 838141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 839141cc406Sopenharmony_ci } 840141cc406Sopenharmony_ci 841141cc406Sopenharmony_ci get_devices_list = *device_list; 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 844141cc406Sopenharmony_ci} 845141cc406Sopenharmony_ci 846141cc406Sopenharmony_ciSANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) 847141cc406Sopenharmony_ci{ 848141cc406Sopenharmony_ci static const char *me = "sane_snapscan_open"; 849141cc406Sopenharmony_ci SnapScan_Device *psd; 850141cc406Sopenharmony_ci SANE_Status status; 851141cc406Sopenharmony_ci 852141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s (%s, %p)\n", me, name, (void *) h); 853141cc406Sopenharmony_ci 854141cc406Sopenharmony_ci /* possible authorization required */ 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_ci /* no device name: use first device */ 857141cc406Sopenharmony_ci if ((strlen(name) == 0) && (first_device != NULL)) 858141cc406Sopenharmony_ci { 859141cc406Sopenharmony_ci name = first_device->dev.name; 860141cc406Sopenharmony_ci } 861141cc406Sopenharmony_ci 862141cc406Sopenharmony_ci /* device exists? */ 863141cc406Sopenharmony_ci psd = find_device (name); 864141cc406Sopenharmony_ci if (!psd) 865141cc406Sopenharmony_ci { 866141cc406Sopenharmony_ci DBG (DL_MINOR_ERROR, 867141cc406Sopenharmony_ci "%s: device \"%s\" not in current device list.\n", 868141cc406Sopenharmony_ci me, 869141cc406Sopenharmony_ci name); 870141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 871141cc406Sopenharmony_ci } 872141cc406Sopenharmony_ci 873141cc406Sopenharmony_ci /* create and initialize the scanner structure */ 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci *h = (SnapScan_Scanner *) calloc (sizeof (SnapScan_Scanner), 1); 876141cc406Sopenharmony_ci if (!*h) 877141cc406Sopenharmony_ci { 878141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 879141cc406Sopenharmony_ci "%s: out of memory creating scanner structure.\n", 880141cc406Sopenharmony_ci me); 881141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 882141cc406Sopenharmony_ci } 883141cc406Sopenharmony_ci 884141cc406Sopenharmony_ci { 885141cc406Sopenharmony_ci SnapScan_Scanner *pss = *(SnapScan_Scanner **) h; 886141cc406Sopenharmony_ci 887141cc406Sopenharmony_ci { 888141cc406Sopenharmony_ci pss->devname = strdup (name); 889141cc406Sopenharmony_ci if (!pss->devname) 890141cc406Sopenharmony_ci { 891141cc406Sopenharmony_ci free (*h); 892141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 893141cc406Sopenharmony_ci "%s: out of memory copying device name.\n", 894141cc406Sopenharmony_ci me); 895141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 896141cc406Sopenharmony_ci } 897141cc406Sopenharmony_ci pss->pdev = psd; 898141cc406Sopenharmony_ci pss->opens = 0; 899141cc406Sopenharmony_ci pss->sense_str = NULL; 900141cc406Sopenharmony_ci pss->as_str = NULL; 901141cc406Sopenharmony_ci pss->phys_buf_sz = DEFAULT_SCANNER_BUF_SZ; 902141cc406Sopenharmony_ci if ((pss->pdev->model == PERFECTION2480) || (pss->pdev->model == PERFECTION3490)) 903141cc406Sopenharmony_ci pss->phys_buf_sz *= 2; 904141cc406Sopenharmony_ci if (psd->bus == SCSI) { 905141cc406Sopenharmony_ci pss->phys_buf_sz = sanei_scsi_max_request_size; 906141cc406Sopenharmony_ci } 907141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 908141cc406Sopenharmony_ci "%s: Allocating %lu bytes as scanner buffer.\n", 909141cc406Sopenharmony_ci me, (u_long) pss->phys_buf_sz); 910141cc406Sopenharmony_ci pss->buf = (u_char *) malloc(pss->phys_buf_sz); 911141cc406Sopenharmony_ci if (!pss->buf) { 912141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 913141cc406Sopenharmony_ci "%s: out of memory creating scanner buffer.\n", 914141cc406Sopenharmony_ci me); 915141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 916141cc406Sopenharmony_ci } 917141cc406Sopenharmony_ci 918141cc406Sopenharmony_ci DBG (DL_VERBOSE, 919141cc406Sopenharmony_ci "%s: allocated scanner structure at %p\n", 920141cc406Sopenharmony_ci me, 921141cc406Sopenharmony_ci (void *) pss); 922141cc406Sopenharmony_ci } 923141cc406Sopenharmony_ci status = snapscani_usb_shm_init(); 924141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 925141cc406Sopenharmony_ci { 926141cc406Sopenharmony_ci return status; 927141cc406Sopenharmony_ci } 928141cc406Sopenharmony_ci status = open_scanner (pss); 929141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 930141cc406Sopenharmony_ci { 931141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 932141cc406Sopenharmony_ci "%s: open_scanner failed, status: %s\n", 933141cc406Sopenharmony_ci me, 934141cc406Sopenharmony_ci sane_strstatus (status)); 935141cc406Sopenharmony_ci free (pss); 936141cc406Sopenharmony_ci return SANE_STATUS_ACCESS_DENIED; 937141cc406Sopenharmony_ci } 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: waiting for scanner to warm up.\n", me); 940141cc406Sopenharmony_ci status = wait_scanner_ready (pss); 941141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 942141cc406Sopenharmony_ci { 943141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 944141cc406Sopenharmony_ci "%s: error waiting for scanner to warm up: %s\n", 945141cc406Sopenharmony_ci me, 946141cc406Sopenharmony_ci sane_strstatus(status)); 947141cc406Sopenharmony_ci free (pss); 948141cc406Sopenharmony_ci return status; 949141cc406Sopenharmony_ci } 950141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: performing scanner self test.\n", me); 951141cc406Sopenharmony_ci status = send_diagnostic (pss); 952141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 953141cc406Sopenharmony_ci { 954141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: send_diagnostic reports %s\n", 955141cc406Sopenharmony_ci me, sane_strstatus (status)); 956141cc406Sopenharmony_ci free (pss); 957141cc406Sopenharmony_ci return status; 958141cc406Sopenharmony_ci } 959141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: self test passed.\n", me); 960141cc406Sopenharmony_ci 961141cc406Sopenharmony_ci /* option initialization depends on getting the hardware configuration 962141cc406Sopenharmony_ci byte */ 963141cc406Sopenharmony_ci status = inquiry (pss); 964141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 965141cc406Sopenharmony_ci { 966141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 967141cc406Sopenharmony_ci "%s: error in inquiry command: %s\n", 968141cc406Sopenharmony_ci me, 969141cc406Sopenharmony_ci sane_strstatus (status)); 970141cc406Sopenharmony_ci free (pss); 971141cc406Sopenharmony_ci return status; 972141cc406Sopenharmony_ci } 973141cc406Sopenharmony_ci 974141cc406Sopenharmony_ci if (pss->pdev->bus == USB) 975141cc406Sopenharmony_ci { 976141cc406Sopenharmony_ci if (sanei_usb_get_vendor_product(pss->fd, &pss->usb_vendor, &pss->usb_product) != SANE_STATUS_GOOD) 977141cc406Sopenharmony_ci { 978141cc406Sopenharmony_ci pss->usb_vendor = 0; 979141cc406Sopenharmony_ci pss->usb_product = 0; 980141cc406Sopenharmony_ci } 981141cc406Sopenharmony_ci /* Download Firmware for USB scanners */ 982141cc406Sopenharmony_ci if (pss->hwst & 0x02) 983141cc406Sopenharmony_ci { 984141cc406Sopenharmony_ci char vendor[8]; 985141cc406Sopenharmony_ci char model[17]; 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci status = download_firmware(pss); 988141cc406Sopenharmony_ci CHECK_STATUS (status, me, "download_firmware"); 989141cc406Sopenharmony_ci /* send inquiry command again, wait for scanner to initialize */ 990141cc406Sopenharmony_ci status = wait_scanner_ready(pss); 991141cc406Sopenharmony_ci CHECK_STATUS (status, me, "wait_scanner_ready after firmware upload"); 992141cc406Sopenharmony_ci status = mini_inquiry (pss->pdev->bus, pss->fd, vendor, model); 993141cc406Sopenharmony_ci CHECK_STATUS (status, me, "mini_inquiry after firmware upload"); 994141cc406Sopenharmony_ci /* The model identifier may change after firmware upload */ 995141cc406Sopenharmony_ci DBG (DL_INFO, 996141cc406Sopenharmony_ci "%s (after firmware upload): Checking if \"%s\" is a supported scanner\n", 997141cc406Sopenharmony_ci me, 998141cc406Sopenharmony_ci model); 999141cc406Sopenharmony_ci /* Check if it is one of our supported models */ 1000141cc406Sopenharmony_ci pss->pdev->model = snapscani_get_model_id(model, pss->fd, pss->pdev->bus); 1001141cc406Sopenharmony_ci 1002141cc406Sopenharmony_ci if (pss->pdev->model == UNKNOWN) { 1003141cc406Sopenharmony_ci DBG (DL_MINOR_ERROR, 1004141cc406Sopenharmony_ci "%s (after firmware upload): \"%s\" is not a supported scanner\n", 1005141cc406Sopenharmony_ci me, 1006141cc406Sopenharmony_ci model); 1007141cc406Sopenharmony_ci } 1008141cc406Sopenharmony_ci /* run "real" inquiry command once again for option initialization */ 1009141cc406Sopenharmony_ci status = inquiry (pss); 1010141cc406Sopenharmony_ci CHECK_STATUS (status, me, "inquiry after firmware upload"); 1011141cc406Sopenharmony_ci } 1012141cc406Sopenharmony_ci } 1013141cc406Sopenharmony_ci close_scanner(pss); 1014141cc406Sopenharmony_ci 1015141cc406Sopenharmony_ci status = alloc_gamma_tables (pss); 1016141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1017141cc406Sopenharmony_ci { 1018141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1019141cc406Sopenharmony_ci "%s: error in alloc_gamma_tables: %s\n", 1020141cc406Sopenharmony_ci me, 1021141cc406Sopenharmony_ci sane_strstatus (status)); 1022141cc406Sopenharmony_ci free (pss); 1023141cc406Sopenharmony_ci return status; 1024141cc406Sopenharmony_ci } 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci init_options (pss); 1027141cc406Sopenharmony_ci status = init_gamma (pss); 1028141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1029141cc406Sopenharmony_ci { 1030141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1031141cc406Sopenharmony_ci "%s: error in init_gamma: %s\n", 1032141cc406Sopenharmony_ci me, 1033141cc406Sopenharmony_ci sane_strstatus (status)); 1034141cc406Sopenharmony_ci free (pss); 1035141cc406Sopenharmony_ci return status; 1036141cc406Sopenharmony_ci } 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci pss->state = ST_IDLE; 1039141cc406Sopenharmony_ci } 1040141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1041141cc406Sopenharmony_ci} 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_civoid sane_close (SANE_Handle h) 1044141cc406Sopenharmony_ci{ 1045141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) h; 1046141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "sane_snapscan_close (%p)\n", (void *) h); 1047141cc406Sopenharmony_ci switch (pss->state) 1048141cc406Sopenharmony_ci { 1049141cc406Sopenharmony_ci case ST_SCAN_INIT: 1050141cc406Sopenharmony_ci case ST_SCANNING: 1051141cc406Sopenharmony_ci release_unit (pss); 1052141cc406Sopenharmony_ci break; 1053141cc406Sopenharmony_ci default: 1054141cc406Sopenharmony_ci break; 1055141cc406Sopenharmony_ci } 1056141cc406Sopenharmony_ci close_scanner (pss); 1057141cc406Sopenharmony_ci snapscani_usb_shm_exit(); 1058141cc406Sopenharmony_ci free (pss->gamma_tables); 1059141cc406Sopenharmony_ci free (pss->buf); 1060141cc406Sopenharmony_ci free (pss); 1061141cc406Sopenharmony_ci} 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_ci 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ciSANE_Status sane_get_parameters (SANE_Handle h, 1066141cc406Sopenharmony_ci SANE_Parameters *p) 1067141cc406Sopenharmony_ci{ 1068141cc406Sopenharmony_ci static const char *me = "sane_snapscan_get_parameters"; 1069141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) h; 1070141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1071141cc406Sopenharmony_ci SnapScan_Mode mode = actual_mode(pss); 1072141cc406Sopenharmony_ci 1073141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s (%p, %p)\n", me, (void *) h, (void *) p); 1074141cc406Sopenharmony_ci 1075141cc406Sopenharmony_ci p->last_frame = SANE_TRUE; /* we always do only one frame */ 1076141cc406Sopenharmony_ci 1077141cc406Sopenharmony_ci if ((pss->state == ST_SCAN_INIT) || (pss->state == ST_SCANNING)) 1078141cc406Sopenharmony_ci { 1079141cc406Sopenharmony_ci /* we are in the middle of a scan, so we can use the data 1080141cc406Sopenharmony_ci that the scanner has reported */ 1081141cc406Sopenharmony_ci if (pss->psrc != NULL) 1082141cc406Sopenharmony_ci { 1083141cc406Sopenharmony_ci DBG(DL_DATA_TRACE, "%s: Using source chain data\n", me); 1084141cc406Sopenharmony_ci /* use what the source chain says */ 1085141cc406Sopenharmony_ci p->pixels_per_line = pss->psrc->pixelsPerLine(pss->psrc); 1086141cc406Sopenharmony_ci p->bytes_per_line = pss->psrc->bytesPerLine(pss->psrc); 1087141cc406Sopenharmony_ci /* p->lines = pss->psrc->remaining(pss->psrc)/p->bytes_per_line; */ 1088141cc406Sopenharmony_ci p->lines = pss->lines; 1089141cc406Sopenharmony_ci } 1090141cc406Sopenharmony_ci else 1091141cc406Sopenharmony_ci { 1092141cc406Sopenharmony_ci DBG(DL_DATA_TRACE, "%s: Using current data\n", me); 1093141cc406Sopenharmony_ci /* estimate based on current data */ 1094141cc406Sopenharmony_ci p->pixels_per_line = pss->pixels_per_line; 1095141cc406Sopenharmony_ci p->bytes_per_line = pss->bytes_per_line; 1096141cc406Sopenharmony_ci p->lines = pss->lines; 1097141cc406Sopenharmony_ci if (mode == MD_BILEVELCOLOUR) 1098141cc406Sopenharmony_ci p->bytes_per_line = p->pixels_per_line*3; 1099141cc406Sopenharmony_ci } 1100141cc406Sopenharmony_ci } 1101141cc406Sopenharmony_ci else 1102141cc406Sopenharmony_ci { 1103141cc406Sopenharmony_ci /* no scan in progress. The scanner data may not be up to date. 1104141cc406Sopenharmony_ci we have to calculate an estimate. */ 1105141cc406Sopenharmony_ci double width, height; 1106141cc406Sopenharmony_ci int dpi; 1107141cc406Sopenharmony_ci double dots_per_mm; 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci DBG(DL_DATA_TRACE, "%s: Using estimated data\n", me); 1110141cc406Sopenharmony_ci width = SANE_UNFIX (pss->brx - pss->tlx); 1111141cc406Sopenharmony_ci height = SANE_UNFIX (pss->bry - pss->tly); 1112141cc406Sopenharmony_ci dpi = pss->res; 1113141cc406Sopenharmony_ci dots_per_mm = dpi / MM_PER_IN; 1114141cc406Sopenharmony_ci p->pixels_per_line = width * dots_per_mm; 1115141cc406Sopenharmony_ci p->lines = height * dots_per_mm; 1116141cc406Sopenharmony_ci switch (mode) 1117141cc406Sopenharmony_ci { 1118141cc406Sopenharmony_ci case MD_COLOUR: 1119141cc406Sopenharmony_ci case MD_BILEVELCOLOUR: 1120141cc406Sopenharmony_ci p->bytes_per_line = 3 * p->pixels_per_line * ((pss->bpp_scan+7)/8); 1121141cc406Sopenharmony_ci break; 1122141cc406Sopenharmony_ci case MD_LINEART: 1123141cc406Sopenharmony_ci p->bytes_per_line = (p->pixels_per_line + 7) / 8; 1124141cc406Sopenharmony_ci break; 1125141cc406Sopenharmony_ci default: 1126141cc406Sopenharmony_ci /* greyscale */ 1127141cc406Sopenharmony_ci p->bytes_per_line = p->pixels_per_line * ((pss->bpp_scan+7)/8); 1128141cc406Sopenharmony_ci break; 1129141cc406Sopenharmony_ci } 1130141cc406Sopenharmony_ci } 1131141cc406Sopenharmony_ci p->format = (is_colour_mode(mode)) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; 1132141cc406Sopenharmony_ci if (mode == MD_LINEART) 1133141cc406Sopenharmony_ci p->depth = 1; 1134141cc406Sopenharmony_ci else if (pss->pdev->model == SCANWIT2720S) 1135141cc406Sopenharmony_ci p->depth = 16; 1136141cc406Sopenharmony_ci else if (pss->preview) 1137141cc406Sopenharmony_ci p->depth = 8; 1138141cc406Sopenharmony_ci else 1139141cc406Sopenharmony_ci p->depth = pss->val[OPT_BIT_DEPTH].w; 1140141cc406Sopenharmony_ci 1141141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: depth = %ld\n", me, (long) p->depth); 1142141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: lines = %ld\n", me, (long) p->lines); 1143141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 1144141cc406Sopenharmony_ci "%s: pixels per line = %ld\n", 1145141cc406Sopenharmony_ci me, 1146141cc406Sopenharmony_ci (long) p->pixels_per_line); 1147141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 1148141cc406Sopenharmony_ci "%s: bytes per line = %ld\n", 1149141cc406Sopenharmony_ci me, 1150141cc406Sopenharmony_ci (long) p->bytes_per_line); 1151141cc406Sopenharmony_ci 1152141cc406Sopenharmony_ci return status; 1153141cc406Sopenharmony_ci} 1154141cc406Sopenharmony_ci 1155141cc406Sopenharmony_ci/* scan data reader routine for child process */ 1156141cc406Sopenharmony_ci 1157141cc406Sopenharmony_ci#define READER_WRITE_SIZE 4096 1158141cc406Sopenharmony_ci 1159141cc406Sopenharmony_cistatic void reader (SnapScan_Scanner *pss) 1160141cc406Sopenharmony_ci{ 1161141cc406Sopenharmony_ci static char me[] = "Child reader process"; 1162141cc406Sopenharmony_ci SANE_Status status; 1163141cc406Sopenharmony_ci SANE_Byte *wbuf = NULL; 1164141cc406Sopenharmony_ci 1165141cc406Sopenharmony_ci 1166141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1167141cc406Sopenharmony_ci 1168141cc406Sopenharmony_ci wbuf = (SANE_Byte*) malloc(READER_WRITE_SIZE); 1169141cc406Sopenharmony_ci if (wbuf == NULL) 1170141cc406Sopenharmony_ci { 1171141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: failed to allocate write buffer.\n", me); 1172141cc406Sopenharmony_ci return; 1173141cc406Sopenharmony_ci } 1174141cc406Sopenharmony_ci 1175141cc406Sopenharmony_ci while ((pss->preadersrc->remaining(pss->preadersrc) > 0) && !cancelRead) 1176141cc406Sopenharmony_ci { 1177141cc406Sopenharmony_ci SANE_Int ndata = READER_WRITE_SIZE; 1178141cc406Sopenharmony_ci status = pss->preadersrc->get(pss->preadersrc, wbuf, &ndata); 1179141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1180141cc406Sopenharmony_ci { 1181141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1182141cc406Sopenharmony_ci "%s: %s on read.\n", 1183141cc406Sopenharmony_ci me, 1184141cc406Sopenharmony_ci sane_strstatus (status)); 1185141cc406Sopenharmony_ci return; 1186141cc406Sopenharmony_ci } 1187141cc406Sopenharmony_ci { 1188141cc406Sopenharmony_ci SANE_Byte *buf = wbuf; 1189141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "READ %d BYTES (%d)\n", ndata, cancelRead); 1190141cc406Sopenharmony_ci while (ndata > 0) 1191141cc406Sopenharmony_ci { 1192141cc406Sopenharmony_ci int written = write (pss->rpipe[1], buf, ndata); 1193141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "WROTE %d BYTES\n", written); 1194141cc406Sopenharmony_ci if (written == -1) 1195141cc406Sopenharmony_ci { 1196141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1197141cc406Sopenharmony_ci "%s: error writing scan data on parent pipe.\n", 1198141cc406Sopenharmony_ci me); 1199141cc406Sopenharmony_ci perror ("pipe error: "); 1200141cc406Sopenharmony_ci } 1201141cc406Sopenharmony_ci else 1202141cc406Sopenharmony_ci { 1203141cc406Sopenharmony_ci ndata -= written; 1204141cc406Sopenharmony_ci buf += written; 1205141cc406Sopenharmony_ci } 1206141cc406Sopenharmony_ci } 1207141cc406Sopenharmony_ci } 1208141cc406Sopenharmony_ci } 1209141cc406Sopenharmony_ci} 1210141cc406Sopenharmony_ci 1211141cc406Sopenharmony_ci/** signal handler to kill the child process 1212141cc406Sopenharmony_ci */ 1213141cc406Sopenharmony_cistatic void usb_reader_process_sigterm_handler( int signo ) 1214141cc406Sopenharmony_ci{ 1215141cc406Sopenharmony_ci DBG( DL_INFO, "(SIG) reader_process: terminated by signal %d\n", signo ); 1216141cc406Sopenharmony_ci cancelRead = SANE_TRUE; 1217141cc406Sopenharmony_ci} 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_cistatic void sigalarm_handler( int signo __sane_unused__) 1220141cc406Sopenharmony_ci{ 1221141cc406Sopenharmony_ci DBG( DL_INFO, "ALARM!!!\n" ); 1222141cc406Sopenharmony_ci} 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci/** executed as a child process 1225141cc406Sopenharmony_ci * read the data from the driver and send them to the parent process 1226141cc406Sopenharmony_ci */ 1227141cc406Sopenharmony_cistatic int reader_process( void *args ) 1228141cc406Sopenharmony_ci{ 1229141cc406Sopenharmony_ci SANE_Status status; 1230141cc406Sopenharmony_ci struct SIGACTION act; 1231141cc406Sopenharmony_ci sigset_t ignore_set; 1232141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) args; 1233141cc406Sopenharmony_ci 1234141cc406Sopenharmony_ci if( sanei_thread_is_forked()) { 1235141cc406Sopenharmony_ci DBG( DL_MINOR_INFO, "reader_process started (forked)\n" ); 1236141cc406Sopenharmony_ci /* child process - close read side, make stdout the write side of the pipe */ 1237141cc406Sopenharmony_ci close( pss->rpipe[0] ); 1238141cc406Sopenharmony_ci pss->rpipe[0] = -1; 1239141cc406Sopenharmony_ci } else { 1240141cc406Sopenharmony_ci DBG( DL_MINOR_INFO, "reader_process started (as thread)\n" ); 1241141cc406Sopenharmony_ci } 1242141cc406Sopenharmony_ci 1243141cc406Sopenharmony_ci sigfillset ( &ignore_set ); 1244141cc406Sopenharmony_ci sigdelset ( &ignore_set, SIGUSR1 ); 1245141cc406Sopenharmony_ci sigprocmask( SIG_SETMASK, &ignore_set, 0 ); 1246141cc406Sopenharmony_ci 1247141cc406Sopenharmony_ci memset ( &act, 0, sizeof (act)); 1248141cc406Sopenharmony_ci sigaction( SIGTERM, &act, 0 ); 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci cancelRead = SANE_FALSE; 1251141cc406Sopenharmony_ci 1252141cc406Sopenharmony_ci /* install the signal handler */ 1253141cc406Sopenharmony_ci sigemptyset(&(act.sa_mask)); 1254141cc406Sopenharmony_ci act.sa_flags = 0; 1255141cc406Sopenharmony_ci 1256141cc406Sopenharmony_ci act.sa_handler = usb_reader_process_sigterm_handler; 1257141cc406Sopenharmony_ci sigaction( SIGUSR1, &act, 0 ); 1258141cc406Sopenharmony_ci 1259141cc406Sopenharmony_ci status = create_base_source (pss, SCSI_SRC, &(pss->preadersrc)); 1260141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1261141cc406Sopenharmony_ci { 1262141cc406Sopenharmony_ci reader (pss); 1263141cc406Sopenharmony_ci } 1264141cc406Sopenharmony_ci else 1265141cc406Sopenharmony_ci { 1266141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1267141cc406Sopenharmony_ci "Reader process: failed to create SCSISource.\n"); 1268141cc406Sopenharmony_ci } 1269141cc406Sopenharmony_ci pss->preadersrc->done(pss->preadersrc); 1270141cc406Sopenharmony_ci free(pss->preadersrc); 1271141cc406Sopenharmony_ci pss->preadersrc = 0; 1272141cc406Sopenharmony_ci close( pss->rpipe[1] ); 1273141cc406Sopenharmony_ci pss->rpipe[1] = -1; 1274141cc406Sopenharmony_ci DBG( DL_MINOR_INFO, "reader_process: finished reading data\n" ); 1275141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1276141cc406Sopenharmony_ci} 1277141cc406Sopenharmony_ci 1278141cc406Sopenharmony_ci 1279141cc406Sopenharmony_cistatic SANE_Status start_reader (SnapScan_Scanner *pss) 1280141cc406Sopenharmony_ci{ 1281141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1282141cc406Sopenharmony_ci static char me[] = "start_reader"; 1283141cc406Sopenharmony_ci 1284141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1285141cc406Sopenharmony_ci 1286141cc406Sopenharmony_ci pss->nonblocking = SANE_FALSE; 1287141cc406Sopenharmony_ci pss->rpipe[0] = pss->rpipe[1] = -1; 1288141cc406Sopenharmony_ci sanei_thread_initialize (pss->child); 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci if (pipe (pss->rpipe) != -1) 1291141cc406Sopenharmony_ci { 1292141cc406Sopenharmony_ci pss->orig_rpipe_flags = fcntl (pss->rpipe[0], F_GETFL, 0); 1293141cc406Sopenharmony_ci pss->child = sanei_thread_begin(reader_process, (void *) pss); 1294141cc406Sopenharmony_ci 1295141cc406Sopenharmony_ci cancelRead = SANE_FALSE; 1296141cc406Sopenharmony_ci 1297141cc406Sopenharmony_ci if (!sanei_thread_is_valid (pss->child)) 1298141cc406Sopenharmony_ci { 1299141cc406Sopenharmony_ci /* we'll have to read in blocking mode */ 1300141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1301141cc406Sopenharmony_ci "%s: Error while calling sanei_thread_begin; must read in blocking mode.\n", 1302141cc406Sopenharmony_ci me); 1303141cc406Sopenharmony_ci close (pss->rpipe[0]); 1304141cc406Sopenharmony_ci close (pss->rpipe[1]); 1305141cc406Sopenharmony_ci status = SANE_STATUS_UNSUPPORTED; 1306141cc406Sopenharmony_ci } 1307141cc406Sopenharmony_ci if (sanei_thread_is_forked()) 1308141cc406Sopenharmony_ci { 1309141cc406Sopenharmony_ci /* parent; close write side */ 1310141cc406Sopenharmony_ci close (pss->rpipe[1]); 1311141cc406Sopenharmony_ci pss->rpipe[1] = -1; 1312141cc406Sopenharmony_ci } 1313141cc406Sopenharmony_ci pss->nonblocking = SANE_TRUE; 1314141cc406Sopenharmony_ci } 1315141cc406Sopenharmony_ci return status; 1316141cc406Sopenharmony_ci} 1317141cc406Sopenharmony_ci 1318141cc406Sopenharmony_cistatic SANE_Status send_gamma_table (SnapScan_Scanner *pss, u_char dtc, u_char dtcq) 1319141cc406Sopenharmony_ci{ 1320141cc406Sopenharmony_ci static char me[] = "send_gamma_table"; 1321141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1322141cc406Sopenharmony_ci status = send (pss, dtc, dtcq); 1323141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1324141cc406Sopenharmony_ci switch (pss->pdev->model) 1325141cc406Sopenharmony_ci { 1326141cc406Sopenharmony_ci case PERFECTION1270: 1327141cc406Sopenharmony_ci case PERFECTION1670: 1328141cc406Sopenharmony_ci case PERFECTION2480: 1329141cc406Sopenharmony_ci case PERFECTION3490: 1330141cc406Sopenharmony_ci /* Some epson scanners need the gamma table twice */ 1331141cc406Sopenharmony_ci status = send (pss, dtc, dtcq); 1332141cc406Sopenharmony_ci CHECK_STATUS (status, me, "2nd send"); 1333141cc406Sopenharmony_ci break; 1334141cc406Sopenharmony_ci case PRISA5150: 1335141cc406Sopenharmony_ci /* 5150 needs the gamma table twice, with dtc = 0x04 for the second one */ 1336141cc406Sopenharmony_ci status = send (pss, DTC_GAMMA2, dtcq); 1337141cc406Sopenharmony_ci CHECK_STATUS (status, me, "2nd send"); 1338141cc406Sopenharmony_ci break; 1339141cc406Sopenharmony_ci default: 1340141cc406Sopenharmony_ci break; 1341141cc406Sopenharmony_ci } 1342141cc406Sopenharmony_ci return status; 1343141cc406Sopenharmony_ci} 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_cistatic SANE_Status download_gamma_tables (SnapScan_Scanner *pss) 1346141cc406Sopenharmony_ci{ 1347141cc406Sopenharmony_ci static char me[] = "download_gamma_tables"; 1348141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1349141cc406Sopenharmony_ci double gamma_gs = SANE_UNFIX (pss->gamma_gs); 1350141cc406Sopenharmony_ci double gamma_r = SANE_UNFIX (pss->gamma_r); 1351141cc406Sopenharmony_ci double gamma_g = SANE_UNFIX (pss->gamma_g); 1352141cc406Sopenharmony_ci double gamma_b = SANE_UNFIX (pss->gamma_b); 1353141cc406Sopenharmony_ci SnapScan_Mode mode = actual_mode (pss); 1354141cc406Sopenharmony_ci int dtcq_gamma_gray; 1355141cc406Sopenharmony_ci int dtcq_gamma_red; 1356141cc406Sopenharmony_ci int dtcq_gamma_green; 1357141cc406Sopenharmony_ci int dtcq_gamma_blue; 1358141cc406Sopenharmony_ci int gamma_mode = GAMMA_8BIT; 1359141cc406Sopenharmony_ci 1360141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1361141cc406Sopenharmony_ci switch (mode) 1362141cc406Sopenharmony_ci { 1363141cc406Sopenharmony_ci case MD_COLOUR: 1364141cc406Sopenharmony_ci break; 1365141cc406Sopenharmony_ci case MD_BILEVELCOLOUR: 1366141cc406Sopenharmony_ci if (!pss->halftone) 1367141cc406Sopenharmony_ci { 1368141cc406Sopenharmony_ci gamma_r = 1369141cc406Sopenharmony_ci gamma_g = 1370141cc406Sopenharmony_ci gamma_b = 1.0; 1371141cc406Sopenharmony_ci } 1372141cc406Sopenharmony_ci break; 1373141cc406Sopenharmony_ci case MD_LINEART: 1374141cc406Sopenharmony_ci if (!pss->halftone) 1375141cc406Sopenharmony_ci gamma_gs = 1.0; 1376141cc406Sopenharmony_ci break; 1377141cc406Sopenharmony_ci default: 1378141cc406Sopenharmony_ci /* no further action for greyscale */ 1379141cc406Sopenharmony_ci break; 1380141cc406Sopenharmony_ci } 1381141cc406Sopenharmony_ci 1382141cc406Sopenharmony_ci switch (pss->bpp) 1383141cc406Sopenharmony_ci { 1384141cc406Sopenharmony_ci case 10: 1385141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); 1386141cc406Sopenharmony_ci dtcq_gamma_gray = DTCQ_GAMMA_GRAY10; 1387141cc406Sopenharmony_ci dtcq_gamma_red = DTCQ_GAMMA_RED10; 1388141cc406Sopenharmony_ci dtcq_gamma_green = DTCQ_GAMMA_GREEN10; 1389141cc406Sopenharmony_ci dtcq_gamma_blue = DTCQ_GAMMA_BLUE10; 1390141cc406Sopenharmony_ci break; 1391141cc406Sopenharmony_ci case 12: 1392141cc406Sopenharmony_ci if (pss->pdev->model == SCANWIT2720S) 1393141cc406Sopenharmony_ci { 1394141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: Sending 16bit gamma table for %d bpp\n", me, pss->bpp); 1395141cc406Sopenharmony_ci dtcq_gamma_gray = DTCQ_GAMMA_GRAY12_16BIT; 1396141cc406Sopenharmony_ci dtcq_gamma_red = DTCQ_GAMMA_RED12_16BIT; 1397141cc406Sopenharmony_ci dtcq_gamma_green = DTCQ_GAMMA_GREEN12_16BIT; 1398141cc406Sopenharmony_ci dtcq_gamma_blue = DTCQ_GAMMA_BLUE12_16BIT; 1399141cc406Sopenharmony_ci gamma_mode = GAMMA_12_16BIT; 1400141cc406Sopenharmony_ci } 1401141cc406Sopenharmony_ci else 1402141cc406Sopenharmony_ci { 1403141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); 1404141cc406Sopenharmony_ci dtcq_gamma_gray = DTCQ_GAMMA_GRAY12; 1405141cc406Sopenharmony_ci dtcq_gamma_red = DTCQ_GAMMA_RED12; 1406141cc406Sopenharmony_ci dtcq_gamma_green = DTCQ_GAMMA_GREEN12; 1407141cc406Sopenharmony_ci dtcq_gamma_blue = DTCQ_GAMMA_BLUE12; 1408141cc406Sopenharmony_ci } 1409141cc406Sopenharmony_ci break; 1410141cc406Sopenharmony_ci case 14: 1411141cc406Sopenharmony_ci if (pss->bpp_scan == 16) 1412141cc406Sopenharmony_ci { 1413141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: Sending 16bit gamma table for %d bpp\n", me, pss->bpp); 1414141cc406Sopenharmony_ci dtcq_gamma_gray = DTCQ_GAMMA_GRAY14_16BIT; 1415141cc406Sopenharmony_ci dtcq_gamma_red = DTCQ_GAMMA_RED14_16BIT; 1416141cc406Sopenharmony_ci dtcq_gamma_green = DTCQ_GAMMA_GREEN14_16BIT; 1417141cc406Sopenharmony_ci dtcq_gamma_blue = DTCQ_GAMMA_BLUE14_16BIT; 1418141cc406Sopenharmony_ci gamma_mode = GAMMA_16BIT; 1419141cc406Sopenharmony_ci } 1420141cc406Sopenharmony_ci else 1421141cc406Sopenharmony_ci { 1422141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); 1423141cc406Sopenharmony_ci dtcq_gamma_gray = DTCQ_GAMMA_GRAY14; 1424141cc406Sopenharmony_ci dtcq_gamma_red = DTCQ_GAMMA_RED14; 1425141cc406Sopenharmony_ci dtcq_gamma_green = DTCQ_GAMMA_GREEN14; 1426141cc406Sopenharmony_ci dtcq_gamma_blue = DTCQ_GAMMA_BLUE14; 1427141cc406Sopenharmony_ci } 1428141cc406Sopenharmony_ci break; 1429141cc406Sopenharmony_ci default: 1430141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); 1431141cc406Sopenharmony_ci dtcq_gamma_gray = DTCQ_GAMMA_GRAY8; 1432141cc406Sopenharmony_ci dtcq_gamma_red = DTCQ_GAMMA_RED8; 1433141cc406Sopenharmony_ci dtcq_gamma_green = DTCQ_GAMMA_GREEN8; 1434141cc406Sopenharmony_ci dtcq_gamma_blue = DTCQ_GAMMA_BLUE8; 1435141cc406Sopenharmony_ci break; 1436141cc406Sopenharmony_ci } 1437141cc406Sopenharmony_ci 1438141cc406Sopenharmony_ci if (is_colour_mode(mode)) 1439141cc406Sopenharmony_ci { 1440141cc406Sopenharmony_ci if (pss->val[OPT_CUSTOM_GAMMA].b) 1441141cc406Sopenharmony_ci { 1442141cc406Sopenharmony_ci if (pss->val[OPT_GAMMA_BIND].b) 1443141cc406Sopenharmony_ci { 1444141cc406Sopenharmony_ci /* Use greyscale gamma for all rgb channels */ 1445141cc406Sopenharmony_ci gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, 1446141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, gamma_mode); 1447141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); 1448141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_ci gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, 1451141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, gamma_mode); 1452141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); 1453141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1454141cc406Sopenharmony_ci 1455141cc406Sopenharmony_ci gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, 1456141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, gamma_mode); 1457141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); 1458141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1459141cc406Sopenharmony_ci } 1460141cc406Sopenharmony_ci else 1461141cc406Sopenharmony_ci { 1462141cc406Sopenharmony_ci gamma_from_sane (pss->gamma_length, pss->gamma_table_r, 1463141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, gamma_mode); 1464141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); 1465141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1466141cc406Sopenharmony_ci 1467141cc406Sopenharmony_ci gamma_from_sane (pss->gamma_length, pss->gamma_table_g, 1468141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, gamma_mode); 1469141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); 1470141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1471141cc406Sopenharmony_ci 1472141cc406Sopenharmony_ci gamma_from_sane (pss->gamma_length, pss->gamma_table_b, 1473141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, gamma_mode); 1474141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); 1475141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1476141cc406Sopenharmony_ci } 1477141cc406Sopenharmony_ci } 1478141cc406Sopenharmony_ci else 1479141cc406Sopenharmony_ci { 1480141cc406Sopenharmony_ci if (pss->val[OPT_GAMMA_BIND].b) 1481141cc406Sopenharmony_ci { 1482141cc406Sopenharmony_ci /* Use greyscale gamma for all rgb channels */ 1483141cc406Sopenharmony_ci gamma_n (gamma_gs, pss->bright, pss->contrast, 1484141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); 1485141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); 1486141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1487141cc406Sopenharmony_ci 1488141cc406Sopenharmony_ci gamma_n (gamma_gs, pss->bright, pss->contrast, 1489141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); 1490141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); 1491141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1492141cc406Sopenharmony_ci 1493141cc406Sopenharmony_ci gamma_n (gamma_gs, pss->bright, pss->contrast, 1494141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); 1495141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); 1496141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1497141cc406Sopenharmony_ci } 1498141cc406Sopenharmony_ci else 1499141cc406Sopenharmony_ci { 1500141cc406Sopenharmony_ci gamma_n (gamma_r, pss->bright, pss->contrast, 1501141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); 1502141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); 1503141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1504141cc406Sopenharmony_ci 1505141cc406Sopenharmony_ci gamma_n (gamma_g, pss->bright, pss->contrast, 1506141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); 1507141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); 1508141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1509141cc406Sopenharmony_ci 1510141cc406Sopenharmony_ci gamma_n (gamma_b, pss->bright, pss->contrast, 1511141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); 1512141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); 1513141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1514141cc406Sopenharmony_ci } 1515141cc406Sopenharmony_ci } 1516141cc406Sopenharmony_ci } 1517141cc406Sopenharmony_ci else 1518141cc406Sopenharmony_ci { 1519141cc406Sopenharmony_ci if(pss->val[OPT_CUSTOM_GAMMA].b) 1520141cc406Sopenharmony_ci { 1521141cc406Sopenharmony_ci gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, 1522141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, gamma_mode); 1523141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_gray); 1524141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1525141cc406Sopenharmony_ci } 1526141cc406Sopenharmony_ci else 1527141cc406Sopenharmony_ci { 1528141cc406Sopenharmony_ci gamma_n (gamma_gs, pss->bright, pss->contrast, 1529141cc406Sopenharmony_ci pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); 1530141cc406Sopenharmony_ci status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_gray); 1531141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1532141cc406Sopenharmony_ci } 1533141cc406Sopenharmony_ci } 1534141cc406Sopenharmony_ci return status; 1535141cc406Sopenharmony_ci} 1536141cc406Sopenharmony_ci 1537141cc406Sopenharmony_cistatic SANE_Status download_halftone_matrices (SnapScan_Scanner *pss) 1538141cc406Sopenharmony_ci{ 1539141cc406Sopenharmony_ci static char me[] = "download_halftone_matrices"; 1540141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1541141cc406Sopenharmony_ci if ((pss->halftone) && 1542141cc406Sopenharmony_ci ((actual_mode(pss) == MD_LINEART) || (actual_mode(pss) == MD_BILEVELCOLOUR))) 1543141cc406Sopenharmony_ci { 1544141cc406Sopenharmony_ci u_char *matrix; 1545141cc406Sopenharmony_ci size_t matrix_sz; 1546141cc406Sopenharmony_ci u_char dtcq; 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci if (pss->dither_matrix == dm_dd8x8) 1549141cc406Sopenharmony_ci { 1550141cc406Sopenharmony_ci matrix = D8; 1551141cc406Sopenharmony_ci matrix_sz = sizeof (D8); 1552141cc406Sopenharmony_ci } 1553141cc406Sopenharmony_ci else 1554141cc406Sopenharmony_ci { 1555141cc406Sopenharmony_ci matrix = D16; 1556141cc406Sopenharmony_ci matrix_sz = sizeof (D16); 1557141cc406Sopenharmony_ci } 1558141cc406Sopenharmony_ci 1559141cc406Sopenharmony_ci memcpy (pss->buf + SEND_LENGTH, matrix, matrix_sz); 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci if (is_colour_mode(actual_mode(pss))) 1562141cc406Sopenharmony_ci { 1563141cc406Sopenharmony_ci if (matrix_sz == sizeof (D8)) 1564141cc406Sopenharmony_ci dtcq = DTCQ_HALFTONE_COLOR8; 1565141cc406Sopenharmony_ci else 1566141cc406Sopenharmony_ci dtcq = DTCQ_HALFTONE_COLOR16; 1567141cc406Sopenharmony_ci 1568141cc406Sopenharmony_ci /* need copies for green and blue bands */ 1569141cc406Sopenharmony_ci memcpy (pss->buf + SEND_LENGTH + matrix_sz, 1570141cc406Sopenharmony_ci matrix, 1571141cc406Sopenharmony_ci matrix_sz); 1572141cc406Sopenharmony_ci memcpy (pss->buf + SEND_LENGTH + 2 * matrix_sz, 1573141cc406Sopenharmony_ci matrix, 1574141cc406Sopenharmony_ci matrix_sz); 1575141cc406Sopenharmony_ci } 1576141cc406Sopenharmony_ci else 1577141cc406Sopenharmony_ci { 1578141cc406Sopenharmony_ci if (matrix_sz == sizeof (D8)) 1579141cc406Sopenharmony_ci dtcq = DTCQ_HALFTONE_BW8; 1580141cc406Sopenharmony_ci else 1581141cc406Sopenharmony_ci dtcq = DTCQ_HALFTONE_BW16; 1582141cc406Sopenharmony_ci } 1583141cc406Sopenharmony_ci 1584141cc406Sopenharmony_ci status = send (pss, DTC_HALFTONE, dtcq); 1585141cc406Sopenharmony_ci CHECK_STATUS (status, me, "send"); 1586141cc406Sopenharmony_ci } 1587141cc406Sopenharmony_ci return status; 1588141cc406Sopenharmony_ci} 1589141cc406Sopenharmony_ci 1590141cc406Sopenharmony_cistatic SANE_Status measure_transfer_rate (SnapScan_Scanner *pss) 1591141cc406Sopenharmony_ci{ 1592141cc406Sopenharmony_ci static char me[] = "measure_transfer_rate"; 1593141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1594141cc406Sopenharmony_ci 1595141cc406Sopenharmony_ci if (pss->hconfig & HCFG_RB) 1596141cc406Sopenharmony_ci { 1597141cc406Sopenharmony_ci /* We have a ring buffer. We simulate one round of a read-store 1598141cc406Sopenharmony_ci cycle on the size of buffer we will be using. For this read only, 1599141cc406Sopenharmony_ci the buffer size must be rounded to a 128-byte boundary. */ 1600141cc406Sopenharmony_ci 1601141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: have ring buffer\n", me); 1602141cc406Sopenharmony_ci if ((pss->pdev->model == PERFECTION2480) || (pss->pdev->model == PERFECTION3490)) 1603141cc406Sopenharmony_ci { 1604141cc406Sopenharmony_ci /* Epson 2480: read a multiple of bytes per line, limit to less than 0xfff0 */ 1605141cc406Sopenharmony_ci if (pss->bytes_per_line > 0xfff0) 1606141cc406Sopenharmony_ci pss->expected_read_bytes = 0xfff0; 1607141cc406Sopenharmony_ci else 1608141cc406Sopenharmony_ci pss->expected_read_bytes = (0xfff0 / pss->bytes_per_line) * pss->bytes_per_line; 1609141cc406Sopenharmony_ci } 1610141cc406Sopenharmony_ci else 1611141cc406Sopenharmony_ci pss->expected_read_bytes = 1612141cc406Sopenharmony_ci (pss->buf_sz%128) ? (pss->buf_sz/128 + 1)*128 : pss->buf_sz; 1613141cc406Sopenharmony_ci 1614141cc406Sopenharmony_ci status = scsi_read (pss, READ_TRANSTIME); 1615141cc406Sopenharmony_ci CHECK_STATUS (status, me, "scsi_read"); 1616141cc406Sopenharmony_ci pss->expected_read_bytes = 0; 1617141cc406Sopenharmony_ci status = scsi_read (pss, READ_TRANSTIME); 1618141cc406Sopenharmony_ci CHECK_STATUS (status, me, "scsi_read"); 1619141cc406Sopenharmony_ci } 1620141cc406Sopenharmony_ci else 1621141cc406Sopenharmony_ci { 1622141cc406Sopenharmony_ci /* we don't have a ring buffer. The test requires transferring one 1623141cc406Sopenharmony_ci scan line of data (rounded up to next 128 byte boundary). */ 1624141cc406Sopenharmony_ci 1625141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: we don't have a ring buffer.\n", me); 1626141cc406Sopenharmony_ci pss->expected_read_bytes = pss->bytes_per_line; 1627141cc406Sopenharmony_ci 1628141cc406Sopenharmony_ci if (pss->expected_read_bytes%128) 1629141cc406Sopenharmony_ci { 1630141cc406Sopenharmony_ci pss->expected_read_bytes = 1631141cc406Sopenharmony_ci (pss->expected_read_bytes/128 + 1)*128; 1632141cc406Sopenharmony_ci } 1633141cc406Sopenharmony_ci status = scsi_read (pss, READ_TRANSTIME); 1634141cc406Sopenharmony_ci CHECK_STATUS (status, me, "scsi_read"); 1635141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: read %ld bytes.\n", me, (long) pss->read_bytes); 1636141cc406Sopenharmony_ci } 1637141cc406Sopenharmony_ci 1638141cc406Sopenharmony_ci pss->expected_read_bytes = 0; 1639141cc406Sopenharmony_ci status = scsi_read (pss, READ_TRANSTIME); 1640141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1641141cc406Sopenharmony_ci { 1642141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: test read failed.\n", me); 1643141cc406Sopenharmony_ci return status; 1644141cc406Sopenharmony_ci } 1645141cc406Sopenharmony_ci 1646141cc406Sopenharmony_ci DBG (DL_VERBOSE, "%s: successfully calibrated transfer rate.\n", me); 1647141cc406Sopenharmony_ci return status; 1648141cc406Sopenharmony_ci} 1649141cc406Sopenharmony_ci 1650141cc406Sopenharmony_ci 1651141cc406Sopenharmony_ciSANE_Status sane_start (SANE_Handle h) 1652141cc406Sopenharmony_ci{ 1653141cc406Sopenharmony_ci static const char *me = "sane_snapscan_start"; 1654141cc406Sopenharmony_ci SANE_Status status; 1655141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) h; 1656141cc406Sopenharmony_ci 1657141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s (%p)\n", me, (void *) h); 1658141cc406Sopenharmony_ci 1659141cc406Sopenharmony_ci /* possible authorization required */ 1660141cc406Sopenharmony_ci 1661141cc406Sopenharmony_ci status = open_scanner (pss); 1662141cc406Sopenharmony_ci CHECK_STATUS (status, me, "open_scanner"); 1663141cc406Sopenharmony_ci 1664141cc406Sopenharmony_ci status = wait_scanner_ready (pss); 1665141cc406Sopenharmony_ci CHECK_STATUS (status, me, "wait_scanner_ready"); 1666141cc406Sopenharmony_ci 1667141cc406Sopenharmony_ci /* start scanning; reserve the unit first, because a release_unit is 1668141cc406Sopenharmony_ci necessary to abort a scan in progress */ 1669141cc406Sopenharmony_ci 1670141cc406Sopenharmony_ci pss->state = ST_SCAN_INIT; 1671141cc406Sopenharmony_ci 1672141cc406Sopenharmony_ci if ((pss->pdev->model == SCANWIT2720S) && (pss->focus_mode == MD_AUTO)) 1673141cc406Sopenharmony_ci { 1674141cc406Sopenharmony_ci status = get_focus(pss); 1675141cc406Sopenharmony_ci CHECK_STATUS (status, me, "get_focus"); 1676141cc406Sopenharmony_ci } 1677141cc406Sopenharmony_ci 1678141cc406Sopenharmony_ci reserve_unit(pss); 1679141cc406Sopenharmony_ci 1680141cc406Sopenharmony_ci if (pss->pdev->model == SCANWIT2720S) 1681141cc406Sopenharmony_ci { 1682141cc406Sopenharmony_ci status = set_frame(pss, 0); 1683141cc406Sopenharmony_ci CHECK_STATUS (status, me, "set_frame"); 1684141cc406Sopenharmony_ci status = set_focus(pss, pss->focus); 1685141cc406Sopenharmony_ci CHECK_STATUS (status, me, "set_focus"); 1686141cc406Sopenharmony_ci } 1687141cc406Sopenharmony_ci 1688141cc406Sopenharmony_ci /* set up the window and fetch the resulting scanner parameters */ 1689141cc406Sopenharmony_ci status = set_window(pss); 1690141cc406Sopenharmony_ci CHECK_STATUS (status, me, "set_window"); 1691141cc406Sopenharmony_ci 1692141cc406Sopenharmony_ci status = inquiry(pss); 1693141cc406Sopenharmony_ci CHECK_STATUS (status, me, "inquiry"); 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci /* download the gamma and halftone tables */ 1696141cc406Sopenharmony_ci 1697141cc406Sopenharmony_ci status = download_gamma_tables(pss); 1698141cc406Sopenharmony_ci CHECK_STATUS (status, me, "download_gamma_tables"); 1699141cc406Sopenharmony_ci 1700141cc406Sopenharmony_ci status = download_halftone_matrices(pss); 1701141cc406Sopenharmony_ci CHECK_STATUS (status, me, "download_halftone_matrices"); 1702141cc406Sopenharmony_ci 1703141cc406Sopenharmony_ci if (pss->val[OPT_QUALITY_CAL].b && (pss->usb_vendor == USB_VENDOR_EPSON)) 1704141cc406Sopenharmony_ci { 1705141cc406Sopenharmony_ci status = calibrate(pss); 1706141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1707141cc406Sopenharmony_ci { 1708141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: calibration failed.\n", me); 1709141cc406Sopenharmony_ci release_unit (pss); 1710141cc406Sopenharmony_ci return status; 1711141cc406Sopenharmony_ci } 1712141cc406Sopenharmony_ci } 1713141cc406Sopenharmony_ci 1714141cc406Sopenharmony_ci /* we must measure the data transfer rate between the host and the 1715141cc406Sopenharmony_ci scanner, and the method varies depending on whether there is a 1716141cc406Sopenharmony_ci ring buffer or not. */ 1717141cc406Sopenharmony_ci 1718141cc406Sopenharmony_ci status = measure_transfer_rate(pss); 1719141cc406Sopenharmony_ci CHECK_STATUS (status, me, "measure_transfer_rate"); 1720141cc406Sopenharmony_ci 1721141cc406Sopenharmony_ci /* now perform an inquiry again to retrieve the scan speed */ 1722141cc406Sopenharmony_ci status = inquiry(pss); 1723141cc406Sopenharmony_ci CHECK_STATUS (status, me, "inquiry"); 1724141cc406Sopenharmony_ci 1725141cc406Sopenharmony_ci DBG (DL_DATA_TRACE, 1726141cc406Sopenharmony_ci "%s: after measuring speed:\n\t%lu bytes per scan line\n" 1727141cc406Sopenharmony_ci "\t%f milliseconds per scan line.\n\t==>%f bytes per millisecond\n", 1728141cc406Sopenharmony_ci me, 1729141cc406Sopenharmony_ci (u_long) pss->bytes_per_line, 1730141cc406Sopenharmony_ci pss->ms_per_line, 1731141cc406Sopenharmony_ci pss->bytes_per_line/pss->ms_per_line); 1732141cc406Sopenharmony_ci 1733141cc406Sopenharmony_ci 1734141cc406Sopenharmony_ci if (pss->val[OPT_QUALITY_CAL].b && (pss->usb_vendor != USB_VENDOR_EPSON)) 1735141cc406Sopenharmony_ci { 1736141cc406Sopenharmony_ci status = calibrate(pss); 1737141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1738141cc406Sopenharmony_ci { 1739141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: calibration failed.\n", me); 1740141cc406Sopenharmony_ci release_unit (pss); 1741141cc406Sopenharmony_ci return status; 1742141cc406Sopenharmony_ci } 1743141cc406Sopenharmony_ci } 1744141cc406Sopenharmony_ci 1745141cc406Sopenharmony_ci status = scan(pss); 1746141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1747141cc406Sopenharmony_ci { 1748141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: scan command failed: %s.\n", me, sane_strstatus(status)); 1749141cc406Sopenharmony_ci release_unit (pss); 1750141cc406Sopenharmony_ci return status; 1751141cc406Sopenharmony_ci } 1752141cc406Sopenharmony_ci 1753141cc406Sopenharmony_ci if (pss->pdev->model == SCANWIT2720S) 1754141cc406Sopenharmony_ci { 1755141cc406Sopenharmony_ci status = set_frame(pss, pss->frame_no); 1756141cc406Sopenharmony_ci CHECK_STATUS (status, me, "set_frame"); 1757141cc406Sopenharmony_ci } 1758141cc406Sopenharmony_ci 1759141cc406Sopenharmony_ci if (pss->source == SRC_ADF) 1760141cc406Sopenharmony_ci { 1761141cc406Sopenharmony_ci /* Wait for scanner ready again (e.g. until paper is loaded from an ADF) */ 1762141cc406Sopenharmony_ci /* Maybe replace with get_data_buffer_status()? */ 1763141cc406Sopenharmony_ci status = wait_scanner_ready (pss); 1764141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1765141cc406Sopenharmony_ci { 1766141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, "%s: scan command failed while waiting for scanner: %s.\n", me, sane_strstatus(status)); 1767141cc406Sopenharmony_ci release_unit (pss); 1768141cc406Sopenharmony_ci return status; 1769141cc406Sopenharmony_ci } 1770141cc406Sopenharmony_ci } 1771141cc406Sopenharmony_ci 1772141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: starting the reader process.\n", me); 1773141cc406Sopenharmony_ci status = start_reader(pss); 1774141cc406Sopenharmony_ci { 1775141cc406Sopenharmony_ci BaseSourceType st = FD_SRC; 1776141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1777141cc406Sopenharmony_ci st = SCSI_SRC; 1778141cc406Sopenharmony_ci status = create_source_chain (pss, st, &(pss->psrc)); 1779141cc406Sopenharmony_ci } 1780141cc406Sopenharmony_ci 1781141cc406Sopenharmony_ci return status; 1782141cc406Sopenharmony_ci} 1783141cc406Sopenharmony_ci 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ciSANE_Status sane_read (SANE_Handle h, 1786141cc406Sopenharmony_ci SANE_Byte *buf, 1787141cc406Sopenharmony_ci SANE_Int maxlen, 1788141cc406Sopenharmony_ci SANE_Int *plen) 1789141cc406Sopenharmony_ci{ 1790141cc406Sopenharmony_ci static const char *me = "sane_snapscan_read"; 1791141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) h; 1792141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1793141cc406Sopenharmony_ci 1794141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, 1795141cc406Sopenharmony_ci "%s (%p, %p, %ld, %p)\n", 1796141cc406Sopenharmony_ci me, 1797141cc406Sopenharmony_ci (void *) h, 1798141cc406Sopenharmony_ci (void *) buf, 1799141cc406Sopenharmony_ci (long) maxlen, 1800141cc406Sopenharmony_ci (void *) plen); 1801141cc406Sopenharmony_ci 1802141cc406Sopenharmony_ci *plen = 0; 1803141cc406Sopenharmony_ci 1804141cc406Sopenharmony_ci if (pss->state == ST_CANCEL_INIT) { 1805141cc406Sopenharmony_ci pss->state = ST_IDLE; 1806141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1807141cc406Sopenharmony_ci } 1808141cc406Sopenharmony_ci 1809141cc406Sopenharmony_ci if (pss->psrc == NULL || pss->psrc->remaining(pss->psrc) == 0) 1810141cc406Sopenharmony_ci { 1811141cc406Sopenharmony_ci if (sanei_thread_is_valid (pss->child)) 1812141cc406Sopenharmony_ci { 1813141cc406Sopenharmony_ci sanei_thread_waitpid (pss->child, 0); /* ensure no zombies */ 1814141cc406Sopenharmony_ci sanei_thread_invalidate (pss->child); 1815141cc406Sopenharmony_ci } 1816141cc406Sopenharmony_ci release_unit (pss); 1817141cc406Sopenharmony_ci close_scanner (pss); 1818141cc406Sopenharmony_ci if (pss->psrc != NULL) 1819141cc406Sopenharmony_ci { 1820141cc406Sopenharmony_ci pss->psrc->done(pss->psrc); 1821141cc406Sopenharmony_ci free(pss->psrc); 1822141cc406Sopenharmony_ci pss->psrc = NULL; 1823141cc406Sopenharmony_ci } 1824141cc406Sopenharmony_ci pss->state = ST_IDLE; 1825141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1826141cc406Sopenharmony_ci } 1827141cc406Sopenharmony_ci 1828141cc406Sopenharmony_ci *plen = maxlen; 1829141cc406Sopenharmony_ci status = pss->psrc->get(pss->psrc, buf, plen); 1830141cc406Sopenharmony_ci 1831141cc406Sopenharmony_ci switch (pss->state) 1832141cc406Sopenharmony_ci { 1833141cc406Sopenharmony_ci case ST_IDLE: 1834141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1835141cc406Sopenharmony_ci "%s: weird error: scanner state should not be idle on call to " 1836141cc406Sopenharmony_ci "sane_read.\n", 1837141cc406Sopenharmony_ci me); 1838141cc406Sopenharmony_ci break; 1839141cc406Sopenharmony_ci case ST_SCAN_INIT: 1840141cc406Sopenharmony_ci /* we've read some data */ 1841141cc406Sopenharmony_ci pss->state = ST_SCANNING; 1842141cc406Sopenharmony_ci break; 1843141cc406Sopenharmony_ci case ST_CANCEL_INIT: 1844141cc406Sopenharmony_ci /* stop scanning */ 1845141cc406Sopenharmony_ci status = SANE_STATUS_CANCELLED; 1846141cc406Sopenharmony_ci break; 1847141cc406Sopenharmony_ci default: 1848141cc406Sopenharmony_ci break; 1849141cc406Sopenharmony_ci } 1850141cc406Sopenharmony_ci 1851141cc406Sopenharmony_ci return status; 1852141cc406Sopenharmony_ci} 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_civoid sane_cancel (SANE_Handle h) 1855141cc406Sopenharmony_ci{ 1856141cc406Sopenharmony_ci char *me = "sane_snapscan_cancel"; 1857141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) h; 1858141cc406Sopenharmony_ci struct SIGACTION act; 1859141cc406Sopenharmony_ci SANE_Pid res; 1860141cc406Sopenharmony_ci 1861141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1862141cc406Sopenharmony_ci switch (pss->state) 1863141cc406Sopenharmony_ci { 1864141cc406Sopenharmony_ci case ST_IDLE: 1865141cc406Sopenharmony_ci break; 1866141cc406Sopenharmony_ci case ST_SCAN_INIT: 1867141cc406Sopenharmony_ci case ST_SCANNING: 1868141cc406Sopenharmony_ci /* signal a cancellation has occurred */ 1869141cc406Sopenharmony_ci pss->state = ST_CANCEL_INIT; 1870141cc406Sopenharmony_ci /* signal the reader, if any */ 1871141cc406Sopenharmony_ci if (sanei_thread_is_valid (pss->child)) 1872141cc406Sopenharmony_ci { 1873141cc406Sopenharmony_ci DBG( DL_INFO, "---- killing reader_process ----\n" ); 1874141cc406Sopenharmony_ci 1875141cc406Sopenharmony_ci sigemptyset(&(act.sa_mask)); 1876141cc406Sopenharmony_ci act.sa_flags = 0; 1877141cc406Sopenharmony_ci 1878141cc406Sopenharmony_ci act.sa_handler = sigalarm_handler; 1879141cc406Sopenharmony_ci sigaction( SIGALRM, &act, 0 ); 1880141cc406Sopenharmony_ci 1881141cc406Sopenharmony_ci if (sanei_thread_is_forked()) 1882141cc406Sopenharmony_ci { 1883141cc406Sopenharmony_ci /* use SIGUSR1 to set cancelRead in child process */ 1884141cc406Sopenharmony_ci sanei_thread_sendsig( pss->child, SIGUSR1 ); 1885141cc406Sopenharmony_ci } 1886141cc406Sopenharmony_ci else 1887141cc406Sopenharmony_ci { 1888141cc406Sopenharmony_ci cancelRead = SANE_TRUE; 1889141cc406Sopenharmony_ci } 1890141cc406Sopenharmony_ci 1891141cc406Sopenharmony_ci /* give'em 10 seconds 'til done...*/ 1892141cc406Sopenharmony_ci alarm(10); 1893141cc406Sopenharmony_ci res = sanei_thread_waitpid( pss->child, 0 ); 1894141cc406Sopenharmony_ci alarm(0); 1895141cc406Sopenharmony_ci 1896141cc406Sopenharmony_ci if( res != pss->child ) { 1897141cc406Sopenharmony_ci DBG( DL_MINOR_ERROR,"sanei_thread_waitpid() failed !\n"); 1898141cc406Sopenharmony_ci 1899141cc406Sopenharmony_ci /* do it the hard way...*/ 1900141cc406Sopenharmony_ci#ifdef USE_PTHREAD 1901141cc406Sopenharmony_ci sanei_thread_kill( pss->child ); 1902141cc406Sopenharmony_ci#else 1903141cc406Sopenharmony_ci sanei_thread_sendsig( pss->child, SIGKILL ); 1904141cc406Sopenharmony_ci#endif 1905141cc406Sopenharmony_ci } 1906141cc406Sopenharmony_ci sanei_thread_invalidate( pss->child ); 1907141cc406Sopenharmony_ci DBG( DL_INFO,"reader_process killed\n"); 1908141cc406Sopenharmony_ci } 1909141cc406Sopenharmony_ci release_unit (pss); 1910141cc406Sopenharmony_ci close_scanner (pss); 1911141cc406Sopenharmony_ci break; 1912141cc406Sopenharmony_ci case ST_CANCEL_INIT: 1913141cc406Sopenharmony_ci DBG (DL_INFO, "%s: cancellation already initiated.\n", me); 1914141cc406Sopenharmony_ci break; 1915141cc406Sopenharmony_ci default: 1916141cc406Sopenharmony_ci DBG (DL_MAJOR_ERROR, 1917141cc406Sopenharmony_ci "%s: weird error: invalid scanner state (%ld).\n", 1918141cc406Sopenharmony_ci me, 1919141cc406Sopenharmony_ci (long) pss->state); 1920141cc406Sopenharmony_ci break; 1921141cc406Sopenharmony_ci } 1922141cc406Sopenharmony_ci} 1923141cc406Sopenharmony_ci 1924141cc406Sopenharmony_ciSANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m) 1925141cc406Sopenharmony_ci{ 1926141cc406Sopenharmony_ci static char me[] = "sane_snapscan_set_io_mode"; 1927141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) h; 1928141cc406Sopenharmony_ci char *op; 1929141cc406Sopenharmony_ci 1930141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1931141cc406Sopenharmony_ci 1932141cc406Sopenharmony_ci if (pss->state != ST_SCAN_INIT) 1933141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1934141cc406Sopenharmony_ci 1935141cc406Sopenharmony_ci if (m) 1936141cc406Sopenharmony_ci { 1937141cc406Sopenharmony_ci if (!sanei_thread_is_valid (pss->child)) 1938141cc406Sopenharmony_ci { 1939141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, 1940141cc406Sopenharmony_ci "%s: no reader child; must use blocking mode.\n", 1941141cc406Sopenharmony_ci me); 1942141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1943141cc406Sopenharmony_ci } 1944141cc406Sopenharmony_ci op = "ON"; 1945141cc406Sopenharmony_ci fcntl (pss->rpipe[0], F_SETFL, O_NONBLOCK | pss->orig_rpipe_flags); 1946141cc406Sopenharmony_ci } 1947141cc406Sopenharmony_ci else 1948141cc406Sopenharmony_ci { 1949141cc406Sopenharmony_ci op = "OFF"; 1950141cc406Sopenharmony_ci fcntl (pss->rpipe[0], F_SETFL, pss->orig_rpipe_flags); 1951141cc406Sopenharmony_ci } 1952141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, "%s: turning nonblocking mode %s.\n", me, op); 1953141cc406Sopenharmony_ci pss->nonblocking = m; 1954141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1955141cc406Sopenharmony_ci} 1956141cc406Sopenharmony_ci 1957141cc406Sopenharmony_ciSANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd) 1958141cc406Sopenharmony_ci{ 1959141cc406Sopenharmony_ci static char me[] = "sane_snapscan_get_select_fd"; 1960141cc406Sopenharmony_ci SnapScan_Scanner *pss = (SnapScan_Scanner *) h; 1961141cc406Sopenharmony_ci 1962141cc406Sopenharmony_ci DBG (DL_CALL_TRACE, "%s\n", me); 1963141cc406Sopenharmony_ci 1964141cc406Sopenharmony_ci if (pss->state != ST_SCAN_INIT) 1965141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1966141cc406Sopenharmony_ci 1967141cc406Sopenharmony_ci if (!sanei_thread_is_valid (pss->child)) 1968141cc406Sopenharmony_ci { 1969141cc406Sopenharmony_ci DBG (DL_MINOR_INFO, 1970141cc406Sopenharmony_ci "%s: no reader child; cannot provide select file descriptor.\n", 1971141cc406Sopenharmony_ci me); 1972141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1973141cc406Sopenharmony_ci } 1974141cc406Sopenharmony_ci *fd = pss->rpipe[0]; 1975141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1976141cc406Sopenharmony_ci} 1977141cc406Sopenharmony_ci 1978141cc406Sopenharmony_ci/* 1979141cc406Sopenharmony_ci * Revision 1.73 2008/11/26 21:21:29 kitno-guest 1980141cc406Sopenharmony_ci * * backend/ *.[ch]: nearly every backend used V_MAJOR 1981141cc406Sopenharmony_ci * instead of SANE_CURRENT_MAJOR in sane_init() 1982141cc406Sopenharmony_ci * * backend/snapscan.c: remove EXPECTED_VERSION check 1983141cc406Sopenharmony_ci * since new SANE standard is forward compatible 1984141cc406Sopenharmony_ci * 1985141cc406Sopenharmony_ci * Revision 1.72 2008-05-15 12:50:24 ellert-guest 1986141cc406Sopenharmony_ci * Fix for bug #306751: sanei-thread with pthreads on 64 bit 1987141cc406Sopenharmony_ci * 1988141cc406Sopenharmony_ci * Revision 1.71 2008-01-29 17:48:42 kitno-guest 1989141cc406Sopenharmony_ci * fix snapscan bug, add LiDE 600F 1990141cc406Sopenharmony_ci * 1991141cc406Sopenharmony_ci * Revision 1.70 2007-11-18 10:59:18 ellert-guest 1992141cc406Sopenharmony_ci * Fix handling of valid "negative" PIDs 1993141cc406Sopenharmony_ci * 1994141cc406Sopenharmony_ci * Revision 1.69 2007-11-16 08:04:02 ellert-guest 1995141cc406Sopenharmony_ci * Correct the test of the return value from sanei_thread_begin 1996141cc406Sopenharmony_ci * 1997141cc406Sopenharmony_ci * Revision 1.68 2006-09-03 10:00:11 oliver-guest 1998141cc406Sopenharmony_ci * Bugfix for firmware download by Paul Smedley 1999141cc406Sopenharmony_ci * 2000141cc406Sopenharmony_ci * Revision 1.67 2006/01/10 19:32:16 oliver-guest 2001141cc406Sopenharmony_ci * Added 12 bit gamma tables for Epson Stylus CX-1500 2002141cc406Sopenharmony_ci * 2003141cc406Sopenharmony_ci * Revision 1.66 2006/01/06 20:59:17 oliver-guest 2004141cc406Sopenharmony_ci * Some fixes for the Epson Stylus CX 1500 2005141cc406Sopenharmony_ci * 2006141cc406Sopenharmony_ci * Revision 1.65 2006/01/01 23:02:55 oliver-guest 2007141cc406Sopenharmony_ci * Added snapscan-data.c to Makefile.in 2008141cc406Sopenharmony_ci * 2009141cc406Sopenharmony_ci * Revision 1.64 2005/12/05 20:38:23 oliver-guest 2010141cc406Sopenharmony_ci * Small bugfix for Benq 5150 2011141cc406Sopenharmony_ci * 2012141cc406Sopenharmony_ci * Revision 1.63 2005/12/04 15:03:00 oliver-guest 2013141cc406Sopenharmony_ci * Some fixes for Benq 5150 2014141cc406Sopenharmony_ci * 2015141cc406Sopenharmony_ci * Revision 1.62 2005/12/02 19:15:42 oliver-guest 2016141cc406Sopenharmony_ci * Change SnapScan version number to 1.4.50 2017141cc406Sopenharmony_ci * 2018141cc406Sopenharmony_ci * Revision 1.61 2005/11/15 20:11:19 oliver-guest 2019141cc406Sopenharmony_ci * Enabled quality calibration for the Epson 3490 2020141cc406Sopenharmony_ci * 2021141cc406Sopenharmony_ci * Revision 1.60 2005/11/10 19:42:02 oliver-guest 2022141cc406Sopenharmony_ci * Added deinterlacing for Epson 3490 2023141cc406Sopenharmony_ci * 2024141cc406Sopenharmony_ci * Revision 1.59 2005/11/02 22:12:54 oliver-guest 2025141cc406Sopenharmony_ci * Correct cut'n'paste error 2026141cc406Sopenharmony_ci * 2027141cc406Sopenharmony_ci * Revision 1.58 2005/11/02 19:22:06 oliver-guest 2028141cc406Sopenharmony_ci * Fixes for Benq 5000 2029141cc406Sopenharmony_ci * 2030141cc406Sopenharmony_ci * Revision 1.57 2005/10/31 21:08:47 oliver-guest 2031141cc406Sopenharmony_ci * Distinguish between Benq 5000/5000E/5000U 2032141cc406Sopenharmony_ci * 2033141cc406Sopenharmony_ci * Revision 1.56 2005/10/24 19:46:40 oliver-guest 2034141cc406Sopenharmony_ci * Preview and range fix for Epson 2480/2580 2035141cc406Sopenharmony_ci * 2036141cc406Sopenharmony_ci * Revision 1.55 2005/10/23 21:28:58 oliver-guest 2037141cc406Sopenharmony_ci * Fix for buffer size in high res modes, fixes for delay code 2038141cc406Sopenharmony_ci * 2039141cc406Sopenharmony_ci * Revision 1.54 2005/10/13 22:43:30 oliver-guest 2040141cc406Sopenharmony_ci * Fixes for 16 bit scan mode from Simon Munton 2041141cc406Sopenharmony_ci * 2042141cc406Sopenharmony_ci * Revision 1.53 2005/10/11 18:47:07 oliver-guest 2043141cc406Sopenharmony_ci * Fixes for Epson 3490 and 16 bit scan mode 2044141cc406Sopenharmony_ci * 2045141cc406Sopenharmony_ci * Revision 1.52 2005/09/28 21:33:11 oliver-guest 2046141cc406Sopenharmony_ci * Added 16 bit option for Epson scanners (untested) 2047141cc406Sopenharmony_ci * 2048141cc406Sopenharmony_ci * Revision 1.51 2005/08/15 18:56:55 oliver-guest 2049141cc406Sopenharmony_ci * Added temporary debug code for 2480/2580 distinction 2050141cc406Sopenharmony_ci * 2051141cc406Sopenharmony_ci * Revision 1.50 2005/08/15 18:06:37 oliver-guest 2052141cc406Sopenharmony_ci * Added support for Epson 3490/3590 (thanks to Matt Judge) 2053141cc406Sopenharmony_ci * 2054141cc406Sopenharmony_ci * Revision 1.49 2005/08/07 12:37:29 oliver-guest 2055141cc406Sopenharmony_ci * Use first known device if no device is specified 2056141cc406Sopenharmony_ci * 2057141cc406Sopenharmony_ci * Revision 1.48 2004/12/09 23:21:48 oliver-guest 2058141cc406Sopenharmony_ci * Added quality calibration for Epson 2480 (by Simon Munton) 2059141cc406Sopenharmony_ci * 2060141cc406Sopenharmony_ci * Revision 1.47 2004/12/01 22:49:14 oliver-guest 2061141cc406Sopenharmony_ci * Fix for allocation of gamma tables by Simon Munton 2062141cc406Sopenharmony_ci * 2063141cc406Sopenharmony_ci * Revision 1.46 2004/12/01 22:12:03 oliver-guest 2064141cc406Sopenharmony_ci * Added support for Epson 1270 2065141cc406Sopenharmony_ci * 2066141cc406Sopenharmony_ci * Revision 1.45 2004/10/03 17:34:36 hmg-guest 2067141cc406Sopenharmony_ci * 64 bit platform fixes (bug #300799). 2068141cc406Sopenharmony_ci * 2069141cc406Sopenharmony_ci * Revision 1.44 2004/09/02 20:59:12 oliver-guest 2070141cc406Sopenharmony_ci * Added support for Epson 2480 2071141cc406Sopenharmony_ci * 2072141cc406Sopenharmony_ci * Revision 1.43 2004/06/16 19:52:26 oliver-guest 2073141cc406Sopenharmony_ci * Don't enforce even number of URB packages on 1212u_2. Fixes bug #300753. 2074141cc406Sopenharmony_ci * 2075141cc406Sopenharmony_ci * Revision 1.42 2004/06/15 12:17:37 hmg-guest 2076141cc406Sopenharmony_ci * Only use __attribute__ if gcc is used for compilation. Some other compilers 2077141cc406Sopenharmony_ci * don't know __attribute__ and therefore can't compile sane-backends without this 2078141cc406Sopenharmony_ci * fix. See bug #300803. 2079141cc406Sopenharmony_ci * 2080141cc406Sopenharmony_ci * Revision 1.41 2004/05/26 22:37:01 oliver-guest 2081141cc406Sopenharmony_ci * Use shared memory for urb counters in snapscan backend 2082141cc406Sopenharmony_ci * 2083141cc406Sopenharmony_ci * Revision 1.40 2004/04/09 11:59:02 oliver-guest 2084141cc406Sopenharmony_ci * Fixes for pthread implementation 2085141cc406Sopenharmony_ci * 2086141cc406Sopenharmony_ci * Revision 1.39 2004/04/08 21:53:10 oliver-guest 2087141cc406Sopenharmony_ci * Use sanei_thread in snapscan backend 2088141cc406Sopenharmony_ci * 2089141cc406Sopenharmony_ci * Revision 1.37 2003/11/27 23:11:32 oliver-guest 2090141cc406Sopenharmony_ci * Send gamma table twice for Epson Perfection 1670 2091141cc406Sopenharmony_ci * 2092141cc406Sopenharmony_ci * Revision 1.36 2003/11/09 21:43:45 oliver-guest 2093141cc406Sopenharmony_ci * Disabled quality calibration for Epson Perfection 1670 2094141cc406Sopenharmony_ci * 2095141cc406Sopenharmony_ci * Revision 1.35 2003/11/07 23:26:49 oliver-guest 2096141cc406Sopenharmony_ci * Final bugfixes for bascic support of Epson 1670 2097141cc406Sopenharmony_ci * 2098141cc406Sopenharmony_ci * Revision 1.34 2003/10/21 20:43:25 oliver-guest 2099141cc406Sopenharmony_ci * Bugfixes for SnapScan backend 2100141cc406Sopenharmony_ci * 2101141cc406Sopenharmony_ci * Revision 1.33 2003/10/07 18:29:20 oliver-guest 2102141cc406Sopenharmony_ci * Initial support for Epson 1670, minor bugfix 2103141cc406Sopenharmony_ci * 2104141cc406Sopenharmony_ci * Revision 1.32 2003/09/24 18:05:39 oliver-guest 2105141cc406Sopenharmony_ci * Bug #300198: Check second argument of sanei_config_get_string 2106141cc406Sopenharmony_ci * 2107141cc406Sopenharmony_ci * Revision 1.31 2003/09/12 16:10:33 hmg-guest 2108141cc406Sopenharmony_ci * Moved union Option_Value from backend header files to sanei_backend.h. No need 2109141cc406Sopenharmony_ci * to copy it over and over again. Changed header inclusion order in backend 2110141cc406Sopenharmony_ci * files to include backend.h after sanei_backend.h. Based on a patch from stef 2111141cc406Sopenharmony_ci * <stef-listes@wanadoo.fr>. 2112141cc406Sopenharmony_ci * 2113141cc406Sopenharmony_ci * Revision 1.30 2003/08/19 21:05:08 oliverschwartz 2114141cc406Sopenharmony_ci * Scanner ID cleanup 2115141cc406Sopenharmony_ci * 2116141cc406Sopenharmony_ci * Revision 1.29 2003/04/30 20:49:40 oliverschwartz 2117141cc406Sopenharmony_ci * SnapScan backend 1.4.26 2118141cc406Sopenharmony_ci * 2119141cc406Sopenharmony_ci * Revision 1.58 2003/04/30 20:43:07 oliverschwartz 2120141cc406Sopenharmony_ci * Set backend version number to 1.4.26 2121141cc406Sopenharmony_ci * 2122141cc406Sopenharmony_ci * Revision 1.57 2003/04/02 21:17:14 oliverschwartz 2123141cc406Sopenharmony_ci * Fix for 1200 DPI with Acer 5000 2124141cc406Sopenharmony_ci * 2125141cc406Sopenharmony_ci * Revision 1.56 2003/02/08 10:45:09 oliverschwartz 2126141cc406Sopenharmony_ci * Use 600 DPI as optical resolution for Benq 5000 2127141cc406Sopenharmony_ci * 2128141cc406Sopenharmony_ci * Revision 1.55 2003/01/08 21:16:17 oliverschwartz 2129141cc406Sopenharmony_ci * Added support for Acer / Benq 310U 2130141cc406Sopenharmony_ci * 2131141cc406Sopenharmony_ci * Revision 1.54 2002/12/10 20:14:12 oliverschwartz 2132141cc406Sopenharmony_ci * Enable color offset correction for SnapScan300 2133141cc406Sopenharmony_ci * 2134141cc406Sopenharmony_ci * Revision 1.53 2002/10/31 19:29:41 oliverschwartz 2135141cc406Sopenharmony_ci * Set version to 1.4.17 2136141cc406Sopenharmony_ci * 2137141cc406Sopenharmony_ci * Revision 1.52 2002/10/12 10:40:48 oliverschwartz 2138141cc406Sopenharmony_ci * Added support for Snapscan e10 2139141cc406Sopenharmony_ci * 2140141cc406Sopenharmony_ci * Revision 1.51 2002/09/26 19:27:44 oliverschwartz 2141141cc406Sopenharmony_ci * Version 1.4.16 2142141cc406Sopenharmony_ci * 2143141cc406Sopenharmony_ci * Revision 1.50 2002/09/24 16:07:44 oliverschwartz 2144141cc406Sopenharmony_ci * Added support for Benq 5000 2145141cc406Sopenharmony_ci * 2146141cc406Sopenharmony_ci * Revision 1.49 2002/07/12 22:53:54 oliverschwartz 2147141cc406Sopenharmony_ci * Version 1.4.15 2148141cc406Sopenharmony_ci * 2149141cc406Sopenharmony_ci * Revision 1.48 2002/07/12 22:53:16 oliverschwartz 2150141cc406Sopenharmony_ci * call sanei_usb_init() before sanei_usb_attach_matching_devices() 2151141cc406Sopenharmony_ci * 2152141cc406Sopenharmony_ci * Revision 1.47 2002/06/06 21:16:23 oliverschwartz 2153141cc406Sopenharmony_ci * Set backend version to 1.4.14 2154141cc406Sopenharmony_ci * 2155141cc406Sopenharmony_ci * Revision 1.46 2002/06/06 20:40:01 oliverschwartz 2156141cc406Sopenharmony_ci * Changed default scan area for transparency unit of SnapScan e50 2157141cc406Sopenharmony_ci * 2158141cc406Sopenharmony_ci * Revision 1.45 2002/05/02 18:29:34 oliverschwartz 2159141cc406Sopenharmony_ci * - Added ADF support 2160141cc406Sopenharmony_ci * - Fixed status handling after cancel 2161141cc406Sopenharmony_ci * 2162141cc406Sopenharmony_ci * Revision 1.44 2002/04/27 14:42:30 oliverschwartz 2163141cc406Sopenharmony_ci * Cleanup of debug logging 2164141cc406Sopenharmony_ci * 2165141cc406Sopenharmony_ci * Revision 1.43 2002/04/23 22:40:33 oliverschwartz 2166141cc406Sopenharmony_ci * Improve config file reading 2167141cc406Sopenharmony_ci * 2168141cc406Sopenharmony_ci * Revision 1.42 2002/04/10 21:00:09 oliverschwartz 2169141cc406Sopenharmony_ci * Check for NULL pointer before deleting device list 2170141cc406Sopenharmony_ci * 2171141cc406Sopenharmony_ci * Revision 1.41 2002/03/24 12:12:36 oliverschwartz 2172141cc406Sopenharmony_ci * - Moved option functions to snapscan-options.c 2173141cc406Sopenharmony_ci * - Autodetect USB scanners 2174141cc406Sopenharmony_ci * - Cleanup 2175141cc406Sopenharmony_ci * 2176141cc406Sopenharmony_ci * Revision 1.40 2002/02/09 14:55:23 oliverschwartz 2177141cc406Sopenharmony_ci * Added language translation support (SANE_I18N) 2178141cc406Sopenharmony_ci * 2179141cc406Sopenharmony_ci * Revision 1.39 2002/01/23 20:40:54 oliverschwartz 2180141cc406Sopenharmony_ci * Don't use quantization for scan area parameter 2181141cc406Sopenharmony_ci * Improve recognition of Acer 320U 2182141cc406Sopenharmony_ci * Version 1.4.7 2183141cc406Sopenharmony_ci * 2184141cc406Sopenharmony_ci * Revision 1.38 2002/01/14 21:11:56 oliverschwartz 2185141cc406Sopenharmony_ci * Add workaround for bug semctl() call in libc for PPC 2186141cc406Sopenharmony_ci * 2187141cc406Sopenharmony_ci * Revision 1.37 2002/01/10 21:33:12 oliverschwartz 2188141cc406Sopenharmony_ci * Set version number to 1.4.4 2189141cc406Sopenharmony_ci * 2190141cc406Sopenharmony_ci * Revision 1.36 2002/01/06 18:34:02 oliverschwartz 2191141cc406Sopenharmony_ci * Added support for Snapscan e42 thanks to Yari Ad� Petralanda 2192141cc406Sopenharmony_ci * 2193141cc406Sopenharmony_ci * Revision 1.35 2001/12/20 23:18:01 oliverschwartz 2194141cc406Sopenharmony_ci * Remove tmpfname 2195141cc406Sopenharmony_ci * 2196141cc406Sopenharmony_ci * Revision 1.34 2001/12/18 18:28:35 oliverschwartz 2197141cc406Sopenharmony_ci * Removed temporary file 2198141cc406Sopenharmony_ci * 2199141cc406Sopenharmony_ci * Revision 1.33 2001/12/12 19:43:30 oliverschwartz 2200141cc406Sopenharmony_ci * - Set version number to 1.4.3 2201141cc406Sopenharmony_ci * - Clean up CVS Log 2202141cc406Sopenharmony_ci * 2203141cc406Sopenharmony_ci * Revision 1.32 2001/12/09 23:06:45 oliverschwartz 2204141cc406Sopenharmony_ci * - use sense handler for USB if scanner reports CHECK_CONDITION 2205141cc406Sopenharmony_ci * 2206141cc406Sopenharmony_ci * Revision 1.31 2001/12/08 11:50:34 oliverschwartz 2207141cc406Sopenharmony_ci * Fix dither matrix computation 2208141cc406Sopenharmony_ci * 2209141cc406Sopenharmony_ci * Revision 1.30 2001/11/29 22:50:14 oliverschwartz 2210141cc406Sopenharmony_ci * Add support for SnapScan e52 2211141cc406Sopenharmony_ci * 2212141cc406Sopenharmony_ci * Revision 1.29 2001/11/27 23:16:17 oliverschwartz 2213141cc406Sopenharmony_ci * - Fix color alignment for SnapScan 600 2214141cc406Sopenharmony_ci * - Added documentation in snapscan-sources.c 2215141cc406Sopenharmony_ci * - Guard against TL_X < BR_X and TL_Y < BR_Y 2216141cc406Sopenharmony_ci * 2217141cc406Sopenharmony_ci * Revision 1.28 2001/11/25 18:51:41 oliverschwartz 2218141cc406Sopenharmony_ci * added support for SnapScan e52 thanks to Rui Lopes 2219141cc406Sopenharmony_ci * 2220141cc406Sopenharmony_ci * Revision 1.27 2001/11/16 20:28:35 oliverschwartz 2221141cc406Sopenharmony_ci * add support for Snapscan e26 2222141cc406Sopenharmony_ci * 2223141cc406Sopenharmony_ci * Revision 1.26 2001/11/16 20:23:16 oliverschwartz 2224141cc406Sopenharmony_ci * Merge with sane-1.0.6 2225141cc406Sopenharmony_ci * - Check USB vendor IDs to avoid hanging scanners 2226141cc406Sopenharmony_ci * - fix bug in dither matrix computation 2227141cc406Sopenharmony_ci * 2228141cc406Sopenharmony_ci * Revision 1.25 2001/10/25 11:06:22 oliverschwartz 2229141cc406Sopenharmony_ci * Change snapscan backend version number to 1.4.0 2230141cc406Sopenharmony_ci * 2231141cc406Sopenharmony_ci * Revision 1.24 2001/10/11 14:02:10 oliverschwartz 2232141cc406Sopenharmony_ci * Distinguish between e20/e25 and e40/e50 2233141cc406Sopenharmony_ci * 2234141cc406Sopenharmony_ci * Revision 1.23 2001/10/09 22:34:23 oliverschwartz 2235141cc406Sopenharmony_ci * fix compiler warnings 2236141cc406Sopenharmony_ci * 2237141cc406Sopenharmony_ci * Revision 1.22 2001/10/08 19:26:01 oliverschwartz 2238141cc406Sopenharmony_ci * - Disable quality calibration for scanners that do not support it 2239141cc406Sopenharmony_ci * 2240141cc406Sopenharmony_ci * Revision 1.21 2001/10/08 18:22:02 oliverschwartz 2241141cc406Sopenharmony_ci * - Disable quality calibration for Acer Vuego 310F 2242141cc406Sopenharmony_ci * - Use sanei_scsi_max_request_size as scanner buffer size 2243141cc406Sopenharmony_ci * for SCSI devices 2244141cc406Sopenharmony_ci * - Added new devices to snapscan.desc 2245141cc406Sopenharmony_ci * 2246141cc406Sopenharmony_ci * Revision 1.20 2001/09/18 15:01:07 oliverschwartz 2247141cc406Sopenharmony_ci * - Read scanner id string again after firmware upload 2248141cc406Sopenharmony_ci * to identify correct model 2249141cc406Sopenharmony_ci * - Make firmware upload work for AGFA scanners 2250141cc406Sopenharmony_ci * - Change copyright notice 2251141cc406Sopenharmony_ci * 2252141cc406Sopenharmony_ci * Revision 1.19 2001/09/17 10:01:08 sable 2253141cc406Sopenharmony_ci * Added model AGFA 1236U 2254141cc406Sopenharmony_ci * 2255141cc406Sopenharmony_ci * Revision 1.18 2001/09/10 10:16:32 oliverschwartz 2256141cc406Sopenharmony_ci * better USB / SCSI recognition, correct max scan area for 1236+TPO 2257141cc406Sopenharmony_ci * 2258141cc406Sopenharmony_ci * Revision 1.17 2001/09/09 18:06:32 oliverschwartz 2259141cc406Sopenharmony_ci * add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup 2260141cc406Sopenharmony_ci * 2261141cc406Sopenharmony_ci * Revision 1.16 2001/09/07 09:42:13 oliverschwartz 2262141cc406Sopenharmony_ci * Sync with Sane-1.0.5 2263141cc406Sopenharmony_ci * 2264141cc406Sopenharmony_ci * Revision 1.15 2001/05/15 20:51:14 oliverschwartz 2265141cc406Sopenharmony_ci * check for pss->devname instead of name in sane_open() 2266141cc406Sopenharmony_ci * 2267141cc406Sopenharmony_ci * Revision 1.14 2001/04/10 13:33:06 sable 2268141cc406Sopenharmony_ci * Transparency adapter bug and xsane crash corrections thanks to Oliver Schwartz 2269141cc406Sopenharmony_ci * 2270141cc406Sopenharmony_ci * Revision 1.13 2001/04/10 13:00:31 sable 2271141cc406Sopenharmony_ci * Moving sanei_usb_* to snapscani_usb* 2272141cc406Sopenharmony_ci * 2273141cc406Sopenharmony_ci * Revision 1.12 2001/04/10 11:04:31 sable 2274141cc406Sopenharmony_ci * Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli 2275141cc406Sopenharmony_ci * 2276141cc406Sopenharmony_ci * Revision 1.11 2001/03/17 22:53:21 sable 2277141cc406Sopenharmony_ci * Applying Mikael Magnusson patch concerning Gamma correction 2278141cc406Sopenharmony_ci * Support for 1212U_2 2279141cc406Sopenharmony_ci * 2280141cc406Sopenharmony_ci * Revision 1.4 2001/03/04 16:50:53 mikael 2281141cc406Sopenharmony_ci * Added Scan Mode, Geometry, Enhancement and Advanced groups. Implemented brightness and contrast controls with gamma tables. Added Quality Calibration, Analog Gamma Bind, Custom Gamma and Gamma Vector GS,R,G,B options. 2282141cc406Sopenharmony_ci * 2283141cc406Sopenharmony_ci * Revision 1.3 2001/02/16 18:32:28 mikael 2284141cc406Sopenharmony_ci * impl calibration, signed position, increased buffer size 2285141cc406Sopenharmony_ci * 2286141cc406Sopenharmony_ci * Revision 1.2 2001/02/10 18:18:29 mikael 2287141cc406Sopenharmony_ci * Extended x and y ranges 2288141cc406Sopenharmony_ci * 2289141cc406Sopenharmony_ci * Revision 1.1.1.1 2001/02/10 17:09:29 mikael 2290141cc406Sopenharmony_ci * Imported from snapscan-11282000.tar.gz 2291141cc406Sopenharmony_ci * 2292141cc406Sopenharmony_ci * Revision 1.10 2000/11/10 01:01:59 sable 2293141cc406Sopenharmony_ci * USB (kind of) autodetection 2294141cc406Sopenharmony_ci * 2295141cc406Sopenharmony_ci * Revision 1.9 2000/11/01 01:26:43 sable 2296141cc406Sopenharmony_ci * Support for 1212U 2297141cc406Sopenharmony_ci * 2298141cc406Sopenharmony_ci * Revision 1.8 2000/10/30 22:31:13 sable 2299141cc406Sopenharmony_ci * Auto preview mode 2300141cc406Sopenharmony_ci * 2301141cc406Sopenharmony_ci * Revision 1.7 2000/10/28 14:16:10 sable 2302141cc406Sopenharmony_ci * Bug correction for SnapScan310 2303141cc406Sopenharmony_ci * 2304141cc406Sopenharmony_ci * Revision 1.6 2000/10/28 14:06:35 sable 2305141cc406Sopenharmony_ci * Add support for Acer300f 2306141cc406Sopenharmony_ci * 2307141cc406Sopenharmony_ci * Revision 1.5 2000/10/15 19:52:06 cbagwell 2308141cc406Sopenharmony_ci * Changed USB support to a 1 line modification instead of multi-file 2309141cc406Sopenharmony_ci * changes. 2310141cc406Sopenharmony_ci * 2311141cc406Sopenharmony_ci * Revision 1.4 2000/10/13 03:50:27 cbagwell 2312141cc406Sopenharmony_ci * Updating to source from SANE 1.0.3. Calling this version 1.1 2313141cc406Sopenharmony_ci * 2314141cc406Sopenharmony_ci * Revision 1.3 2000/08/12 15:09:35 pere 2315141cc406Sopenharmony_ci * Merge devel (v1.0.3) into head branch. 2316141cc406Sopenharmony_ci * 2317141cc406Sopenharmony_ci * Revision 1.1.1.1.2.5 2000/07/29 16:04:33 hmg 2318141cc406Sopenharmony_ci * 2000-07-29 Henning Meier-Geinitz <hmg@gmx.de> 2319141cc406Sopenharmony_ci * 2320141cc406Sopenharmony_ci * * backend/GUIDE: Added some comments about portability and 2321141cc406Sopenharmony_ci * documentation. 2322141cc406Sopenharmony_ci * * backend/abaton.c backend/agfafocus.c backend/apple.c 2323141cc406Sopenharmony_ci * backend/canon.c backend/coolscan.c backend/dc210.c backend/dc25.c 2324141cc406Sopenharmony_ci * backend/dll.c backend/dmc.c backend/microtek.c backend/microtek2.c 2325141cc406Sopenharmony_ci * backend/microtek2.c backend/mustek_pp.c backend/net.c backend/pint.c 2326141cc406Sopenharmony_ci * backend/pnm.c backend/qcam.c backend/ricoh.c backend/s9036.c 2327141cc406Sopenharmony_ci * backend/sane_strstatus.c backend/sharp.c backend/snapscan.c 2328141cc406Sopenharmony_ci * backend/st400.c backend/stubs.c backend/tamarack.c backend/v4l.c: 2329141cc406Sopenharmony_ci * Changed include statements from #include <sane/...> to 2330141cc406Sopenharmony_ci * #include "sane...". 2331141cc406Sopenharmony_ci * * backend/avision.c backend/dc25.c: Use DBG(0, ...) instead of 2332141cc406Sopenharmony_ci * fprintf (stderr, ...) 2333141cc406Sopenharmony_ci * * backend/avision.c backend/canon-sane.c backend/coolscan.c 2334141cc406Sopenharmony_ci * backend/dc25.c backend/microtek.c backend/microtek2.c 2335141cc406Sopenharmony_ci * backend/st400.c: Use sanei_config_read() instead of fgets(). 2336141cc406Sopenharmony_ci * * backend/coolscan.desc backend/microtek.desc backend/microtek2.desc 2337141cc406Sopenharmony_ci * backend/st400.desc: Added :interface and :manpage entries. 2338141cc406Sopenharmony_ci * * backend/nec.desc: Status is beta now (was: new). Fixed typo. 2339141cc406Sopenharmony_ci * * doc/canon.README: Removed, because the information is included in 2340141cc406Sopenharmony_ci * the manpage now. 2341141cc406Sopenharmony_ci * * doc/Makefile.in: Added sane-coolscan to list of mapages to install. 2342141cc406Sopenharmony_ci * * README: Added Link to coolscan manpage. 2343141cc406Sopenharmony_ci * * backend/mustek.*: Update to Mustek backend 1.0-94. Fixed the 2344141cc406Sopenharmony_ci * #include <sane/...> bug. 2345141cc406Sopenharmony_ci * 2346141cc406Sopenharmony_ci * Revision 1.1.1.1.2.4 2000/07/25 21:47:43 hmg 2347141cc406Sopenharmony_ci * 2000-07-25 Henning Meier-Geinitz <hmg@gmx.de> 2348141cc406Sopenharmony_ci * 2349141cc406Sopenharmony_ci * * backend/snapscan.c: Use DBG(0, ...) instead of fprintf (stderr, ...). 2350141cc406Sopenharmony_ci * * backend/abaton.c backend/agfafocus.c backend/apple.c backend/dc210.c 2351141cc406Sopenharmony_ci * backend/dll.c backend/dmc.c backend/microtek2.c backend/pint.c 2352141cc406Sopenharmony_ci * backend/qcam.c backend/ricoh.c backend/s9036.c backend/snapscan.c 2353141cc406Sopenharmony_ci * backend/tamarack.c: Use sanei_config_read instead of fgets. 2354141cc406Sopenharmony_ci * * backend/dc210.c backend/microtek.c backend/pnm.c: Added 2355141cc406Sopenharmony_ci * #include "../include/sane/config.h". 2356141cc406Sopenharmony_ci * * backend/dc25.c backend/m3096.c backend/sp15.c 2357141cc406Sopenharmony_ci * backend/st400.c: Moved #include "../include/sane/config.h" to the beginning. 2358141cc406Sopenharmony_ci * * AUTHORS: Changed agfa to agfafocus. 2359141cc406Sopenharmony_ci * 2360141cc406Sopenharmony_ci * Revision 1.1.1.1.2.3 2000/07/17 21:37:28 hmg 2361141cc406Sopenharmony_ci * 2000-07-17 Henning Meier-Geinitz <hmg@gmx.de> 2362141cc406Sopenharmony_ci * 2363141cc406Sopenharmony_ci * * backend/snapscan.c backend/snapscan-scsi.c: Replace C++ comment 2364141cc406Sopenharmony_ci * with C comment. 2365141cc406Sopenharmony_ci * 2366141cc406Sopenharmony_ci * Revision 1.1.1.1.2.2 2000/07/13 04:47:46 pere 2367141cc406Sopenharmony_ci * New snapscan backend version dated 20000514 from Steve Underwood. 2368141cc406Sopenharmony_ci * 2369141cc406Sopenharmony_ci * Revision 1.2 2000/05/14 13:30:20 coppice 2370141cc406Sopenharmony_ci * R, G and B images now merge correctly. Still some outstanding issues, 2371141cc406Sopenharmony_ci * but a lot more useful than before. 2372141cc406Sopenharmony_ci * 2373141cc406Sopenharmony_ci * Revision 1.2 2000/03/05 13:55:20 pere 2374141cc406Sopenharmony_ci * Merged main branch with current DEVEL_1_9. 2375141cc406Sopenharmony_ci * 2376141cc406Sopenharmony_ci * Revision 1.1.1.1.2.1 1999/09/15 18:20:44 charter 2377141cc406Sopenharmony_ci * Early version 1.0 snapscan.c 2378141cc406Sopenharmony_ci * 2379141cc406Sopenharmony_ci * Revision 2.2 1999/09/09 18:22:45 charter 2380141cc406Sopenharmony_ci * Checkpoint. Now using Sources for scanner data, and have removed 2381141cc406Sopenharmony_ci * references to the old snapscan-310.c stuff. This stuff must still 2382141cc406Sopenharmony_ci * be incorporated into the RGBRouter to get trilinear CCD SnapScan 2383141cc406Sopenharmony_ci * models working. 2384141cc406Sopenharmony_ci * 2385141cc406Sopenharmony_ci * Revision 2.1 1999/09/08 03:07:05 charter 2386141cc406Sopenharmony_ci * Start of branch 2; same as 1.47. 2387141cc406Sopenharmony_ci * 2388141cc406Sopenharmony_ci * Revision 1.47 1999/09/08 03:03:53 charter 2389141cc406Sopenharmony_ci * The actions for the scanner command options now use fprintf for 2390141cc406Sopenharmony_ci * printing, rather than DGB. I want the output to come out no matter 2391141cc406Sopenharmony_ci * what the value of the snapscan debug level. 2392141cc406Sopenharmony_ci * 2393141cc406Sopenharmony_ci * Revision 1.46 1999/09/07 20:53:41 charter 2394141cc406Sopenharmony_ci * Changed expected_data_len to bytes_remaining. 2395141cc406Sopenharmony_ci * 2396141cc406Sopenharmony_ci * Revision 1.45 1999/09/06 23:32:37 charter 2397141cc406Sopenharmony_ci * Split up sane_start() into sub-functions to improve readability (again). 2398141cc406Sopenharmony_ci * Introduced actual_mode() and is_colour_mode() (again). 2399141cc406Sopenharmony_ci * Fixed problems with cancellation. Works fine with my system now. 2400141cc406Sopenharmony_ci * 2401141cc406Sopenharmony_ci * Revision 1.44 1999/09/02 05:28:01 charter 2402141cc406Sopenharmony_ci * Added Gary Plewa's name to the list of copyrighted contributors. 2403141cc406Sopenharmony_ci * 2404141cc406Sopenharmony_ci * Revision 1.43 1999/09/02 05:23:54 charter 2405141cc406Sopenharmony_ci * Added Gary Plewa's patch for the Acer PRISA 620s. 2406141cc406Sopenharmony_ci * 2407141cc406Sopenharmony_ci * Revision 1.42 1999/09/02 02:05:34 charter 2408141cc406Sopenharmony_ci * Check-in of revision 1.42 (release 0.7 of the backend). 2409141cc406Sopenharmony_ci * This is part of the recovery from the great disk crash of Sept 1, 1999. 2410141cc406Sopenharmony_ci * 2411141cc406Sopenharmony_ci * Revision 1.42 1999/07/09 22:37:55 charter 2412141cc406Sopenharmony_ci * Potential bugfix for problems with sane_get_parameters() and 2413141cc406Sopenharmony_ci * the new generic scsi driver (suggested by Francois Desarmeni, 2414141cc406Sopenharmony_ci * Douglas Gilbert, Abel Deuring). 2415141cc406Sopenharmony_ci * 2416141cc406Sopenharmony_ci * Revision 1.41 1999/07/09 20:58:07 charter 2417141cc406Sopenharmony_ci * Changes to support SnapScan 1236s (Petter Reinholdsten). 2418141cc406Sopenharmony_ci * 2419141cc406Sopenharmony_ci * Revision 1.40 1998/12/16 18:43:06 charter 2420141cc406Sopenharmony_ci * Fixed major version problem precipitated by release of SANE-1.00. 2421141cc406Sopenharmony_ci * 2422141cc406Sopenharmony_ci * Revision 1.39 1998/09/07 06:09:26 charter 2423141cc406Sopenharmony_ci * Formatting (whitespace) changes. 2424141cc406Sopenharmony_ci * 2425141cc406Sopenharmony_ci * Revision 1.38 1998/09/07 06:06:01 charter 2426141cc406Sopenharmony_ci * Merged in Wolfgang Goeller's changes (Vuego 310S, bugfixes). 2427141cc406Sopenharmony_ci * 2428141cc406Sopenharmony_ci * Revision 1.37 1998/08/06 06:16:39 charter 2429141cc406Sopenharmony_ci * Now using sane_config_attach_matching_devices() in sane_snapscan_init(). 2430141cc406Sopenharmony_ci * Change contributed by David Mosberger-Tang. 2431141cc406Sopenharmony_ci * 2432141cc406Sopenharmony_ci * Revision 1.36 1998/05/11 17:02:53 charter 2433141cc406Sopenharmony_ci * Added Mikko's threshold stuff. 2434141cc406Sopenharmony_ci * 2435141cc406Sopenharmony_ci * Revision 1.35 1998/03/10 23:43:23 eblot 2436141cc406Sopenharmony_ci * Bug correction 2437141cc406Sopenharmony_ci * 2438141cc406Sopenharmony_ci * Revision 0.72 1998/03/10 23:40:42 eblot 2439141cc406Sopenharmony_ci * More support for 310/600 models: color preview, large window 2440141cc406Sopenharmony_ci * 2441141cc406Sopenharmony_ci * Revision 1.35 1998/03/10 21:32:07 eblot 2442141cc406Sopenharmony_ci * Debugging 2443141cc406Sopenharmony_ci * 2444141cc406Sopenharmony_ci * Revision 1.34 1998/02/15 21:55:53 charter 2445141cc406Sopenharmony_ci * From Emmanuel Blot: 2446141cc406Sopenharmony_ci * First routines to support SnapScan 310 scanned data. 2447141cc406Sopenharmony_ci * 2448141cc406Sopenharmony_ci * Revision 1.33 1998/02/06 02:30:28 charter 2449141cc406Sopenharmony_ci * Now using a mode enum (instead of the static string pointers directly). 2450141cc406Sopenharmony_ci * Now check for the SnapScan 310 and 600 explicitly (start of support 2451141cc406Sopenharmony_ci * for these models). 2452141cc406Sopenharmony_ci * 2453141cc406Sopenharmony_ci * Revision 1.32 1998/02/01 21:56:48 charter 2454141cc406Sopenharmony_ci * Patches to fix compilation problems on Solaris supplied by 2455141cc406Sopenharmony_ci * Jim McBeath. 2456141cc406Sopenharmony_ci * 2457141cc406Sopenharmony_ci * Revision 1.31 1998/02/01 03:36:40 charter 2458141cc406Sopenharmony_ci * Now check for BRX < TLX and BRY < TLY and whether the area of the 2459141cc406Sopenharmony_ci * scanning window is approaching zero in set_window. I'm setting a 2460141cc406Sopenharmony_ci * minimum window size of 75x75 hardware pixels (0.25 inches a side). 2461141cc406Sopenharmony_ci * If the area falls to zero, the scanner seems to hang in the middle 2462141cc406Sopenharmony_ci * of the set_window command. 2463141cc406Sopenharmony_ci * 2464141cc406Sopenharmony_ci * Revision 1.30 1998/02/01 00:00:33 charter 2465141cc406Sopenharmony_ci * TLX, TLY, BRX and BRY are now lengths expressed in mm. The frontends 2466141cc406Sopenharmony_ci * can now allow changes in the units, and units that are more user- 2467141cc406Sopenharmony_ci * friendly. 2468141cc406Sopenharmony_ci * 2469141cc406Sopenharmony_ci * Revision 1.29 1998/01/31 21:09:19 charter 2470141cc406Sopenharmony_ci * Fixed another problem with add_device(): if mini_inquiry ends 2471141cc406Sopenharmony_ci * up indirectly invoking the sense handler, there'll be a segfault 2472141cc406Sopenharmony_ci * because the sense_handler isn't set. Had to fix sense_handler so 2473141cc406Sopenharmony_ci * it can handle a NULL pss pointer and then use the sanei_scsi stuff 2474141cc406Sopenharmony_ci * everywhere. This error is most likely to occur if the scanner is 2475141cc406Sopenharmony_ci * turned off. 2476141cc406Sopenharmony_ci * 2477141cc406Sopenharmony_ci * Revision 1.28 1998/01/31 18:45:22 charter 2478141cc406Sopenharmony_ci * Last fix botched, produced a compile error. Thought I'd already 2479141cc406Sopenharmony_ci * compiled successfully. 2480141cc406Sopenharmony_ci * 2481141cc406Sopenharmony_ci * Revision 1.27 1998/01/31 18:32:42 charter 2482141cc406Sopenharmony_ci * Fixed stupid bug in add_device that causes segfault when no snapscan 2483141cc406Sopenharmony_ci * found: closing a scsi fd opened with open() using sanei_scsi_close(). 2484141cc406Sopenharmony_ci * 2485141cc406Sopenharmony_ci * Revision 1.26 1998/01/30 21:19:02 charter 2486141cc406Sopenharmony_ci * sane_snapscan_init() handles failure of add_device() in the same 2487141cc406Sopenharmony_ci * way when there is no snapscan.conf file available as when there is 2488141cc406Sopenharmony_ci * one. 2489141cc406Sopenharmony_ci * 2490141cc406Sopenharmony_ci * Revision 1.25 1998/01/30 19:41:11 charter 2491141cc406Sopenharmony_ci * Waiting for child process termination at regular end of scan (not 2492141cc406Sopenharmony_ci * just on cancellation); before I was getting zombies. 2493141cc406Sopenharmony_ci * 2494141cc406Sopenharmony_ci * Revision 1.24 1998/01/30 19:19:27 charter 2495141cc406Sopenharmony_ci * Changed from strncmp() to strncasecmp() to do vendor and model 2496141cc406Sopenharmony_ci * comparisons in sane_snapscan_init. There are some snapcsan models 2497141cc406Sopenharmony_ci * that use lower case. 2498141cc406Sopenharmony_ci * Now have debug level defines instead of raw numbers, and better debug 2499141cc406Sopenharmony_ci * information categories. 2500141cc406Sopenharmony_ci * Don't complain at debug level 0 when a snapscan isn't found on a 2501141cc406Sopenharmony_ci * requested device. 2502141cc406Sopenharmony_ci * Changed CHECK_STATUS to take caller parameter instead of always 2503141cc406Sopenharmony_ci * assuming an available string "me". 2504141cc406Sopenharmony_ci * 2505141cc406Sopenharmony_ci * Revision 1.23 1998/01/30 11:03:04 charter 2506141cc406Sopenharmony_ci * Fixed * vs [] operator precedence screwup in sane_snapscan_get_devices() 2507141cc406Sopenharmony_ci * that caused a segfault in scanimage -h. 2508141cc406Sopenharmony_ci * Fixed problem with not closing the scsi fd between certain commands 2509141cc406Sopenharmony_ci * that caused scanimage to hang; now using open_scanner() and close_scanner(). 2510141cc406Sopenharmony_ci * 2511141cc406Sopenharmony_ci * Revision 1.22 1998/01/28 09:02:55 charter 2512141cc406Sopenharmony_ci * Fixed bug: zero allocation length in request sense command buffer 2513141cc406Sopenharmony_ci * was preventing sense information from being received. The 2514141cc406Sopenharmony_ci * backend now correctly waits for the scanner to warm up. 2515141cc406Sopenharmony_ci * Now using the hardware configuration byte to check whether 2516141cc406Sopenharmony_ci * both 8x8 and 16x16 halftoning should be made available. 2517141cc406Sopenharmony_ci * 2518141cc406Sopenharmony_ci * Revision 1.21 1998/01/25 09:57:57 charter 2519141cc406Sopenharmony_ci * Added more SCSI command buttons (and a group for them). 2520141cc406Sopenharmony_ci * Made the output of the Inquiry command a bit nicer. 2521141cc406Sopenharmony_ci * 2522141cc406Sopenharmony_ci * Revision 1.20 1998/01/25 08:53:14 charter 2523141cc406Sopenharmony_ci * Have added bi-level colour mode, with halftones too. 2524141cc406Sopenharmony_ci * Can now select preview mode (but it's an advanced option, since 2525141cc406Sopenharmony_ci * you usually don't want to do it). 2526141cc406Sopenharmony_ci * 2527141cc406Sopenharmony_ci * Revision 1.19 1998/01/25 02:25:02 charter 2528141cc406Sopenharmony_ci * Fixed bug: preview mode gives blank image at initial startup. 2529141cc406Sopenharmony_ci * Fixed bug: lineart mode goes weird after a preview or gs image. 2530141cc406Sopenharmony_ci * More changes to option relationships; 2531141cc406Sopenharmony_ci * now using test_unit_ready and send_diagnostic in sane_snapscan_open(). 2532141cc406Sopenharmony_ci * Added negative option. 2533141cc406Sopenharmony_ci * 2534141cc406Sopenharmony_ci * Revision 1.18 1998/01/24 05:15:32 charter 2535141cc406Sopenharmony_ci * Now have RGB gamma correction and dispersed-dot dither halftoning 2536141cc406Sopenharmony_ci * for BW images. Cleaned up some spots in the code and have set up 2537141cc406Sopenharmony_ci * option interactions a bit better (e.g. halftoning and GS gamma 2538141cc406Sopenharmony_ci * correction made inactive in colour mode, etc). TL_[XY] and BR_[XY] 2539141cc406Sopenharmony_ci * now change in ten-pixel increments (I had problems with screwed-up 2540141cc406Sopenharmony_ci * scan lines when the dimensions were weird at low res... could be the 2541141cc406Sopenharmony_ci * problem). 2542141cc406Sopenharmony_ci * 2543141cc406Sopenharmony_ci * Revision 1.17 1998/01/23 13:03:17 charter 2544141cc406Sopenharmony_ci * Several changes, all aimed at getting scanning performance working 2545141cc406Sopenharmony_ci * correctly, and the progress/cancel window functioning. Cleaned up 2546141cc406Sopenharmony_ci * a few nasty things as well. 2547141cc406Sopenharmony_ci * 2548141cc406Sopenharmony_ci * Revision 1.16 1998/01/23 07:40:23 charter 2549141cc406Sopenharmony_ci * Reindented using GNU convention at David Mosberger-Tang's request. 2550141cc406Sopenharmony_ci * Also applied David's patch fixing problems on 64-bit architectures. 2551141cc406Sopenharmony_ci * Now using scanner's reported speed to gauge amount of data to request 2552141cc406Sopenharmony_ci * in a read on the scsi fd---nonblocking mode operates better now. 2553141cc406Sopenharmony_ci * Fixed stupid bug I introduced in preview mode data transfer. 2554141cc406Sopenharmony_ci * 2555141cc406Sopenharmony_ci * Revision 1.15 1998/01/22 06:18:57 charter 2556141cc406Sopenharmony_ci * Raised the priority of a couple of DBG messages in reserve_unit() 2557141cc406Sopenharmony_ci * and release_unit(), and got rid of some unnecessary ones. 2558141cc406Sopenharmony_ci * 2559141cc406Sopenharmony_ci * Revision 1.14 1998/01/22 05:15:35 charter 2560141cc406Sopenharmony_ci * Have replaced the bit depth option with a mode option; various 2561141cc406Sopenharmony_ci * changes associated with that. 2562141cc406Sopenharmony_ci * Also, I again close the STDERR_FILENO in the reader child and 2563141cc406Sopenharmony_ci * dup the STDOUT file descriptor onto it. This prevents an "X io" 2564141cc406Sopenharmony_ci * error when the child exits, while still allowing the use of 2565141cc406Sopenharmony_ci * DBG. 2566141cc406Sopenharmony_ci * 2567141cc406Sopenharmony_ci * Revision 1.13 1998/01/21 20:41:22 charter 2568141cc406Sopenharmony_ci * Added copyright info. 2569141cc406Sopenharmony_ci * Also now seem to have cancellation working. This requires using a 2570141cc406Sopenharmony_ci * new scanner state variable and checking in all the right places 2571141cc406Sopenharmony_ci * in the reader child and the sane_snapscan_read function. I've 2572141cc406Sopenharmony_ci * tested it using both blocking and nonblocking I/O and it seems 2573141cc406Sopenharmony_ci * to work both ways. 2574141cc406Sopenharmony_ci * I've also switched to GTK+-0.99.2 and sane-0.69, and the 2575141cc406Sopenharmony_ci * mysterious problems with the preview window have disappeared. 2576141cc406Sopenharmony_ci * Problems with scanimage doing weird things to options have also 2577141cc406Sopenharmony_ci * gone away and the frontends seem more stable. 2578141cc406Sopenharmony_ci * 2579141cc406Sopenharmony_ci * Revision 1.12 1998/01/21 11:05:53 charter 2580141cc406Sopenharmony_ci * Inoperative code largely #defined out; I had the preview window 2581141cc406Sopenharmony_ci * working correctly by having the window coordinates properly 2582141cc406Sopenharmony_ci * constrained, but now the preview window bombs with a floating- 2583141cc406Sopenharmony_ci * point error each time... I'm not sure yet what happened. 2584141cc406Sopenharmony_ci * I've also figured out that we need to use reserve_unit and 2585141cc406Sopenharmony_ci * release_unit in order to cancel scans in progress. This works 2586141cc406Sopenharmony_ci * under scanimage, but I can't seem to find a way to fit cancellation 2587141cc406Sopenharmony_ci * into xscanimage properly. 2588141cc406Sopenharmony_ci * 2589141cc406Sopenharmony_ci * Revision 1.11 1998/01/20 22:42:08 charter 2590141cc406Sopenharmony_ci * Applied Franck's patch from Dec 17; preview mode is now grayscale. 2591141cc406Sopenharmony_ci * 2592141cc406Sopenharmony_ci * Revision 1.10 1997/12/10 23:33:12 charter 2593141cc406Sopenharmony_ci * Slight change to some floating-point computations in the brightness 2594141cc406Sopenharmony_ci * and contrast stuff. The controls don't seem to do anything to the 2595141cc406Sopenharmony_ci * scanner though (I think these aren't actually supported in the 2596141cc406Sopenharmony_ci * SnapScan). 2597141cc406Sopenharmony_ci * 2598141cc406Sopenharmony_ci * Revision 1.9 1997/11/26 15:40:50 charter 2599141cc406Sopenharmony_ci * Brightness and contrast added by Michel. 2600141cc406Sopenharmony_ci * 2601141cc406Sopenharmony_ci * Revision 1.8 1997/11/12 12:55:40 charter 2602141cc406Sopenharmony_ci * No longer exec after forking to do nonblocking scanning; found how 2603141cc406Sopenharmony_ci * to fix the problems with SIGPIPEs from before. 2604141cc406Sopenharmony_ci * Now support a config file like the other scanner drivers, and 2605141cc406Sopenharmony_ci * can check whether a given device is an AGFA SnapScan (mini_inquiry()). 2606141cc406Sopenharmony_ci * 2607141cc406Sopenharmony_ci * Revision 1.7 1997/11/10 05:52:08 charter 2608141cc406Sopenharmony_ci * Now have the child reader process and pipe stuff working, and 2609141cc406Sopenharmony_ci * nonblocking mode. For large scans the nonblocking mode actually 2610141cc406Sopenharmony_ci * seems to cut down on cpu hogging (though there is still a hit). 2611141cc406Sopenharmony_ci * 2612141cc406Sopenharmony_ci * Revision 1.6 1997/11/03 07:45:54 charter 2613141cc406Sopenharmony_ci * Added the predef_window stuff. I've tried it with 6x4, and it seems 2614141cc406Sopenharmony_ci * to work; I think something gets inconsistent if a preview is 2615141cc406Sopenharmony_ci * performed though. 2616141cc406Sopenharmony_ci * 2617141cc406Sopenharmony_ci * Revision 1.5 1997/11/03 03:15:27 charter 2618141cc406Sopenharmony_ci * Global static variables have now become part of the scanner structure; 2619141cc406Sopenharmony_ci * the inquiry command automatically retrieves window parameters into 2620141cc406Sopenharmony_ci * scanner structure members. Things are a bit cleaned up. 2621141cc406Sopenharmony_ci * 2622141cc406Sopenharmony_ci * Revision 1.4 1997/11/02 23:35:28 charter 2623141cc406Sopenharmony_ci * After much grief.... I can finally scan reliably. Now it's a matter 2624141cc406Sopenharmony_ci * of getting the band arrangement sorted out. 2625141cc406Sopenharmony_ci * 2626141cc406Sopenharmony_ci * Revision 1.3 1997/10/30 07:36:37 charter 2627141cc406Sopenharmony_ci * Fixed a stupid bug in the #defines for the inquiry command, pointed out 2628141cc406Sopenharmony_ci * by Franck. 2629141cc406Sopenharmony_ci * 2630141cc406Sopenharmony_ci * Revision 1.2 1997/10/14 06:00:11 charter 2631141cc406Sopenharmony_ci * Option manipulation and some basic SCSI commands done; the basics 2632141cc406Sopenharmony_ci * for scanning are written but there are bugs. A full scan always hangs 2633141cc406Sopenharmony_ci * the SCSI driver, and preview mode scans complete but it isn't clear 2634141cc406Sopenharmony_ci * whether any meaningful data is received. 2635141cc406Sopenharmony_ci * 2636141cc406Sopenharmony_ci * Revision 1.1 1997/10/13 02:25:54 charter 2637141cc406Sopenharmony_ci * Initial revision 2638141cc406Sopenharmony_ci * */ 2639