1999-08-09 18:06:01 +00:00
|
|
|
|
/* sane - Scanner Access Now Easy.
|
2001-10-12 21:19:16 +00:00
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
Copyright (C) 1997, 1998, 2001 Franck Schnefra, Michel Roelofs,
|
2000-03-05 13:57:25 +00:00
|
|
|
|
Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson,
|
|
|
|
|
Oliver Schwartz and Kevin Charter
|
2002-04-23 22:37:54 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
This file is part of the SANE package.
|
2002-04-23 22:37:54 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
2001-10-09 09:45:21 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
General Public License for more details.
|
2001-10-09 09:45:21 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
|
|
|
MA 02111-1307, USA.
|
2002-04-23 22:37:54 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
As a special exception, the authors of SANE give permission for
|
|
|
|
|
additional uses of the libraries contained in this release of SANE.
|
2000-08-12 15:11:46 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
The exception is that, if you link a SANE library with other files
|
|
|
|
|
to produce an executable, this does not by itself cause the
|
|
|
|
|
resulting executable to be covered by the GNU General Public
|
|
|
|
|
License. Your use of that executable is in no way restricted on
|
|
|
|
|
account of linking the SANE library code into it.
|
2001-10-09 09:45:21 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
This exception does not, however, invalidate any other reasons why
|
|
|
|
|
the executable file might be covered by the GNU General Public
|
|
|
|
|
License.
|
2002-04-23 22:37:54 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
If you submit changes to SANE to the maintainers to be included in
|
|
|
|
|
a subsequent release, you agree by submitting the changes that
|
|
|
|
|
those changes may be distributed with this exception intact.
|
2002-04-23 22:37:54 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
If you write modifications of your own for SANE, it is your choice
|
|
|
|
|
whether to permit this exception to apply to your modifications.
|
|
|
|
|
If you do not wish that, delete this exception notice.
|
2001-10-09 09:45:21 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
This file is a component of the implementation of a backend for many
|
|
|
|
|
of the the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* $Id$
|
|
|
|
|
SANE SnapScan backend */
|
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
#include "../include/sane/config.h"
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
#include "../include/sane/sane.h"
|
|
|
|
|
#include "../include/sane/sanei.h"
|
|
|
|
|
#include "../include/sane/sanei_scsi.h"
|
2001-10-27 09:08:17 +00:00
|
|
|
|
#include "../include/sane/sanei_usb.h"
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
#ifndef PATH_MAX
|
2001-10-09 09:45:21 +00:00
|
|
|
|
#define PATH_MAX 1024
|
1999-08-09 18:06:01 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2001-10-25 10:56:41 +00:00
|
|
|
|
#define EXPECTED_MAJOR 1
|
|
|
|
|
#define MINOR_VERSION 4
|
2002-10-14 21:49:45 +00:00
|
|
|
|
#define BUILD 17
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
#include "snapscan.h"
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
#define BACKEND_NAME snapscan
|
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
#include "../include/sane/sanei_backend.h"
|
|
|
|
|
#include "../include/sane/saneopts.h"
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
#define MIN(x,y) ((x)<(y) ? (x) : (y))
|
|
|
|
|
#define MAX(x,y) ((x)>(y) ? (x) : (y))
|
2001-05-26 12:47:34 +00:00
|
|
|
|
#define LIMIT(x,min,max) MIN(MAX(x, min), max)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
#ifdef INOPERATIVE
|
|
|
|
|
#define P_200_TO_255(per) SANE_UNFIX(255.0*((per + 100)/200.0))
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
#include "../include/sane/sanei_config.h"
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
/* debug levels */
|
2002-04-23 22:37:54 +00:00
|
|
|
|
#define DL_INFO 10
|
|
|
|
|
#define DL_MINOR_INFO 15
|
1999-08-09 18:06:01 +00:00
|
|
|
|
#define DL_MAJOR_ERROR 1
|
|
|
|
|
#define DL_MINOR_ERROR 2
|
2002-04-23 22:37:54 +00:00
|
|
|
|
#define DL_DATA_TRACE 50
|
|
|
|
|
#define DL_CALL_TRACE 30
|
|
|
|
|
#define DL_VERBOSE 20
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
#define CHECK_STATUS(s,caller,cmd) \
|
|
|
|
|
if ((s) != SANE_STATUS_GOOD) { DBG(DL_MAJOR_ERROR, "%s: %s command failed: %s\n", caller, (cmd), sane_strstatus(s)); return s; }
|
|
|
|
|
|
|
|
|
|
/*----- internal scanner operations -----*/
|
|
|
|
|
|
|
|
|
|
/* hardware configuration byte masks */
|
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
#define HCFG_ADC 0x80 /* AD converter 1 ==> 10bit, 0 ==> 8bit */
|
|
|
|
|
#define HCFG_ADF 0x40 /* automatic document feeder */
|
|
|
|
|
#define HCFG_TPO 0x20 /* transparency option */
|
|
|
|
|
#define HCFG_RB 0x10 /* ring buffer */
|
|
|
|
|
#define HCFG_HT16 0x08 /* 16x16 halftone matrices */
|
|
|
|
|
#define HCFG_HT8 0x04 /* 8x8 halftone matrices */
|
|
|
|
|
#define HCFG_SRA 0x02 /* scanline row average (high-speed colour) */
|
|
|
|
|
#define HCFG_CAL_ALLOWED 0x01 /* 1 ==> calibration allowed */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
#define HCFG_HT 0x0C /* support halftone matrices at all */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
#define MM_PER_IN 25.4 /* # millimetres per inch */
|
|
|
|
|
#define IN_PER_MM 0.03937 /* # inches per millimetre */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
/* default option values */
|
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
#define DEFAULT_RES 300
|
|
|
|
|
#define DEFAULT_PREVIEW SANE_FALSE
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
#define DEFAULT_BRIGHTNESS 0
|
|
|
|
|
#define DEFAULT_CONTRAST 0
|
|
|
|
|
#define DEFAULT_GAMMA SANE_FIX(1.8)
|
|
|
|
|
#define DEFAULT_HALFTONE SANE_FALSE
|
|
|
|
|
#define DEFAULT_NEGATIVE SANE_FALSE
|
|
|
|
|
#define DEFAULT_THRESHOLD 50
|
|
|
|
|
#define DEFAULT_QUALITY SANE_TRUE
|
|
|
|
|
#define DEFAULT_CUSTOM_GAMMA SANE_FALSE
|
|
|
|
|
#define DEFAULT_GAMMA_BIND SANE_FALSE
|
2000-08-12 15:11:46 +00:00
|
|
|
|
|
2002-02-09 15:03:07 +00:00
|
|
|
|
#ifndef SANE_I18N
|
|
|
|
|
#define SANE_I18N(text) text
|
|
|
|
|
#endif
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
static SANE_Int def_rgb_lpr = 4;
|
|
|
|
|
static SANE_Int def_gs_lpr = 12;
|
|
|
|
|
|
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
/* predefined preview mode name */
|
|
|
|
|
static char md_auto[] = "Auto";
|
2001-05-26 12:47:34 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
/* predefined scan mode names */
|
2002-02-09 15:03:07 +00:00
|
|
|
|
static char md_colour[] = SANE_I18N("Color");
|
|
|
|
|
static char md_bilevelcolour[] = SANE_I18N("Halftone");
|
|
|
|
|
static char md_greyscale[] = SANE_I18N("Gray");
|
|
|
|
|
static char md_lineart[] = SANE_I18N("Lineart");
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* predefined scan source names */
|
2002-02-09 15:03:07 +00:00
|
|
|
|
static char src_flatbed[] = SANE_I18N("Flatbed");
|
|
|
|
|
static char src_tpo[] = SANE_I18N("Transparency Adapter");
|
2002-05-02 17:19:20 +00:00
|
|
|
|
static char src_adf[] = SANE_I18N("Document Feeder");
|
2000-08-12 15:11:46 +00:00
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
/* predefined scan window setting names */
|
2002-02-09 15:03:07 +00:00
|
|
|
|
static char pdw_none[] = SANE_I18N("none");
|
|
|
|
|
static char pdw_6X4[] = SANE_I18N("6x4 (inch)");
|
|
|
|
|
static char pdw_8X10[] = SANE_I18N("8x10 (inch)");
|
|
|
|
|
static char pdw_85X11[] = SANE_I18N("8.5x11 (inch)");
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
/* predefined dither matrix names */
|
2002-02-09 15:03:07 +00:00
|
|
|
|
static char dm_none[] = SANE_I18N("Halftoning Unsupported");
|
|
|
|
|
static char dm_dd8x8[] = SANE_I18N("DispersedDot8x8");
|
|
|
|
|
static char dm_dd16x16[] = SANE_I18N("DispersedDot16x16");
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
/* strings */
|
2002-02-09 15:03:07 +00:00
|
|
|
|
static char lpr_desc[] = SANE_I18N(
|
2000-08-12 15:11:46 +00:00
|
|
|
|
"Number of scan lines to request in a SCSI read. "
|
|
|
|
|
"Changing this parameter allows you to tune the speed at which "
|
|
|
|
|
"data is read from the scanner during scans. If this is set too "
|
|
|
|
|
"low, the scanner will have to stop periodically in the middle of "
|
|
|
|
|
"a scan; if it's set too high, X-based frontends may stop responding "
|
2002-02-09 15:03:07 +00:00
|
|
|
|
"to X events and your system could bog down.");
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
/* authorization stuff */
|
|
|
|
|
static SANE_Auth_Callback auth = NULL;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
#if UNUSED
|
1999-08-09 18:06:01 +00:00
|
|
|
|
static SANE_Char username[SANE_MAX_USERNAME_LEN];
|
|
|
|
|
static SANE_Char password[SANE_MAX_PASSWORD_LEN];
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* bit depth tables */
|
2001-10-09 09:45:21 +00:00
|
|
|
|
static u_char depths8[MD_NUM_MODES] = {8, 1, 8, 1};
|
|
|
|
|
static u_char depths10[MD_NUM_MODES] = {10, 1, 10, 1};
|
|
|
|
|
static u_char depths12[MD_NUM_MODES] = {12, 1, 12, 1};
|
|
|
|
|
static u_char depths14[MD_NUM_MODES] = {14, 1, 14, 1};
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
/* function prototypes */
|
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
static void gamma_n (double gamma, int brightness, int contrast,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
u_char *buf, int length);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
static void gamma_to_sane (int length, u_char *in, SANE_Int *out);
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
static size_t max_string_size(SANE_String_Const strings[]);
|
|
|
|
|
|
|
|
|
|
/* inline functions */
|
2001-05-26 12:47:34 +00:00
|
|
|
|
static inline SnapScan_Mode actual_mode (SnapScan_Scanner *pss)
|
|
|
|
|
{
|
|
|
|
|
if (pss->preview == SANE_TRUE)
|
|
|
|
|
return pss->preview_mode;
|
|
|
|
|
return pss->mode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int is_colour_mode (SnapScan_Mode m)
|
|
|
|
|
{
|
|
|
|
|
return (m == MD_COLOUR) || (m == MD_BILEVELCOLOUR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int calibration_line_length(SnapScan_Scanner *pss)
|
|
|
|
|
{
|
|
|
|
|
int pixel_length = pss->actual_res * 8.5;
|
|
|
|
|
|
|
|
|
|
if(is_colour_mode(actual_mode(pss))) {
|
2001-10-09 09:45:21 +00:00
|
|
|
|
return 3 * pixel_length;
|
2001-05-26 12:47:34 +00:00
|
|
|
|
} else {
|
2001-10-09 09:45:21 +00:00
|
|
|
|
return pixel_length;
|
2001-05-26 12:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
/*----- global data structures and access utilities -----*/
|
|
|
|
|
|
|
|
|
|
/* available device list */
|
|
|
|
|
|
|
|
|
|
static SnapScan_Device *first_device = NULL; /* device list head */
|
|
|
|
|
static SANE_Int n_devices = 0; /* the device count */
|
|
|
|
|
static SANE_Char *default_firmware_filename;
|
|
|
|
|
|
|
|
|
|
/* list returned from sane_get_devices() */
|
|
|
|
|
static const SANE_Device **get_devices_list = NULL;
|
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
/* external routines */
|
2000-08-12 15:11:46 +00:00
|
|
|
|
#include "snapscan-scsi.c"
|
|
|
|
|
#include "snapscan-sources.c"
|
2001-05-26 12:47:34 +00:00
|
|
|
|
#include "snapscan-usb.c"
|
2002-03-24 12:32:38 +00:00
|
|
|
|
#include "snapscan-options.c"
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
/* Initialize gamma tables */
|
|
|
|
|
static SANE_Status init_gamma(SnapScan_Scanner * ps)
|
|
|
|
|
{
|
|
|
|
|
u_char *gamma;
|
|
|
|
|
int bpp = (ps->hconfig & HCFG_ADC) ? 10 : 8;
|
|
|
|
|
|
|
|
|
|
ps->gamma_length = 1 << bpp;
|
|
|
|
|
|
|
|
|
|
ps->gamma_tables =
|
2001-10-09 09:45:21 +00:00
|
|
|
|
(SANE_Int *) malloc(4 * ps->gamma_length * sizeof(SANE_Int));
|
2001-05-26 12:47:34 +00:00
|
|
|
|
|
|
|
|
|
gamma = (u_char*) malloc(ps->gamma_length * sizeof(u_char));
|
|
|
|
|
|
|
|
|
|
if (!ps->gamma_tables || !gamma)
|
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
if (ps->gamma_tables)
|
|
|
|
|
free (ps->gamma_tables);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
if (gamma)
|
|
|
|
|
free (gamma);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
|
|
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ps->gamma_table_gs = &ps->gamma_tables[0 * ps->gamma_length];
|
|
|
|
|
ps->gamma_table_r = &ps->gamma_tables[1 * ps->gamma_length];
|
|
|
|
|
ps->gamma_table_g = &ps->gamma_tables[2 * ps->gamma_length];
|
|
|
|
|
ps->gamma_table_b = &ps->gamma_tables[3 * ps->gamma_length];
|
2002-02-09 15:03:07 +00:00
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
/* Default tables */
|
|
|
|
|
gamma_n (ps->gamma_gs, ps->bright, ps->contrast, gamma, bpp);
|
|
|
|
|
gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_gs);
|
|
|
|
|
|
|
|
|
|
gamma_n (ps->gamma_r, ps->bright, ps->contrast, gamma, bpp);
|
|
|
|
|
gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_r);
|
|
|
|
|
|
|
|
|
|
gamma_n (ps->gamma_g, ps->bright, ps->contrast, gamma, bpp);
|
|
|
|
|
gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_g);
|
|
|
|
|
|
|
|
|
|
gamma_n (ps->gamma_b, ps->bright, ps->contrast, gamma, bpp);
|
|
|
|
|
gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_b);
|
|
|
|
|
|
|
|
|
|
free (gamma);
|
|
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* Max string size */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static size_t max_string_size (SANE_String_Const strings[])
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
size_t size;
|
|
|
|
|
size_t max_size = 0;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; strings[i]; ++i)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
size = strlen (strings[i]) + 1;
|
|
|
|
|
if (size > max_size)
|
|
|
|
|
max_size = size;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return max_size;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* gamma table computation */
|
2001-05-26 12:47:34 +00:00
|
|
|
|
static void gamma_n (double gamma, int brightness, int contrast,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
u_char *buf, int bpp)
|
2000-08-12 15:11:46 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
double i_gamma = 1.0/gamma;
|
2001-05-26 12:47:34 +00:00
|
|
|
|
int length = 1 << bpp;
|
|
|
|
|
int max = length - 1;
|
|
|
|
|
double mid = max / 2.0;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
double val = (i - mid) * (1.0 + contrast / 100.0)
|
|
|
|
|
+ (1.0 + brightness / 100.0) * mid;
|
|
|
|
|
val = LIMIT(val, 0, max);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
buf[i] =
|
2001-10-09 09:45:21 +00:00
|
|
|
|
(u_char) LIMIT(255*pow ((double) val/max, i_gamma) + 0.5, 0, 255);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gamma_from_sane (int length, SANE_Int *in, u_char *out)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < length; i++)
|
2001-10-09 09:45:21 +00:00
|
|
|
|
out[i] = (u_char) LIMIT(in[i], 0, 255);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gamma_to_sane (int length, u_char *in, SANE_Int *out)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < length; i++)
|
2001-10-09 09:45:21 +00:00
|
|
|
|
out[i] = in[i];
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
/* dispersed-dot dither matrices; this is discussed in Foley, Van Dam,
|
2001-12-17 22:51:52 +00:00
|
|
|
|
Feiner and Hughes: Computer Graphics: principles and practice,
|
|
|
|
|
2nd ed. (Addison-Wesley), pp 570-571.
|
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
The function mfDn computes the nth dispersed-dot dither matrix Dn
|
|
|
|
|
given D(n/2) and n; n is presumed to be a power of 2. D8 and D16
|
|
|
|
|
are the matrices of interest to us, since the SnapScan supports
|
|
|
|
|
only 8x8 and 16x16 dither matrices. */
|
|
|
|
|
|
2001-12-17 22:51:52 +00:00
|
|
|
|
static u_char D2[] ={0, 2, 3, 1};
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
|
|
|
|
static u_char D4[16], D8[64], D16[256];
|
|
|
|
|
|
2001-12-17 22:51:52 +00:00
|
|
|
|
static void mkDn (u_char *Dn, u_char *Dn_half, unsigned n)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2001-12-17 22:51:52 +00:00
|
|
|
|
unsigned int x, y;
|
|
|
|
|
for (y = 0; y < n; y++) {
|
|
|
|
|
for (x = 0; x < n; x++) {
|
|
|
|
|
/* Dn(x,y) = D2(2*x/n, 2*y/n) +4*Dn_half(x%(n/2), y%(n/2)) */
|
|
|
|
|
Dn[y*n + x] = D2[((int)(2*y/n))*2 + (int)(2*x/n)]
|
|
|
|
|
+ 4*Dn_half[(y%(n/2))*(n/2) + x%(n/2)];
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static SANE_Bool device_already_in_list (SnapScan_Device *current,
|
|
|
|
|
SANE_String_Const name)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
for ( ; NULL != current; current = current->pnext)
|
|
|
|
|
{
|
|
|
|
|
if (0 == strcmp (name, current->dev.name))
|
|
|
|
|
return SANE_TRUE;
|
|
|
|
|
}
|
|
|
|
|
return SANE_FALSE;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
static SANE_Char* get_driver_name(SnapScan_Model model_num) {
|
|
|
|
|
SANE_Int i;
|
|
|
|
|
for (i=0; i<known_drivers; i++) {
|
|
|
|
|
if (drivers[i].id == model_num) break;
|
2001-10-27 09:08:17 +00:00
|
|
|
|
}
|
2002-03-24 12:32:38 +00:00
|
|
|
|
if (drivers[i].id != model_num) {
|
|
|
|
|
DBG(0, "Implementation error: Driver name not found\n");
|
|
|
|
|
return ("Unknown");
|
2001-10-27 09:08:17 +00:00
|
|
|
|
}
|
2002-03-24 12:32:38 +00:00
|
|
|
|
return (drivers[i].driver_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SANE_Status snapscani_check_device(
|
|
|
|
|
int fd,
|
|
|
|
|
SnapScan_Bus bus_type,
|
|
|
|
|
char* vendor,
|
|
|
|
|
char* model,
|
|
|
|
|
SnapScan_Model* model_num
|
|
|
|
|
) {
|
|
|
|
|
static const char me[] = "snapscani_check_device";
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
|
|
|
int supported_vendor = 0;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
DBG (DL_CALL_TRACE, "%s()\n", me);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* check that the device is legitimate */
|
2001-05-26 12:47:34 +00:00
|
|
|
|
if ((status = mini_inquiry (bus_type, fd, vendor, model)) != SANE_STATUS_GOOD)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: mini_inquiry failed with %s.\n",
|
|
|
|
|
me,
|
|
|
|
|
sane_strstatus (status));
|
|
|
|
|
return status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_VERBOSE,
|
|
|
|
|
"%s: Is vendor \"%s\" model \"%s\" a supported scanner?\n",
|
|
|
|
|
me,
|
|
|
|
|
vendor,
|
|
|
|
|
model);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* check if this is one of our supported vendors */
|
|
|
|
|
for (i = 0; i < known_vendors; i++)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (0 == strcasecmp (vendor, vendors[i]))
|
|
|
|
|
{
|
|
|
|
|
supported_vendor = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (supported_vendor)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
/* Known vendor. Check if it is one of our supported models */
|
2002-03-24 12:32:38 +00:00
|
|
|
|
*model_num = snapscani_get_model_id(model, fd, bus_type);
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (!supported_vendor || UNKNOWN == model_num)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MINOR_ERROR,
|
|
|
|
|
"%s: \"%s %s\" is not one of %s\n",
|
|
|
|
|
me,
|
|
|
|
|
vendor,
|
|
|
|
|
model,
|
2002-10-14 21:49:45 +00:00
|
|
|
|
"AGFA SnapScan 300, 310, 600, 1212, 1236, e10, e20, e25, e26, "
|
2002-01-10 22:20:17 +00:00
|
|
|
|
"e40, e42, e50, e52 or e60\n"
|
2001-12-17 22:51:52 +00:00
|
|
|
|
"Acer 300, 310, 610, 610+, "
|
|
|
|
|
"620, 620+, 640, 1240, 3300, 4300 or 5300\n"
|
|
|
|
|
"Guillemot MaxiScan A4 Deluxe");
|
2002-03-24 12:32:38 +00:00
|
|
|
|
status = SANE_STATUS_INVAL;
|
|
|
|
|
} else {
|
2002-09-26 20:09:24 +00:00
|
|
|
|
DBG(DL_VERBOSE, "%s: Autodetected driver: %s\n", me, get_driver_name(*model_num));
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2002-03-24 12:32:38 +00:00
|
|
|
|
return status;
|
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
static SANE_Status snapscani_init_device_structure(
|
|
|
|
|
SnapScan_Device **pd,
|
|
|
|
|
const SnapScan_Bus bus_type,
|
|
|
|
|
SANE_String_Const name,
|
|
|
|
|
const char* vendor,
|
|
|
|
|
const char* model,
|
|
|
|
|
const SnapScan_Model model_num
|
|
|
|
|
) {
|
|
|
|
|
static const char me[] = "snapscani_init_device_structure";
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;;
|
|
|
|
|
|
|
|
|
|
DBG (DL_CALL_TRACE, "%s()\n", me);
|
|
|
|
|
|
|
|
|
|
(*pd) = (SnapScan_Device *) malloc (sizeof (SnapScan_Device));
|
|
|
|
|
if (!(*pd))
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR, "%s: out of memory allocating device.", me);
|
|
|
|
|
return SANE_STATUS_NO_MEM;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2002-03-24 12:32:38 +00:00
|
|
|
|
(*pd)->dev.name = strdup (name);
|
|
|
|
|
if (strcmp(vendor, "Color") == 0) {
|
|
|
|
|
(*pd)->dev.vendor = strdup ("Acer");
|
|
|
|
|
} else {
|
|
|
|
|
(*pd)->dev.vendor = strdup (vendor);
|
|
|
|
|
}
|
|
|
|
|
(*pd)->dev.model = strdup (model);
|
|
|
|
|
(*pd)->dev.type = strdup (SNAPSCAN_TYPE);
|
|
|
|
|
(*pd)->bus = bus_type;
|
|
|
|
|
(*pd)->model = model_num;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
switch (model_num)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
|
|
|
|
case SNAPSCAN300:
|
2002-03-24 12:32:38 +00:00
|
|
|
|
(*pd)->depths = depths8;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
case PRISA620S:
|
2002-03-24 12:32:38 +00:00
|
|
|
|
(*pd)->depths = depths12;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
2001-10-09 09:45:21 +00:00
|
|
|
|
case PRISA4300_2:
|
|
|
|
|
case PRISA5300:
|
2002-03-24 12:32:38 +00:00
|
|
|
|
(*pd)->depths = depths14;
|
2001-10-09 09:45:21 +00:00
|
|
|
|
break;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
default:
|
2002-03-24 12:32:38 +00:00
|
|
|
|
(*pd)->depths = depths10;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
if (!(*pd)->dev.name || !(*pd)->dev.vendor || !(*pd)->dev.model || !(*pd)->dev.type)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: out of memory allocating device descriptor strings.\n",
|
2001-10-09 09:45:21 +00:00
|
|
|
|
me);
|
2002-03-24 12:32:38 +00:00
|
|
|
|
free (*pd);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return SANE_STATUS_NO_MEM;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2002-03-24 12:32:38 +00:00
|
|
|
|
(*pd)->x_range.min = x_range_fb.min;
|
|
|
|
|
(*pd)->x_range.quant = x_range_fb.quant;
|
|
|
|
|
(*pd)->x_range.max = x_range_fb.max;
|
|
|
|
|
(*pd)->y_range.min = y_range_fb.min;
|
|
|
|
|
(*pd)->y_range.quant = y_range_fb.quant;
|
|
|
|
|
(*pd)->y_range.max = y_range_fb.max;
|
|
|
|
|
(*pd)->firmware_filename = NULL;
|
|
|
|
|
|
|
|
|
|
(*pd)->pnext = first_device;
|
|
|
|
|
first_device = (*pd);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
n_devices++;
|
2002-03-24 12:32:38 +00:00
|
|
|
|
return status;
|
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
static SANE_Status add_scsi_device (SANE_String_Const full_name)
|
|
|
|
|
{
|
|
|
|
|
int fd;
|
|
|
|
|
static const char me[] = "add_scsi_device";
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
|
|
|
SnapScan_Device *pd;
|
|
|
|
|
SnapScan_Model model_num = UNKNOWN;
|
|
|
|
|
SnapScan_Bus bus_type = SCSI;
|
|
|
|
|
char vendor[8];
|
|
|
|
|
char model[17];
|
|
|
|
|
SANE_Char *name = NULL;
|
|
|
|
|
|
2002-09-26 20:09:24 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s(%s)\n", me, full_name);
|
2002-03-24 12:32:38 +00:00
|
|
|
|
|
|
|
|
|
sanei_config_get_string(full_name, &name);
|
|
|
|
|
/* Avoid adding the same device more then once */
|
|
|
|
|
if (device_already_in_list (first_device, name)) {
|
|
|
|
|
free(name);
|
|
|
|
|
name = 0;
|
|
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vendor[0] = model[0] = '\0';
|
|
|
|
|
|
|
|
|
|
DBG (DL_VERBOSE, "%s: Detected (kind of) a SCSI device\n", me);
|
|
|
|
|
|
|
|
|
|
status = sanei_scsi_open (name, &fd, sense_handler, NULL);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: error opening device %s: %s\n",
|
|
|
|
|
me,
|
|
|
|
|
name,
|
|
|
|
|
sane_strstatus (status));
|
|
|
|
|
} else {
|
|
|
|
|
status = snapscani_check_device(fd, bus_type, vendor, model, &model_num);
|
|
|
|
|
sanei_scsi_close(fd);
|
|
|
|
|
}
|
|
|
|
|
if (status == SANE_STATUS_GOOD) {
|
|
|
|
|
status = snapscani_init_device_structure(
|
|
|
|
|
&pd,
|
|
|
|
|
bus_type,
|
|
|
|
|
name,
|
|
|
|
|
vendor,
|
|
|
|
|
model,
|
|
|
|
|
model_num
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
free(name);
|
|
|
|
|
name = 0;
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SANE_Status add_usb_device (SANE_String_Const full_name) {
|
|
|
|
|
static const char me[] = "add_usb_device";
|
|
|
|
|
int fd;
|
|
|
|
|
SnapScan_Device *pd;
|
|
|
|
|
SnapScan_Model model_num = UNKNOWN;
|
|
|
|
|
SANE_Word vendor_id, product_id;
|
|
|
|
|
int supported_usb_vendor = 0;
|
|
|
|
|
char vendor[8];
|
|
|
|
|
char model[17];
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
|
|
|
SnapScan_Bus bus_type = USB;
|
|
|
|
|
int i;
|
|
|
|
|
SANE_Char *name = NULL;
|
|
|
|
|
|
|
|
|
|
DBG (DL_CALL_TRACE, "%s(%s)\n", me, full_name);
|
|
|
|
|
sanei_config_get_string(full_name, &name);
|
|
|
|
|
/* Avoid adding the same device more then once */
|
|
|
|
|
if (device_already_in_list (first_device, name)) {
|
|
|
|
|
free(name);
|
|
|
|
|
name = 0;
|
|
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vendor[0] = model[0] = '\0';
|
|
|
|
|
|
|
|
|
|
DBG (DL_VERBOSE, "%s: Detected (kind of) an USB device\n", me);
|
|
|
|
|
bus_type = USB;
|
|
|
|
|
status = snapscani_usb_open (name, &fd, sense_handler, NULL);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: error opening device %s: %s\n",
|
|
|
|
|
me,
|
|
|
|
|
name,
|
|
|
|
|
sane_strstatus (status));
|
|
|
|
|
} else {
|
|
|
|
|
if (sanei_usb_get_vendor_product(fd, &vendor_id, &product_id) ==
|
|
|
|
|
SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
/* check for known USB vendors to avoid hanging scanners by
|
|
|
|
|
inquiry-command.
|
|
|
|
|
*/
|
|
|
|
|
DBG(DL_INFO, "%s: Checking if 0x%04x is a supported USB vendor ID\n",
|
|
|
|
|
me, vendor_id);
|
|
|
|
|
for (i = 0; i < known_usb_vendor_ids; i++) {
|
|
|
|
|
if (vendor_id == usb_vendor_ids[i]) {
|
|
|
|
|
supported_usb_vendor = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!supported_usb_vendor) {
|
|
|
|
|
DBG(DL_MINOR_ERROR,
|
|
|
|
|
"%s: USB vendor ID 0x%04x is currently NOT supported by the snapscan backend.\n",
|
|
|
|
|
me, vendor_id);
|
|
|
|
|
status=SANE_STATUS_INVAL;
|
|
|
|
|
snapscani_usb_close(fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (status == SANE_STATUS_GOOD) {
|
|
|
|
|
status = snapscani_check_device(fd, bus_type, vendor, model, &model_num);
|
|
|
|
|
snapscani_usb_close(fd);
|
|
|
|
|
}
|
|
|
|
|
if (status == SANE_STATUS_GOOD) {
|
|
|
|
|
status = snapscani_init_device_structure(
|
|
|
|
|
&pd,
|
|
|
|
|
bus_type,
|
|
|
|
|
name,
|
|
|
|
|
vendor,
|
|
|
|
|
model,
|
|
|
|
|
model_num
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
free(name);
|
|
|
|
|
name = 0;
|
|
|
|
|
return status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-05 13:57:25 +00:00
|
|
|
|
/* find_device: find a device in the available list by name
|
2002-03-24 12:32:38 +00:00
|
|
|
|
|
2000-03-05 13:57:25 +00:00
|
|
|
|
ARG: the device name
|
2002-03-24 12:32:38 +00:00
|
|
|
|
|
2000-03-05 13:57:25 +00:00
|
|
|
|
RET: a pointer to the corresponding device record, or NULL if there
|
|
|
|
|
is no such device */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static SnapScan_Device *find_device (SANE_String_Const name)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static char me[] = "find_device";
|
|
|
|
|
SnapScan_Device *psd;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s\n", me);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
for (psd = first_device; psd; psd = psd->pnext)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (strcmp (psd->dev.name, name) == 0)
|
|
|
|
|
return psd;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return NULL;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-05 13:57:25 +00:00
|
|
|
|
/*----- functions in the scanner interface -----*/
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_init (SANE_Int *version_code,
|
|
|
|
|
SANE_Auth_Callback authorize)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static const char me[] = "sane_snapscan_init";
|
|
|
|
|
char dev_name[PATH_MAX];
|
|
|
|
|
size_t len;
|
|
|
|
|
FILE *fp;
|
|
|
|
|
SANE_Status status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG_INIT ();
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s\n", me);
|
2001-10-25 10:56:41 +00:00
|
|
|
|
DBG (DL_VERBOSE, "%s: Snapscan backend version %d.%d.%d\n",
|
|
|
|
|
me,
|
|
|
|
|
EXPECTED_MAJOR, MINOR_VERSION, BUILD);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* version check */
|
|
|
|
|
if (SANE_CURRENT_MAJOR != EXPECTED_MAJOR)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: this version of the SnapScan backend is intended for use\n"
|
|
|
|
|
"with SANE major version %ld, but the major version of this SANE\n"
|
|
|
|
|
"release is %ld. Sorry, but you need a different version of\n"
|
|
|
|
|
"this backend.\n\n",
|
|
|
|
|
me,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
(long) /*SANE_CURRENT_MAJOR */ V_MAJOR,
|
|
|
|
|
(long) EXPECTED_MAJOR);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return SANE_STATUS_INVAL;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (version_code != NULL)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*version_code =
|
|
|
|
|
SANE_VERSION_CODE (SANE_CURRENT_MAJOR, MINOR_VERSION, BUILD);
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
auth = authorize;
|
2002-03-24 12:32:38 +00:00
|
|
|
|
/* Initialize data structures */
|
|
|
|
|
default_firmware_filename = NULL;
|
|
|
|
|
first_device = NULL;
|
|
|
|
|
n_devices = 0;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2002-07-12 23:29:11 +00:00
|
|
|
|
sanei_usb_init();
|
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
/* build a device structure */
|
2000-08-12 15:11:46 +00:00
|
|
|
|
fp = sanei_config_open (SNAPSCAN_CONFIG_FILE);
|
|
|
|
|
if (!fp)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* default to DEFAULT_DEVICE instead of insisting on config file */
|
|
|
|
|
DBG (DL_INFO,
|
|
|
|
|
"%s: configuration file not found, defaulting to %s.\n",
|
|
|
|
|
me,
|
|
|
|
|
DEFAULT_DEVICE);
|
2002-03-24 12:32:38 +00:00
|
|
|
|
status = add_scsi_device (DEFAULT_DEVICE);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MINOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: failed to add device \"%s\"\n",
|
2000-08-12 15:11:46 +00:00
|
|
|
|
me,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
dev_name);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
else
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
while (sanei_config_read (dev_name, sizeof (dev_name), fp))
|
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
len = strlen (dev_name);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (!len)
|
2001-10-09 09:45:21 +00:00
|
|
|
|
continue; /* ignore empty lines */
|
2002-03-24 12:32:38 +00:00
|
|
|
|
if (dev_name[0] == '#') /* ignore line comments */
|
|
|
|
|
continue;
|
|
|
|
|
if (strncasecmp(dev_name, FIRMWARE_KW, strlen(FIRMWARE_KW)) == 0) {
|
|
|
|
|
if (!default_firmware_filename) {
|
|
|
|
|
sanei_config_get_string(dev_name + strlen(FIRMWARE_KW), &default_firmware_filename);
|
|
|
|
|
if (default_firmware_filename == NULL) {
|
|
|
|
|
DBG (0, "%s: Illegal firmware entry %s.\n", me, dev_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-23 22:37:54 +00:00
|
|
|
|
else if (strncasecmp(dev_name, OPTIONS_KW, strlen(OPTIONS_KW)) == 0)
|
2002-03-24 12:32:38 +00:00
|
|
|
|
continue; /* ignore options lines */
|
|
|
|
|
|
2002-04-23 22:37:54 +00:00
|
|
|
|
else if (strncmp(dev_name, "usb", 3) == 0) {
|
2002-03-24 12:32:38 +00:00
|
|
|
|
sanei_usb_attach_matching_devices (dev_name, add_usb_device);
|
2002-04-27 15:35:19 +00:00
|
|
|
|
}
|
2002-04-23 22:37:54 +00:00
|
|
|
|
else if (strncmp(dev_name, "scsi", 4) == 0) {
|
2002-03-24 12:32:38 +00:00
|
|
|
|
sanei_config_attach_matching_devices (dev_name, add_scsi_device);
|
2002-04-27 15:35:19 +00:00
|
|
|
|
}
|
2002-04-23 22:37:54 +00:00
|
|
|
|
else if (strstr (dev_name, "usb")) {
|
2002-03-24 12:32:38 +00:00
|
|
|
|
add_usb_device(dev_name);
|
2002-04-27 15:35:19 +00:00
|
|
|
|
}
|
2002-04-23 22:37:54 +00:00
|
|
|
|
else {
|
2002-03-24 12:32:38 +00:00
|
|
|
|
add_scsi_device(dev_name);
|
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
|
|
|
|
fclose (fp);
|
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* compute the dither matrices */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
mkDn (D4, D2, 4);
|
|
|
|
|
mkDn (D8, D4, 8);
|
|
|
|
|
mkDn (D16, D8, 16);
|
|
|
|
|
/* scale the D8 matrix from 0..63 to 0..255 */
|
|
|
|
|
{
|
|
|
|
|
u_char i;
|
|
|
|
|
for (i = 0; i < 64; i++)
|
2001-12-17 22:51:52 +00:00
|
|
|
|
D8[i] = (u_char) (4 * D8[i] + 2);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return SANE_STATUS_GOOD;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
static void free_device_list(SnapScan_Device *psd) {
|
|
|
|
|
if (psd->pnext != NULL) {
|
|
|
|
|
free_device_list(psd->pnext);
|
|
|
|
|
}
|
|
|
|
|
free(psd);
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
void sane_exit (void)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "sane_snapscan_exit\n");
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2002-03-24 16:42:04 +00:00
|
|
|
|
if (get_devices_list)
|
2000-08-12 15:11:46 +00:00
|
|
|
|
free (get_devices_list);
|
|
|
|
|
get_devices_list = NULL;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* just for safety, reset things to known values */
|
|
|
|
|
auth = NULL;
|
2002-03-24 16:42:04 +00:00
|
|
|
|
|
|
|
|
|
if (first_device) {
|
|
|
|
|
free_device_list(first_device);
|
|
|
|
|
first_device = NULL;
|
|
|
|
|
}
|
2002-03-24 12:32:38 +00:00
|
|
|
|
n_devices = 0;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-24 12:32:38 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_get_devices (const SANE_Device ***device_list,
|
|
|
|
|
SANE_Bool local_only)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static const char *me = "sane_snapscan_get_devices";
|
|
|
|
|
DBG (DL_CALL_TRACE,
|
|
|
|
|
"%s (%p, %ld)\n",
|
|
|
|
|
me,
|
2001-10-10 07:30:06 +00:00
|
|
|
|
(const void *) device_list,
|
2000-08-12 15:11:46 +00:00
|
|
|
|
(long) local_only);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* Waste the last list returned from this function */
|
|
|
|
|
if (NULL != get_devices_list)
|
|
|
|
|
free (get_devices_list);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*device_list =
|
|
|
|
|
(const SANE_Device **) malloc ((n_devices + 1) * sizeof (SANE_Device *));
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (*device_list)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
int i;
|
|
|
|
|
SnapScan_Device *pdev;
|
|
|
|
|
for (i = 0, pdev = first_device; pdev; i++, pdev = pdev->pnext)
|
|
|
|
|
(*device_list)[i] = &(pdev->dev);
|
|
|
|
|
(*device_list)[i] = 0x0000 /*NULL */;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
else
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR, "%s: out of memory\n", me);
|
|
|
|
|
return SANE_STATUS_NO_MEM;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
get_devices_list = *device_list;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return SANE_STATUS_GOOD;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static const char *me = "sane_snapscan_open";
|
|
|
|
|
SnapScan_Device *psd;
|
|
|
|
|
SANE_Status status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s (%s, %p)\n", me, name, (void *) h);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* possible authorization required */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* device exists? */
|
|
|
|
|
psd = find_device (name);
|
|
|
|
|
if (!psd)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MINOR_ERROR,
|
|
|
|
|
"%s: device \"%s\" not in current device list.\n",
|
|
|
|
|
me,
|
|
|
|
|
name);
|
|
|
|
|
return SANE_STATUS_INVAL;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* create and initialize the scanner structure */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
*h = (SnapScan_Scanner *) calloc (sizeof (SnapScan_Scanner), 1);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (!*h)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: out of memory creating scanner structure.\n",
|
|
|
|
|
me);
|
|
|
|
|
return SANE_STATUS_NO_MEM;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SnapScan_Scanner *pss = *(SnapScan_Scanner **) h;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
pss->devname = strdup (name);
|
2001-06-01 16:24:46 +00:00
|
|
|
|
if (!pss->devname)
|
2000-08-12 15:11:46 +00:00
|
|
|
|
{
|
|
|
|
|
free (*h);
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: out of memory copying device name.\n",
|
|
|
|
|
me);
|
|
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
|
}
|
|
|
|
|
pss->pdev = psd;
|
|
|
|
|
pss->opens = 0;
|
|
|
|
|
pss->sense_str = NULL;
|
|
|
|
|
pss->as_str = NULL;
|
2001-10-09 09:45:21 +00:00
|
|
|
|
pss->phys_buf_sz = DEFAULT_SCANNER_BUF_SZ;
|
|
|
|
|
if (psd->bus == SCSI) {
|
|
|
|
|
pss->phys_buf_sz = sanei_scsi_max_request_size;
|
|
|
|
|
}
|
|
|
|
|
DBG (DL_DATA_TRACE,
|
|
|
|
|
"%s: Allocating %d bytes as scanner buffer.\n",
|
|
|
|
|
me, pss->phys_buf_sz);
|
|
|
|
|
pss->buf = (u_char *) malloc(pss->phys_buf_sz);
|
|
|
|
|
if (!pss->buf) {
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: out of memory creating scanner buffer.\n",
|
|
|
|
|
me);
|
|
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
|
|
|
|
|
DBG (DL_VERBOSE,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: allocated scanner structure at %p\n",
|
2000-08-12 15:11:46 +00:00
|
|
|
|
me,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
(void *) pss);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = open_scanner (pss);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: open_scanner failed, status: %s\n",
|
2000-08-12 15:11:46 +00:00
|
|
|
|
me,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
sane_strstatus (status));
|
2000-08-12 15:11:46 +00:00
|
|
|
|
free (pss);
|
|
|
|
|
return SANE_STATUS_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBG (DL_MINOR_INFO, "%s: waiting for scanner to warm up.\n", me);
|
|
|
|
|
status = wait_scanner_ready (pss);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
2002-05-02 17:19:20 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: error waiting for scanner to warm up: %s\n",
|
|
|
|
|
me,
|
|
|
|
|
sane_strstatus(status));
|
|
|
|
|
free (pss);
|
|
|
|
|
return status;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
|
|
|
|
DBG (DL_MINOR_INFO, "%s: performing scanner self test.\n", me);
|
|
|
|
|
status = send_diagnostic (pss);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MINOR_INFO, "%s: send_diagnostic reports %s\n",
|
|
|
|
|
me, sane_strstatus (status));
|
|
|
|
|
free (pss);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
DBG (DL_MINOR_INFO, "%s: self test passed.\n", me);
|
|
|
|
|
|
|
|
|
|
/* option initialization depends on getting the hardware configuration
|
|
|
|
|
byte */
|
|
|
|
|
status = inquiry (pss);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: error in inquiry command: %s\n",
|
|
|
|
|
me,
|
|
|
|
|
sane_strstatus (status));
|
2000-08-12 15:11:46 +00:00
|
|
|
|
free (pss);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
close_scanner (pss);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
status = init_gamma (pss);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: error in init_gamma: %s\n",
|
2001-05-26 12:47:34 +00:00
|
|
|
|
me,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
sane_strstatus (status));
|
2001-05-26 12:47:34 +00:00
|
|
|
|
free (pss);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
init_options (pss);
|
|
|
|
|
pss->state = ST_IDLE;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return SANE_STATUS_GOOD;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
void sane_close (SANE_Handle h)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
|
|
|
|
|
DBG (DL_CALL_TRACE, "sane_snapscan_close (%p)\n", (void *) h);
|
|
|
|
|
switch (pss->state)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
|
|
|
|
case ST_SCAN_INIT:
|
|
|
|
|
case ST_SCANNING:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
release_unit (pss);
|
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
default:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
close_scanner (pss);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
free (pss->gamma_tables);
|
2001-10-09 09:45:21 +00:00
|
|
|
|
free (pss->buf);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
free (pss);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_get_parameters (SANE_Handle h,
|
|
|
|
|
SANE_Parameters *p)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static const char *me = "sane_snapscan_get_parameters";
|
|
|
|
|
SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
|
|
|
SnapScan_Mode mode = actual_mode(pss);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s (%p, %p)\n", me, (void *) h, (void *) p);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
p->last_frame = SANE_TRUE; /* we always do only one frame */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
if ((pss->state == ST_SCAN_INIT) || (pss->state == ST_SCANNING))
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
/* we are in the middle of a scan, so we can use the data
|
|
|
|
|
that the scanner has reported */
|
|
|
|
|
if (pss->psrc != NULL)
|
|
|
|
|
{
|
|
|
|
|
DBG(DL_DATA_TRACE, "%s: Using source chain data\n", me);
|
|
|
|
|
/* use what the source chain says */
|
|
|
|
|
p->pixels_per_line = pss->psrc->pixelsPerLine(pss->psrc);
|
|
|
|
|
p->bytes_per_line = pss->psrc->bytesPerLine(pss->psrc);
|
|
|
|
|
/* p->lines = pss->psrc->remaining(pss->psrc)/p->bytes_per_line; */
|
|
|
|
|
p->lines = pss->lines;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DBG(DL_DATA_TRACE, "%s: Using current data\n", me);
|
|
|
|
|
/* estimate based on current data */
|
|
|
|
|
p->pixels_per_line = pss->pixels_per_line;
|
|
|
|
|
p->bytes_per_line = pss->bytes_per_line;
|
|
|
|
|
p->lines = pss->lines;
|
|
|
|
|
if (mode == MD_BILEVELCOLOUR)
|
|
|
|
|
p->bytes_per_line = p->pixels_per_line*3;
|
|
|
|
|
}
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
else
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
/* no scan in progress. The scanner data may not be up to date.
|
|
|
|
|
we have to calculate an estimate. */
|
|
|
|
|
double width, height;
|
|
|
|
|
int dpi;
|
|
|
|
|
double dots_per_mm;
|
|
|
|
|
|
|
|
|
|
DBG(DL_DATA_TRACE, "%s: Using estimated data\n", me);
|
|
|
|
|
width = SANE_UNFIX (pss->brx - pss->tlx);
|
|
|
|
|
height = SANE_UNFIX (pss->bry - pss->tly);
|
|
|
|
|
dpi = pss->res;
|
|
|
|
|
dots_per_mm = dpi / MM_PER_IN;
|
|
|
|
|
p->pixels_per_line = width * dots_per_mm;
|
|
|
|
|
p->lines = height * dots_per_mm;
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case MD_COLOUR:
|
|
|
|
|
case MD_BILEVELCOLOUR:
|
|
|
|
|
p->bytes_per_line = 3 * p->pixels_per_line;
|
|
|
|
|
break;
|
|
|
|
|
case MD_LINEART:
|
|
|
|
|
p->bytes_per_line = (p->pixels_per_line + 7) / 8;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* greyscale */
|
|
|
|
|
p->bytes_per_line = p->pixels_per_line;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
p->format = (is_colour_mode(mode)) ? SANE_FRAME_RGB : SANE_FRAME_GRAY;
|
|
|
|
|
p->depth = (mode == MD_LINEART) ? 1 : 8;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_DATA_TRACE, "%s: depth = %ld\n", me, (long) p->depth);
|
|
|
|
|
DBG (DL_DATA_TRACE, "%s: lines = %ld\n", me, (long) p->lines);
|
|
|
|
|
DBG (DL_DATA_TRACE,
|
|
|
|
|
"%s: pixels per line = %ld\n",
|
|
|
|
|
me,
|
|
|
|
|
(long) p->pixels_per_line);
|
|
|
|
|
DBG (DL_DATA_TRACE,
|
|
|
|
|
"%s: bytes per line = %ld\n",
|
2001-10-09 09:45:21 +00:00
|
|
|
|
me,
|
2000-08-12 15:11:46 +00:00
|
|
|
|
(long) p->bytes_per_line);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* scan data reader routine for child process */
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static void handler (int signo)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
signal (signo, handler);
|
|
|
|
|
DBG (DL_MINOR_INFO, "child process: received signal %ld\n", (long) signo);
|
|
|
|
|
close (STDOUT_FILENO);
|
|
|
|
|
_exit(0);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-05 13:57:25 +00:00
|
|
|
|
#define READER_WRITE_SIZE 4096
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static void reader (SnapScan_Scanner *pss)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static char me[] = "Child reader process";
|
|
|
|
|
SANE_Status status;
|
|
|
|
|
SANE_Byte *wbuf = NULL;
|
|
|
|
|
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s\n", me);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
wbuf = (SANE_Byte*) malloc(READER_WRITE_SIZE);
|
|
|
|
|
if (wbuf == NULL)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR, "%s: failed to allocate write buffer.\n", me);
|
|
|
|
|
_exit(1);
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
while (pss->psrc->remaining(pss->psrc) > 0)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Int ndata = READER_WRITE_SIZE;
|
|
|
|
|
status = pss->psrc->get(pss->psrc, wbuf, &ndata);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: %s on read.\n",
|
|
|
|
|
me,
|
2000-08-12 15:11:46 +00:00
|
|
|
|
sane_strstatus (status));
|
|
|
|
|
close (STDOUT_FILENO);
|
|
|
|
|
_exit (1);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
SANE_Byte *buf = wbuf;
|
2002-04-27 15:35:19 +00:00
|
|
|
|
DBG (DL_DATA_TRACE, "READ %d BYTES\n", ndata);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
while (ndata > 0)
|
|
|
|
|
{
|
|
|
|
|
int written = write (STDOUT_FILENO, buf, ndata);
|
2002-04-27 15:35:19 +00:00
|
|
|
|
DBG (DL_DATA_TRACE, "WROTE %d BYTES\n", written);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (written == -1)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"%s: error writing scan data on parent pipe.\n",
|
2001-10-09 09:45:21 +00:00
|
|
|
|
me);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
perror ("pipe error: ");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ndata -= written;
|
|
|
|
|
buf += written;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static SANE_Status start_reader (SnapScan_Scanner *pss)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
|
|
|
static char me[] = "start_reader";
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s\n", me);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* We can implement nonblocking mode by forking a separate reader
|
|
|
|
|
process. It doesn't seem that we can poll the scsi descriptor. */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
pss->nonblocking = SANE_FALSE;
|
|
|
|
|
pss->rpipe[0] = pss->rpipe[1] = -1;
|
|
|
|
|
pss->child = -1;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
if (pss->pdev->model == VUEGO610S
|
|
|
|
|
||
|
|
|
|
|
pss->pdev->model == ACER300F
|
2000-08-12 15:11:46 +00:00
|
|
|
|
||
|
2001-10-09 09:45:21 +00:00
|
|
|
|
pss->pdev->model == SNAPSCAN310
|
|
|
|
|
||
|
|
|
|
|
pss->pdev->model == VUEGO310S
|
|
|
|
|
||
|
2001-10-12 21:19:16 +00:00
|
|
|
|
pss->pdev->model == SNAPSCANE20
|
|
|
|
|
||
|
2001-10-09 09:45:21 +00:00
|
|
|
|
pss->pdev->model == SNAPSCANE50
|
|
|
|
|
||
|
|
|
|
|
pss->pdev->model == SNAPSCAN1236)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
status = SANE_STATUS_UNSUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
else if (pipe (pss->rpipe) != -1)
|
|
|
|
|
{
|
|
|
|
|
pss->orig_rpipe_flags = fcntl (pss->rpipe[0], F_GETFL, 0);
|
|
|
|
|
switch (pss->child = fork ())
|
|
|
|
|
{
|
|
|
|
|
case -1:
|
|
|
|
|
/* we'll have to read in blocking mode */
|
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: can't fork; must read in blocking mode.\n",
|
2000-08-12 15:11:46 +00:00
|
|
|
|
me);
|
|
|
|
|
close (pss->rpipe[0]);
|
|
|
|
|
close (pss->rpipe[1]);
|
|
|
|
|
status = SANE_STATUS_UNSUPPORTED;
|
|
|
|
|
break;
|
|
|
|
|
case 0:
|
|
|
|
|
/* child; close read side, make stdout the write side of the pipe */
|
|
|
|
|
signal (SIGTERM, handler);
|
|
|
|
|
dup2 (pss->rpipe[1], STDOUT_FILENO);
|
|
|
|
|
close (pss->rpipe[0]);
|
|
|
|
|
status = create_base_source (pss, SCSI_SRC, &(pss->psrc));
|
|
|
|
|
if (status == SANE_STATUS_GOOD)
|
2001-10-09 09:45:21 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
reader (pss);
|
|
|
|
|
}
|
2001-10-09 09:45:21 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
|
|
|
|
"Reader process: failed to create SCSISource.\n");
|
|
|
|
|
}
|
2001-10-09 09:45:21 +00:00
|
|
|
|
/* regular exit may cause a SIGPIPE */
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MINOR_INFO, "Reader process terminating.\n");
|
|
|
|
|
_exit (0);
|
2001-10-09 09:45:21 +00:00
|
|
|
|
break; /* not reached */
|
2000-08-12 15:11:46 +00:00
|
|
|
|
default:
|
|
|
|
|
/* parent; close write side */
|
|
|
|
|
close (pss->rpipe[1]);
|
|
|
|
|
pss->nonblocking = SANE_TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return status;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static SANE_Status download_gamma_tables (SnapScan_Scanner *pss)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static char me[] = "download_gamma_tables";
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
|
|
|
float gamma_gs = SANE_UNFIX (pss->gamma_gs);
|
|
|
|
|
float gamma_r = SANE_UNFIX (pss->gamma_r);
|
|
|
|
|
float gamma_g = SANE_UNFIX (pss->gamma_g);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
float gamma_b = SANE_UNFIX (pss->gamma_b);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SnapScan_Mode mode = actual_mode (pss);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
int dtcq_gamma_gray;
|
|
|
|
|
int dtcq_gamma_red;
|
|
|
|
|
int dtcq_gamma_green;
|
|
|
|
|
int dtcq_gamma_blue;
|
|
|
|
|
int bpp = (pss->hconfig & HCFG_ADC) ? 10 : 8;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
|
|
|
|
|
switch (mode)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
|
|
|
|
case MD_COLOUR:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
case MD_BILEVELCOLOUR:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (!pss->halftone)
|
2001-10-09 09:45:21 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
gamma_r =
|
2001-10-09 09:45:21 +00:00
|
|
|
|
gamma_g =
|
|
|
|
|
gamma_b = 1.0;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
2001-10-09 09:45:21 +00:00
|
|
|
|
break;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
case MD_LINEART:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (!pss->halftone)
|
|
|
|
|
gamma_gs = 1.0;
|
|
|
|
|
break;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
default:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* no further action for greyscale */
|
|
|
|
|
break;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
if (bpp == 10)
|
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
dtcq_gamma_gray = DTCQ_GAMMA_GRAY10;
|
|
|
|
|
dtcq_gamma_red = DTCQ_GAMMA_RED10;
|
|
|
|
|
dtcq_gamma_green = DTCQ_GAMMA_GREEN10;
|
|
|
|
|
dtcq_gamma_blue = DTCQ_GAMMA_BLUE10;
|
2001-05-26 12:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
dtcq_gamma_gray = DTCQ_GAMMA_GRAY8;
|
|
|
|
|
dtcq_gamma_red = DTCQ_GAMMA_RED8;
|
|
|
|
|
dtcq_gamma_green = DTCQ_GAMMA_GREEN8;
|
|
|
|
|
dtcq_gamma_blue = DTCQ_GAMMA_BLUE8;
|
2001-05-26 12:47:34 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (is_colour_mode(mode))
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
if (pss->val[OPT_CUSTOM_GAMMA].b)
|
|
|
|
|
{
|
|
|
|
|
if (pss->val[OPT_GAMMA_BIND].b)
|
|
|
|
|
{
|
|
|
|
|
/* Use greyscale gamma for all rgb channels */
|
|
|
|
|
gamma_from_sane (pss->gamma_length, pss->gamma_table_gs,
|
|
|
|
|
pss->buf + SEND_LENGTH);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_red);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
|
|
|
|
|
gamma_from_sane (pss->gamma_length, pss->gamma_table_gs,
|
|
|
|
|
pss->buf + SEND_LENGTH);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_green);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
|
|
|
|
|
gamma_from_sane (pss->gamma_length, pss->gamma_table_gs,
|
|
|
|
|
pss->buf + SEND_LENGTH);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_blue);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
gamma_from_sane (pss->gamma_length, pss->gamma_table_r,
|
|
|
|
|
pss->buf + SEND_LENGTH);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_red);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
|
|
|
|
|
gamma_from_sane (pss->gamma_length, pss->gamma_table_g,
|
|
|
|
|
pss->buf + SEND_LENGTH);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_green);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
2001-12-17 22:51:52 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
gamma_from_sane (pss->gamma_length, pss->gamma_table_b,
|
|
|
|
|
pss->buf + SEND_LENGTH);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_blue);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (pss->val[OPT_GAMMA_BIND].b)
|
|
|
|
|
{
|
|
|
|
|
/* Use greyscale gamma for all rgb channels */
|
|
|
|
|
gamma_n (gamma_gs, pss->bright, pss->contrast,
|
|
|
|
|
pss->buf + SEND_LENGTH, bpp);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_red);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
|
|
|
|
|
gamma_n (gamma_gs, pss->bright, pss->contrast,
|
|
|
|
|
pss->buf + SEND_LENGTH, bpp);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_green);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
|
|
|
|
|
gamma_n (gamma_gs, pss->bright, pss->contrast,
|
|
|
|
|
pss->buf + SEND_LENGTH, bpp);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_blue);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
gamma_n (gamma_r, pss->bright, pss->contrast,
|
|
|
|
|
pss->buf + SEND_LENGTH, bpp);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_red);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
|
|
|
|
|
gamma_n (gamma_g, pss->bright, pss->contrast,
|
|
|
|
|
pss->buf + SEND_LENGTH, bpp);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_green);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
2001-12-17 22:51:52 +00:00
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
gamma_n (gamma_b, pss->bright, pss->contrast,
|
|
|
|
|
pss->buf + SEND_LENGTH, bpp);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_blue);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
else
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
if(pss->val[OPT_CUSTOM_GAMMA].b)
|
|
|
|
|
{
|
|
|
|
|
gamma_from_sane (pss->gamma_length, pss->gamma_table_gs,
|
|
|
|
|
pss->buf + SEND_LENGTH);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_gray);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
gamma_n (gamma_gs, pss->bright, pss->contrast,
|
|
|
|
|
pss->buf + SEND_LENGTH, bpp);
|
|
|
|
|
status = send (pss, DTC_GAMMA, dtcq_gamma_gray);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
|
|
|
|
}
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return status;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static SANE_Status download_halftone_matrices (SnapScan_Scanner *pss)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static char me[] = "download_halftone_matrices";
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
2001-12-17 22:51:52 +00:00
|
|
|
|
if ((pss->halftone) &&
|
|
|
|
|
((actual_mode(pss) == MD_LINEART) || (actual_mode(pss) == MD_BILEVELCOLOUR)))
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
u_char *matrix;
|
|
|
|
|
size_t matrix_sz;
|
|
|
|
|
u_char dtcq;
|
|
|
|
|
|
|
|
|
|
if (pss->dither_matrix == dm_dd8x8)
|
|
|
|
|
{
|
|
|
|
|
matrix = D8;
|
|
|
|
|
matrix_sz = sizeof (D8);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
matrix = D16;
|
|
|
|
|
matrix_sz = sizeof (D16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy (pss->buf + SEND_LENGTH, matrix, matrix_sz);
|
|
|
|
|
|
|
|
|
|
if (is_colour_mode(actual_mode(pss)))
|
|
|
|
|
{
|
|
|
|
|
if (matrix_sz == sizeof (D8))
|
|
|
|
|
dtcq = DTCQ_HALFTONE_COLOR8;
|
|
|
|
|
else
|
|
|
|
|
dtcq = DTCQ_HALFTONE_COLOR16;
|
|
|
|
|
|
|
|
|
|
/* need copies for green and blue bands */
|
|
|
|
|
memcpy (pss->buf + SEND_LENGTH + matrix_sz,
|
|
|
|
|
matrix,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
matrix_sz);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
memcpy (pss->buf + SEND_LENGTH + 2 * matrix_sz,
|
|
|
|
|
matrix,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
matrix_sz);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (matrix_sz == sizeof (D8))
|
|
|
|
|
dtcq = DTCQ_HALFTONE_BW8;
|
|
|
|
|
else
|
|
|
|
|
dtcq = DTCQ_HALFTONE_BW16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = send (pss, DTC_HALFTONE, dtcq);
|
|
|
|
|
CHECK_STATUS (status, me, "send");
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return status;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static SANE_Status measure_transfer_rate (SnapScan_Scanner *pss)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static char me[] = "measure_transfer_rate";
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
if (pss->hconfig & HCFG_RB)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* We have a ring buffer. We simulate one round of a read-store
|
|
|
|
|
cycle on the size of buffer we will be using. For this read only,
|
|
|
|
|
the buffer size must be rounded to a 128-byte boundary. */
|
|
|
|
|
|
|
|
|
|
DBG (DL_VERBOSE, "%s: have ring buffer\n", me);
|
|
|
|
|
pss->expected_read_bytes =
|
|
|
|
|
(pss->buf_sz%128) ? (pss->buf_sz/128 + 1)*128 : pss->buf_sz;
|
|
|
|
|
|
2001-10-09 09:45:21 +00:00
|
|
|
|
status = scsi_read (pss, READ_TRANSTIME);
|
|
|
|
|
CHECK_STATUS (status, me, "scsi_read");
|
2000-08-12 15:11:46 +00:00
|
|
|
|
pss->expected_read_bytes = 0;
|
|
|
|
|
status = scsi_read (pss, READ_TRANSTIME);
|
|
|
|
|
CHECK_STATUS (status, me, "scsi_read");
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
else
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* we don't have a ring buffer. The test requires transferring one
|
|
|
|
|
scan line of data (rounded up to next 128 byte boundary). */
|
|
|
|
|
|
|
|
|
|
DBG (DL_VERBOSE, "%s: we don't have a ring buffer.\n", me);
|
|
|
|
|
pss->expected_read_bytes = pss->bytes_per_line;
|
|
|
|
|
|
|
|
|
|
if (pss->expected_read_bytes%128)
|
|
|
|
|
{
|
|
|
|
|
pss->expected_read_bytes =
|
|
|
|
|
(pss->expected_read_bytes/128 + 1)*128;
|
|
|
|
|
}
|
|
|
|
|
status = scsi_read (pss, READ_TRANSTIME);
|
|
|
|
|
CHECK_STATUS (status, me, "scsi_read");
|
|
|
|
|
DBG (DL_VERBOSE, "%s: read %ld bytes.\n", me, (long) pss->read_bytes);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-05-26 12:47:34 +00:00
|
|
|
|
pss->expected_read_bytes = 0;
|
|
|
|
|
status = scsi_read (pss, READ_TRANSTIME);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR, "%s: test read failed.\n", me);
|
|
|
|
|
return status;
|
2001-05-26 12:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_VERBOSE, "%s: successfully calibrated transfer rate.\n", me);
|
|
|
|
|
return status;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_start (SANE_Handle h)
|
2000-03-05 13:57:25 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static const char *me = "sane_snapscan_start";
|
|
|
|
|
SANE_Status status;
|
|
|
|
|
SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s (%p)\n", me, (void *) h);
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* possible authorization required */
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
status = open_scanner (pss);
|
|
|
|
|
CHECK_STATUS (status, me, "open_scanner");
|
|
|
|
|
|
|
|
|
|
status = wait_scanner_ready (pss);
|
|
|
|
|
CHECK_STATUS (status, me, "wait_scanner_ready");
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* download the gamma and halftone tables */
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
status = download_gamma_tables(pss);
|
|
|
|
|
CHECK_STATUS (status, me, "download_gamma_tables");
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
status = download_halftone_matrices(pss);
|
|
|
|
|
CHECK_STATUS (status, me, "download_halftone_matrices");
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* set up the window and fetch the resulting scanner parameters */
|
|
|
|
|
status = set_window(pss);
|
|
|
|
|
CHECK_STATUS (status, me, "set_window");
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
status = inquiry(pss);
|
|
|
|
|
CHECK_STATUS (status, me, "inquiry");
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* we must measure the data transfer rate between the host and the
|
|
|
|
|
scanner, and the method varies depending on whether there is a
|
|
|
|
|
ring buffer or not. */
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
status = measure_transfer_rate(pss);
|
|
|
|
|
CHECK_STATUS (status, me, "measure_transfer_rate");
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* now perform an inquiry again to retrieve the scan speed */
|
|
|
|
|
status = inquiry(pss);
|
|
|
|
|
CHECK_STATUS (status, me, "inquiry");
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_DATA_TRACE,
|
|
|
|
|
"%s: after measuring speed:\n\t%lu bytes per scan line\n"
|
|
|
|
|
"\t%f milliseconds per scan line.\n\t==>%f bytes per millisecond\n",
|
|
|
|
|
me,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
(u_long) pss->bytes_per_line,
|
|
|
|
|
pss->ms_per_line,
|
2000-08-12 15:11:46 +00:00
|
|
|
|
pss->bytes_per_line/pss->ms_per_line);
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* start scanning; reserve the unit first, because a release_unit is
|
|
|
|
|
necessary to abort a scan in progress */
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
pss->state = ST_SCAN_INIT;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
reserve_unit(pss);
|
2001-05-26 12:47:34 +00:00
|
|
|
|
|
|
|
|
|
if(pss->val[OPT_QUALITY_CAL].b)
|
|
|
|
|
{
|
2001-10-09 09:45:21 +00:00
|
|
|
|
status = calibrate(pss);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MAJOR_ERROR, "%s: calibration failed.\n", me);
|
|
|
|
|
release_unit (pss);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
2001-05-26 12:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
status = scan(pss);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2002-05-02 17:19:20 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR, "%s: scan command failed: %s.\n", me, sane_strstatus(status));
|
2000-08-12 15:11:46 +00:00
|
|
|
|
release_unit (pss);
|
|
|
|
|
return status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2002-07-12 23:29:11 +00:00
|
|
|
|
/* Wait for scanner ready again (e.g. until paper is loaded from an ADF) */
|
2002-05-02 17:19:20 +00:00
|
|
|
|
status = wait_scanner_ready (pss);
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
{
|
2002-07-12 23:29:11 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR, "%s: scan command failed while waiting for scanner: %s.\n", me, sane_strstatus(status));
|
2002-05-02 17:19:20 +00:00
|
|
|
|
release_unit (pss);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MINOR_INFO, "%s: starting the reader process.\n", me);
|
|
|
|
|
status = start_reader(pss);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
BaseSourceType st = FD_SRC;
|
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
|
st = SCSI_SRC;
|
|
|
|
|
status = create_source_chain (pss, st, &(pss->psrc));
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_read (SANE_Handle h,
|
|
|
|
|
SANE_Byte *buf,
|
|
|
|
|
SANE_Int maxlen,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
SANE_Int *plen)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static const char *me = "sane_snapscan_read";
|
|
|
|
|
SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
|
|
|
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s (%p, %p, %ld, %p)\n",
|
|
|
|
|
me,
|
|
|
|
|
(void *) h,
|
|
|
|
|
(void *) buf,
|
|
|
|
|
(long) maxlen,
|
|
|
|
|
(void *) plen);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*plen = 0;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2002-05-02 17:19:20 +00:00
|
|
|
|
if (pss->state == ST_CANCEL_INIT) {
|
|
|
|
|
pss->state = ST_IDLE;
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return SANE_STATUS_CANCELLED;
|
2002-05-02 17:19:20 +00:00
|
|
|
|
}
|
2000-03-05 13:57:25 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (pss->psrc == NULL || pss->psrc->remaining(pss->psrc) == 0)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (pss->child > 0)
|
|
|
|
|
{
|
|
|
|
|
int status;
|
2001-10-09 09:45:21 +00:00
|
|
|
|
wait (&status); /* ensure no zombies */
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
|
|
|
|
release_unit (pss);
|
|
|
|
|
close_scanner (pss);
|
|
|
|
|
if (pss->psrc != NULL)
|
|
|
|
|
{
|
|
|
|
|
pss->psrc->done(pss->psrc);
|
|
|
|
|
free(pss->psrc);
|
|
|
|
|
pss->psrc = NULL;
|
|
|
|
|
}
|
|
|
|
|
pss->state = ST_IDLE;
|
|
|
|
|
return SANE_STATUS_EOF;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*plen = maxlen;
|
|
|
|
|
status = pss->psrc->get(pss->psrc, buf, plen);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
switch (pss->state)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
|
|
|
|
case ST_IDLE:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: weird error: scanner state should not be idle on call to "
|
|
|
|
|
"sane_read.\n",
|
|
|
|
|
me);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
case ST_SCAN_INIT:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* we've read some data */
|
|
|
|
|
pss->state = ST_SCANNING;
|
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
case ST_CANCEL_INIT:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* stop scanning */
|
|
|
|
|
status = SANE_STATUS_CANCELLED;
|
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
default:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return status;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
void sane_cancel (SANE_Handle h)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
char *me = "sane_snapscan_cancel";
|
|
|
|
|
SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s\n", me);
|
|
|
|
|
switch (pss->state)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
|
|
|
|
case ST_IDLE:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
case ST_SCAN_INIT:
|
|
|
|
|
case ST_SCANNING:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
/* signal a cancellation has occurred */
|
|
|
|
|
pss->state = ST_CANCEL_INIT;
|
|
|
|
|
/* signal the reader, if any */
|
|
|
|
|
if (pss->child > 0)
|
|
|
|
|
{
|
|
|
|
|
int result;
|
|
|
|
|
if ((result = kill (pss->child, SIGTERM)) < 0)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_VERBOSE,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: error: kill returns %ld\n",
|
|
|
|
|
me,
|
|
|
|
|
(long) result);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int status;
|
|
|
|
|
DBG (DL_VERBOSE, "%s: waiting on child reader.\n", me);
|
|
|
|
|
wait (&status);
|
|
|
|
|
DBG (DL_VERBOSE, "%s: child has terminated.\n", me);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
release_unit (pss);
|
|
|
|
|
close_scanner (pss);
|
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
case ST_CANCEL_INIT:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_INFO, "%s: cancellation already initiated.\n", me);
|
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
default:
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MAJOR_ERROR,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
"%s: weird error: invalid scanner state (%ld).\n",
|
2000-08-12 15:11:46 +00:00
|
|
|
|
me,
|
2001-10-09 09:45:21 +00:00
|
|
|
|
(long) pss->state);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
break;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static char me[] = "sane_snapscan_set_io_mode";
|
|
|
|
|
SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
|
|
|
|
|
char *op;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s\n", me);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (pss->state != ST_SCAN_INIT)
|
|
|
|
|
return SANE_STATUS_INVAL;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (m)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (pss->child == -1)
|
|
|
|
|
{
|
|
|
|
|
DBG (DL_MINOR_INFO,
|
|
|
|
|
"%s: no reader child; must use blocking mode.\n",
|
2001-10-09 09:45:21 +00:00
|
|
|
|
me);
|
2000-08-12 15:11:46 +00:00
|
|
|
|
return SANE_STATUS_UNSUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
op = "ON";
|
|
|
|
|
fcntl (pss->rpipe[0], F_SETFL, O_NONBLOCK | pss->orig_rpipe_flags);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
else
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
op = "OFF";
|
|
|
|
|
fcntl (pss->rpipe[0], F_SETFL, pss->orig_rpipe_flags);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MINOR_INFO, "%s: turning nonblocking mode %s.\n", me, op);
|
|
|
|
|
pss->nonblocking = m;
|
|
|
|
|
return SANE_STATUS_GOOD;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
static char me[] = "sane_snapscan_get_select_fd";
|
|
|
|
|
SnapScan_Scanner *pss = (SnapScan_Scanner *) h;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_CALL_TRACE, "%s\n", me);
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (pss->state != ST_SCAN_INIT)
|
|
|
|
|
return SANE_STATUS_INVAL;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
|
2000-08-12 15:11:46 +00:00
|
|
|
|
if (pss->child == -1)
|
1999-08-09 18:06:01 +00:00
|
|
|
|
{
|
2000-08-12 15:11:46 +00:00
|
|
|
|
DBG (DL_MINOR_INFO,
|
|
|
|
|
"%s: no reader child; cannot provide select file descriptor.\n",
|
|
|
|
|
me);
|
|
|
|
|
return SANE_STATUS_UNSUPPORTED;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*fd = pss->rpipe[0];
|
|
|
|
|
return SANE_STATUS_GOOD;
|
1999-08-09 18:06:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-05 13:57:25 +00:00
|
|
|
|
/*
|
|
|
|
|
* $Log$
|
2002-10-14 21:49:45 +00:00
|
|
|
|
* Revision 1.26 2002/10/14 21:49:42 oliverschwartz
|
|
|
|
|
* SnapScan backend 1.4.17
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.52 2002/10/12 10:40:48 oliverschwartz
|
|
|
|
|
* Added support for Snapscan e10
|
2002-09-26 20:09:24 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.51 2002/09/26 19:27:44 oliverschwartz
|
|
|
|
|
* Version 1.4.16
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.50 2002/09/24 16:07:44 oliverschwartz
|
|
|
|
|
* Added support for Benq 5000
|
2002-07-12 23:29:11 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.49 2002/07/12 22:53:54 oliverschwartz
|
|
|
|
|
* Version 1.4.15
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.48 2002/07/12 22:53:16 oliverschwartz
|
|
|
|
|
* call sanei_usb_init() before sanei_usb_attach_matching_devices()
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.47 2002/06/06 21:16:23 oliverschwartz
|
|
|
|
|
* Set backend version to 1.4.14
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.46 2002/06/06 20:40:01 oliverschwartz
|
|
|
|
|
* Changed default scan area for transparancy unit of SnapScan e50
|
2002-05-02 17:19:20 +00:00
|
|
|
|
*
|
2002-07-12 23:29:11 +00:00
|
|
|
|
* Revision 1.45 2002/05/02 18:29:34 oliverschwartz
|
|
|
|
|
* - Added ADF support
|
|
|
|
|
* - Fixed status handling after cancel
|
2002-04-27 15:35:19 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.44 2002/04/27 14:42:30 oliverschwartz
|
|
|
|
|
* Cleanup of debug logging
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.43 2002/04/23 22:40:33 oliverschwartz
|
|
|
|
|
* Improve config file reading
|
2002-04-23 22:37:54 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.42 2002/04/10 21:00:09 oliverschwartz
|
|
|
|
|
* Check for NULL pointer before deleting device list
|
2002-03-24 12:32:38 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.41 2002/03/24 12:12:36 oliverschwartz
|
|
|
|
|
* - Moved option functions to snapscan-options.c
|
|
|
|
|
* - Autodetect USB scanners
|
|
|
|
|
* - Cleanup
|
2002-02-09 15:03:07 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.40 2002/02/09 14:55:23 oliverschwartz
|
|
|
|
|
* Added language translation support (SANE_I18N)
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.39 2002/01/23 20:40:54 oliverschwartz
|
|
|
|
|
* Don't use quantization for scan area parameter
|
|
|
|
|
* Improve recognition of Acer 320U
|
|
|
|
|
* Version 1.4.7
|
2002-01-15 20:16:55 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.38 2002/01/14 21:11:56 oliverschwartz
|
|
|
|
|
* Add workaround for bug semctl() call in libc for PPC
|
2002-01-10 22:20:17 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.37 2002/01/10 21:33:12 oliverschwartz
|
|
|
|
|
* Set version number to 1.4.4
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.36 2002/01/06 18:34:02 oliverschwartz
|
|
|
|
|
* Added support for Snapscan e42 thanks to Yari Ad<EFBFBD>n Petralanda
|
2001-12-20 23:22:52 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.35 2001/12/20 23:18:01 oliverschwartz
|
|
|
|
|
* Remove tmpfname
|
2001-12-18 18:34:17 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.34 2001/12/18 18:28:35 oliverschwartz
|
|
|
|
|
* Removed temporary file
|
2001-10-27 09:08:17 +00:00
|
|
|
|
*
|
2001-12-17 22:51:52 +00:00
|
|
|
|
* Revision 1.33 2001/12/12 19:43:30 oliverschwartz
|
|
|
|
|
* - Set version number to 1.4.3
|
|
|
|
|
* - Clean up CVS Log
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.32 2001/12/09 23:06:45 oliverschwartz
|
|
|
|
|
* - use sense handler for USB if scanner reports CHECK_CONDITION
|
2001-10-25 10:56:41 +00:00
|
|
|
|
*
|
2001-12-17 22:51:52 +00:00
|
|
|
|
* Revision 1.31 2001/12/08 11:50:34 oliverschwartz
|
|
|
|
|
* Fix dither matrix computation
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.30 2001/11/29 22:50:14 oliverschwartz
|
|
|
|
|
* Add support for SnapScan e52
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.29 2001/11/27 23:16:17 oliverschwartz
|
|
|
|
|
* - Fix color alignment for SnapScan 600
|
|
|
|
|
* - Added documentation in snapscan-sources.c
|
|
|
|
|
* - Guard against TL_X < BR_X and TL_Y < BR_Y
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.28 2001/11/25 18:51:41 oliverschwartz
|
|
|
|
|
* added support for SnapScan e52 thanks to Rui Lopes
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.27 2001/11/16 20:28:35 oliverschwartz
|
|
|
|
|
* add support for Snapscan e26
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.26 2001/11/16 20:23:16 oliverschwartz
|
|
|
|
|
* Merge with sane-1.0.6
|
|
|
|
|
* - Check USB vendor IDs to avoid hanging scanners
|
|
|
|
|
* - fix bug in dither matrix computation
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.25 2001/10/25 11:06:22 oliverschwartz
|
|
|
|
|
* Change snapscan backend version number to 1.4.0
|
2001-10-12 21:19:16 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.24 2001/10/11 14:02:10 oliverschwartz
|
|
|
|
|
* Distinguish between e20/e25 and e40/e50
|
2001-10-10 07:30:06 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.23 2001/10/09 22:34:23 oliverschwartz
|
|
|
|
|
* fix compiler warnings
|
2001-10-09 09:45:21 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.22 2001/10/08 19:26:01 oliverschwartz
|
|
|
|
|
* - Disable quality calibration for scanners that do not support it
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.21 2001/10/08 18:22:02 oliverschwartz
|
|
|
|
|
* - Disable quality calibration for Acer Vuego 310F
|
|
|
|
|
* - Use sanei_scsi_max_request_size as scanner buffer size
|
|
|
|
|
* for SCSI devices
|
|
|
|
|
* - Added new devices to snapscan.desc
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.20 2001/09/18 15:01:07 oliverschwartz
|
|
|
|
|
* - Read scanner id string again after firmware upload
|
|
|
|
|
* to indentify correct model
|
|
|
|
|
* - Make firmware upload work for AGFA scanners
|
|
|
|
|
* - Change copyright notice
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.19 2001/09/17 10:01:08 sable
|
|
|
|
|
* Added model AGFA 1236U
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.18 2001/09/10 10:16:32 oliverschwartz
|
|
|
|
|
* better USB / SCSI recognition, correct max scan area for 1236+TPO
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.17 2001/09/09 18:06:32 oliverschwartz
|
|
|
|
|
* 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
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.16 2001/09/07 09:42:13 oliverschwartz
|
|
|
|
|
* Sync with Sane-1.0.5
|
2001-06-01 16:24:46 +00:00
|
|
|
|
*
|
2001-10-09 09:45:21 +00:00
|
|
|
|
* Revision 1.15 2001/05/15 20:51:14 oliverschwartz
|
|
|
|
|
* check for pss->devname instead of name in sane_open()
|
2001-05-26 12:47:34 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.14 2001/04/10 13:33:06 sable
|
|
|
|
|
* Transparency adapter bug and xsane crash corrections thanks to Oliver Schwartz
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.13 2001/04/10 13:00:31 sable
|
|
|
|
|
* Moving sanei_usb_* to snapscani_usb*
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.12 2001/04/10 11:04:31 sable
|
|
|
|
|
* Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.11 2001/03/17 22:53:21 sable
|
|
|
|
|
* Applying Mikael Magnusson patch concerning Gamma correction
|
|
|
|
|
* Support for 1212U_2
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.4 2001/03/04 16:50:53 mikael
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.3 2001/02/16 18:32:28 mikael
|
|
|
|
|
* impl calibration, signed position, increased buffer size
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.2 2001/02/10 18:18:29 mikael
|
|
|
|
|
* Extended x and y ranges
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.1.1.1 2001/02/10 17:09:29 mikael
|
|
|
|
|
* Imported from snapscan-11282000.tar.gz
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.10 2000/11/10 01:01:59 sable
|
|
|
|
|
* USB (kind of) autodetection
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.9 2000/11/01 01:26:43 sable
|
|
|
|
|
* Support for 1212U
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.8 2000/10/30 22:31:13 sable
|
|
|
|
|
* Auto preview mode
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.7 2000/10/28 14:16:10 sable
|
|
|
|
|
* Bug correction for SnapScan310
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.6 2000/10/28 14:06:35 sable
|
|
|
|
|
* Add support for Acer300f
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.5 2000/10/15 19:52:06 cbagwell
|
|
|
|
|
* Changed USB support to a 1 line modification instead of multi-file
|
|
|
|
|
* changes.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.4 2000/10/13 03:50:27 cbagwell
|
|
|
|
|
* Updating to source from SANE 1.0.3. Calling this versin 1.1
|
|
|
|
|
*
|
2000-08-12 15:11:46 +00:00
|
|
|
|
* Revision 1.3 2000/08/12 15:09:35 pere
|
|
|
|
|
* Merge devel (v1.0.3) into head branch.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.1.1.1.2.5 2000/07/29 16:04:33 hmg
|
|
|
|
|
* 2000-07-29 Henning Meier-Geinitz <hmg@gmx.de>
|
|
|
|
|
*
|
2001-10-09 09:45:21 +00:00
|
|
|
|
* * backend/GUIDE: Added some comments about portability and
|
|
|
|
|
* documentation.
|
|
|
|
|
* * backend/abaton.c backend/agfafocus.c backend/apple.c
|
|
|
|
|
* backend/canon.c backend/coolscan.c backend/dc210.c backend/dc25.c
|
|
|
|
|
* backend/dll.c backend/dmc.c backend/microtek.c backend/microtek2.c
|
|
|
|
|
* backend/microtek2.c backend/mustek_pp.c backend/net.c backend/pint.c
|
|
|
|
|
* backend/pnm.c backend/qcam.c backend/ricoh.c backend/s9036.c
|
|
|
|
|
* backend/sane_strstatus.c backend/sharp.c backend/snapscan.c
|
|
|
|
|
* backend/st400.c backend/stubs.c backend/tamarack.c backend/v4l.c:
|
|
|
|
|
* Changed include statements from #include <sane/...> to
|
|
|
|
|
* #include "sane...".
|
|
|
|
|
* * backend/avision.c backend/dc25.c: Use DBG(0, ...) instead of
|
|
|
|
|
* fprintf (stderr, ...)
|
|
|
|
|
* * backend/avision.c backend/canon-sane.c backend/coolscan.c
|
|
|
|
|
* backend/dc25.c backend/microtek.c backend/microtek2.c
|
|
|
|
|
* backend/st400.c: Use sanei_config_read() instead of fgets().
|
|
|
|
|
* * backend/coolscan.desc backend/microtek.desc backend/microtek2.desc
|
|
|
|
|
* backend/st400.desc: Added :interface and :manpage entries.
|
|
|
|
|
* * backend/nec.desc: Status is beta now (was: new). Fixed typo.
|
|
|
|
|
* * doc/canon.README: Removed, because the information is included in
|
|
|
|
|
* the manpage now.
|
|
|
|
|
* * doc/Makefile.in: Added sane-coolscan to list of mapages to install.
|
|
|
|
|
* * README: Added Link to coolscan manpage.
|
|
|
|
|
* * backend/mustek.*: Update to Mustek backend 1.0-94. Fixed the
|
|
|
|
|
* #include <sane/...> bug.
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.1.1.1.2.4 2000/07/25 21:47:43 hmg
|
|
|
|
|
* 2000-07-25 Henning Meier-Geinitz <hmg@gmx.de>
|
|
|
|
|
*
|
2001-10-09 09:45:21 +00:00
|
|
|
|
* * backend/snapscan.c: Use DBG(0, ...) instead of fprintf (stderr, ...).
|
|
|
|
|
* * backend/abaton.c backend/agfafocus.c backend/apple.c backend/dc210.c
|
|
|
|
|
* backend/dll.c backend/dmc.c backend/microtek2.c backend/pint.c
|
|
|
|
|
* backend/qcam.c backend/ricoh.c backend/s9036.c backend/snapscan.c
|
|
|
|
|
* backend/tamarack.c: Use sanei_config_read instead of fgets.
|
|
|
|
|
* * backend/dc210.c backend/microtek.c backend/pnm.c: Added
|
|
|
|
|
* #include <sane/config.h>.
|
|
|
|
|
* * backend/dc25.c backend/m3096.c backend/sp15.c
|
|
|
|
|
* backend/st400.c: Moved #include <sane/config.h> to the beginning.
|
|
|
|
|
* * AUTHORS: Changed agfa to agfafocus.
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.1.1.1.2.3 2000/07/17 21:37:28 hmg
|
|
|
|
|
* 2000-07-17 Henning Meier-Geinitz <hmg@gmx.de>
|
|
|
|
|
*
|
2001-10-09 09:45:21 +00:00
|
|
|
|
* * backend/snapscan.c backend/snapscan-scsi.c: Replace C++ comment
|
|
|
|
|
* with C comment.
|
2000-08-12 15:11:46 +00:00
|
|
|
|
*
|
|
|
|
|
* Revision 1.1.1.1.2.2 2000/07/13 04:47:46 pere
|
|
|
|
|
* New snapscan backend version dated 20000514 from Steve Underwood.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.2 2000/05/14 13:30:20 coppice
|
|
|
|
|
* R, G and B images now merge correctly. Still some outstanding issues,
|
|
|
|
|
* but a lot more useful than before.
|
|
|
|
|
*
|
2000-03-05 13:57:25 +00:00
|
|
|
|
* Revision 1.2 2000/03/05 13:55:20 pere
|
|
|
|
|
* Merged main branch with current DEVEL_1_9.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.1.1.1.2.1 1999/09/15 18:20:44 charter
|
|
|
|
|
* Early version 1.0 snapscan.c
|
|
|
|
|
*
|
|
|
|
|
* Revision 2.2 1999/09/09 18:22:45 charter
|
|
|
|
|
* Checkpoint. Now using Sources for scanner data, and have removed
|
|
|
|
|
* references to the old snapscan-310.c stuff. This stuff must still
|
|
|
|
|
* be incorporated into the RGBRouter to get trilinear CCD SnapScan
|
|
|
|
|
* models working.
|
|
|
|
|
*
|
|
|
|
|
* Revision 2.1 1999/09/08 03:07:05 charter
|
|
|
|
|
* Start of branch 2; same as 1.47.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.47 1999/09/08 03:03:53 charter
|
|
|
|
|
* The actions for the scanner command options now use fprintf for
|
|
|
|
|
* printing, rather than DGB. I want the output to come out no matter
|
|
|
|
|
* what the value of the snapscan debug level.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.46 1999/09/07 20:53:41 charter
|
|
|
|
|
* Changed expected_data_len to bytes_remaining.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.45 1999/09/06 23:32:37 charter
|
|
|
|
|
* Split up sane_start() into sub-functions to improve readability (again).
|
|
|
|
|
* Introduced actual_mode() and is_colour_mode() (again).
|
|
|
|
|
* Fixed problems with cancellation. Works fine with my system now.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.44 1999/09/02 05:28:01 charter
|
|
|
|
|
* Added Gary Plewa's name to the list of copyrighted contributors.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.43 1999/09/02 05:23:54 charter
|
|
|
|
|
* Added Gary Plewa's patch for the Acer PRISA 620s.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.42 1999/09/02 02:05:34 charter
|
|
|
|
|
* Check-in of revision 1.42 (release 0.7 of the backend).
|
|
|
|
|
* This is part of the recovery from the great disk crash of Sept 1, 1999.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.42 1999/07/09 22:37:55 charter
|
|
|
|
|
* Potential bugfix for problems with sane_get_parameters() and
|
|
|
|
|
* the new generic scsi driver (suggested by Francois Desarmeni,
|
|
|
|
|
* Douglas Gilbert, Abel Deuring).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.41 1999/07/09 20:58:07 charter
|
|
|
|
|
* Changes to support SnapScan 1236s (Petter Reinholdsten).
|
1999-08-09 18:06:01 +00:00
|
|
|
|
*
|
2000-03-05 13:57:25 +00:00
|
|
|
|
* Revision 1.40 1998/12/16 18:43:06 charter
|
1999-08-09 18:06:01 +00:00
|
|
|
|
* Fixed major version problem precipitated by release of SANE-1.00.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.39 1998/09/07 06:09:26 charter
|
|
|
|
|
* Formatting (whitespace) changes.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.38 1998/09/07 06:06:01 charter
|
|
|
|
|
* Merged in Wolfgang Goeller's changes (Vuego 310S, bugfixes).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.37 1998/08/06 06:16:39 charter
|
|
|
|
|
* Now using sane_config_attach_matching_devices() in sane_snapscan_init().
|
|
|
|
|
* Change contributed by David Mosberger-Tang.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.36 1998/05/11 17:02:53 charter
|
|
|
|
|
* Added Mikko's threshold stuff.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.35 1998/03/10 23:43:23 eblot
|
|
|
|
|
* Bug correction
|
|
|
|
|
*
|
|
|
|
|
* Revision 0.72 1998/03/10 23:40:42 eblot
|
|
|
|
|
* More support for 310/600 models: color preview, large window
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.35 1998/03/10 21:32:07 eblot
|
|
|
|
|
* Debugging
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.34 1998/02/15 21:55:53 charter
|
|
|
|
|
* From Emmanuel Blot:
|
|
|
|
|
* First routines to support SnapScan 310 scanned data.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.33 1998/02/06 02:30:28 charter
|
|
|
|
|
* Now using a mode enum (instead of the static string pointers directly).
|
|
|
|
|
* Now check for the SnapScan 310 and 600 explicitly (start of support
|
|
|
|
|
* for these models).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.32 1998/02/01 21:56:48 charter
|
|
|
|
|
* Patches to fix compilation problems on Solaris supplied by
|
|
|
|
|
* Jim McBeath.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.31 1998/02/01 03:36:40 charter
|
|
|
|
|
* Now check for BRX < TLX and BRY < TLY and whether the area of the
|
|
|
|
|
* scanning window is approaching zero in set_window. I'm setting a
|
|
|
|
|
* minimum window size of 75x75 hardware pixels (0.25 inches a side).
|
|
|
|
|
* If the area falls to zero, the scanner seems to hang in the middle
|
|
|
|
|
* of the set_window command.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.30 1998/02/01 00:00:33 charter
|
|
|
|
|
* TLX, TLY, BRX and BRY are now lengths expressed in mm. The frontends
|
|
|
|
|
* can now allow changes in the units, and units that are more user-
|
|
|
|
|
* friendly.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.29 1998/01/31 21:09:19 charter
|
|
|
|
|
* Fixed another problem with add_device(): if mini_inquiry ends
|
|
|
|
|
* up indirectly invoking the sense handler, there'll be a segfault
|
|
|
|
|
* because the sense_handler isn't set. Had to fix sense_handler so
|
|
|
|
|
* it can handle a NULL pss pointer and then use the sanei_scsi stuff
|
|
|
|
|
* everywhere. This error is most likely to occur if the scanner is
|
|
|
|
|
* turned off.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.28 1998/01/31 18:45:22 charter
|
|
|
|
|
* Last fix botched, produced a compile error. Thought I'd already
|
|
|
|
|
* compiled successfully.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.27 1998/01/31 18:32:42 charter
|
|
|
|
|
* Fixed stupid bug in add_device that causes segfault when no snapscan
|
|
|
|
|
* found: closing a scsi fd opened with open() using sanei_scsi_close().
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.26 1998/01/30 21:19:02 charter
|
|
|
|
|
* sane_snapscan_init() handles failure of add_device() in the same
|
|
|
|
|
* way when there is no snapscan.conf file available as when there is
|
|
|
|
|
* one.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.25 1998/01/30 19:41:11 charter
|
|
|
|
|
* Waiting for child process termination at regular end of scan (not
|
|
|
|
|
* just on cancellation); before I was getting zombies.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.24 1998/01/30 19:19:27 charter
|
|
|
|
|
* Changed from strncmp() to strncasecmp() to do vendor and model
|
|
|
|
|
* comparisons in sane_snapscan_init. There are some snapcsan models
|
|
|
|
|
* that use lower case.
|
|
|
|
|
* Now have debug level defines instead of raw numbers, and better debug
|
|
|
|
|
* information categories.
|
|
|
|
|
* Don't complain at debug level 0 when a snapscan isn't found on a
|
|
|
|
|
* requested device.
|
|
|
|
|
* Changed CHECK_STATUS to take caller parameter instead of always
|
|
|
|
|
* assuming an available string "me".
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.23 1998/01/30 11:03:04 charter
|
|
|
|
|
* Fixed * vs [] operator precedence screwup in sane_snapscan_get_devices()
|
|
|
|
|
* that caused a segfault in scanimage -h.
|
|
|
|
|
* Fixed problem with not closing the scsi fd between certain commands
|
|
|
|
|
* that caused scanimage to hang; now using open_scanner() and close_scanner().
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.22 1998/01/28 09:02:55 charter
|
|
|
|
|
* Fixed bug: zero allocation length in request sense command buffer
|
|
|
|
|
* was preventing sense information from being received. The
|
|
|
|
|
* backend now correctly waits for the scanner to warm up.
|
|
|
|
|
* Now using the hardware configuration byte to check whether
|
|
|
|
|
* both 8x8 and 16x16 halftoning should be made available.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.21 1998/01/25 09:57:57 charter
|
|
|
|
|
* Added more SCSI command buttons (and a group for them).
|
|
|
|
|
* Made the output of the Inquiry command a bit nicer.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.20 1998/01/25 08:53:14 charter
|
|
|
|
|
* Have added bi-level colour mode, with halftones too.
|
|
|
|
|
* Can now select preview mode (but it's an advanced option, since
|
|
|
|
|
* you usually don't want to do it).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.19 1998/01/25 02:25:02 charter
|
|
|
|
|
* Fixed bug: preview mode gives blank image at initial startup.
|
|
|
|
|
* Fixed bug: lineart mode goes weird after a preview or gs image.
|
|
|
|
|
* More changes to option relationships;
|
|
|
|
|
* now using test_unit_ready and send_diagnostic in sane_snapscan_open().
|
|
|
|
|
* Added negative option.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.18 1998/01/24 05:15:32 charter
|
|
|
|
|
* Now have RGB gamma correction and dispersed-dot dither halftoning
|
|
|
|
|
* for BW images. Cleaned up some spots in the code and have set up
|
|
|
|
|
* option interactions a bit better (e.g. halftoning and GS gamma
|
|
|
|
|
* correction made inactive in colour mode, etc). TL_[XY] and BR_[XY]
|
|
|
|
|
* now change in ten-pixel increments (I had problems with screwed-up
|
|
|
|
|
* scan lines when the dimensions were weird at low res... could be the
|
|
|
|
|
* problem).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.17 1998/01/23 13:03:17 charter
|
|
|
|
|
* Several changes, all aimed at getting scanning performance working
|
|
|
|
|
* correctly, and the progress/cancel window functioning. Cleaned up
|
|
|
|
|
* a few nasty things as well.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.16 1998/01/23 07:40:23 charter
|
|
|
|
|
* Reindented using GNU convention at David Mosberger-Tang's request.
|
|
|
|
|
* Also applied David's patch fixing problems on 64-bit architectures.
|
|
|
|
|
* Now using scanner's reported speed to guage amount of data to request
|
|
|
|
|
* in a read on the scsi fd---nonblocking mode operates better now.
|
|
|
|
|
* Fixed stupid bug I introduced in preview mode data transfer.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.15 1998/01/22 06:18:57 charter
|
|
|
|
|
* Raised the priority of a couple of DBG messages in reserve_unit()
|
|
|
|
|
* and release_unit(), and got rid of some unecessary ones.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.14 1998/01/22 05:15:35 charter
|
|
|
|
|
* Have replaced the bit depth option with a mode option; various
|
|
|
|
|
* changes associated with that.
|
|
|
|
|
* Also, I again close the STDERR_FILENO in the reader child and
|
|
|
|
|
* dup the STDOUT file descriptor onto it. This prevents an "X io"
|
|
|
|
|
* error when the child exits, while still allowing the use of
|
|
|
|
|
* DBG.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.13 1998/01/21 20:41:22 charter
|
|
|
|
|
* Added copyright info.
|
|
|
|
|
* Also now seem to have cancellation working. This requires using a
|
|
|
|
|
* new scanner state variable and checking in all the right places
|
|
|
|
|
* in the reader child and the sane_snapscan_read function. I've
|
|
|
|
|
* tested it using both blocking and nonblocking I/O and it seems
|
|
|
|
|
* to work both ways.
|
|
|
|
|
* I've also switched to GTK+-0.99.2 and sane-0.69, and the
|
|
|
|
|
* mysterious problems with the preview window have disappeared.
|
|
|
|
|
* Problems with scanimage doing weird things to options have also
|
|
|
|
|
* gone away and the frontends seem more stable.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.12 1998/01/21 11:05:53 charter
|
|
|
|
|
* Inoperative code largely #defined out; I had the preview window
|
|
|
|
|
* working correctly by having the window coordinates properly
|
|
|
|
|
* constrained, but now the preview window bombs with a floating-
|
|
|
|
|
* point error each time... I'm not sure yet what happened.
|
|
|
|
|
* I've also figured out that we need to use reserve_unit and
|
|
|
|
|
* release_unit in order to cancel scans in progress. This works
|
|
|
|
|
* under scanimage, but I can't seem to find a way to fit cancellation
|
|
|
|
|
* into xscanimage properly.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.11 1998/01/20 22:42:08 charter
|
|
|
|
|
* Applied Franck's patch from Dec 17; preview mode is now grayscale.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.10 1997/12/10 23:33:12 charter
|
|
|
|
|
* Slight change to some floating-point computations in the brightness
|
|
|
|
|
* and contrast stuff. The controls don't seem to do anything to the
|
|
|
|
|
* scanner though (I think these aren't actually supported in the
|
|
|
|
|
* SnapScan).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.9 1997/11/26 15:40:50 charter
|
|
|
|
|
* Brightness and contrast added by Michel.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.8 1997/11/12 12:55:40 charter
|
|
|
|
|
* No longer exec after forking to do nonblocking scanning; found how
|
|
|
|
|
* to fix the problems with SIGPIPEs from before.
|
|
|
|
|
* Now support a config file like the other scanner drivers, and
|
|
|
|
|
* can check whether a given device is an AGFA SnapScan (mini_inquiry()).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.7 1997/11/10 05:52:08 charter
|
|
|
|
|
* Now have the child reader process and pipe stuff working, and
|
|
|
|
|
* nonblocking mode. For large scans the nonblocking mode actually
|
|
|
|
|
* seems to cut down on cpu hogging (though there is still a hit).
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.6 1997/11/03 07:45:54 charter
|
|
|
|
|
* Added the predef_window stuff. I've tried it with 6x4, and it seems
|
|
|
|
|
* to work; I think something gets inconsistent if a preview is
|
|
|
|
|
* performed though.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.5 1997/11/03 03:15:27 charter
|
|
|
|
|
* Global static variables have now become part of the scanner structure;
|
|
|
|
|
* the inquiry command automatically retrieves window parameters into
|
|
|
|
|
* scanner structure members. Things are a bit cleaned up.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.4 1997/11/02 23:35:28 charter
|
|
|
|
|
* After much grief.... I can finally scan reliably. Now it's a matter
|
|
|
|
|
* of getting the band arrangement sorted out.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.3 1997/10/30 07:36:37 charter
|
|
|
|
|
* Fixed a stupid bug in the #defines for the inquiry command, pointed out
|
|
|
|
|
* by Franck.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.2 1997/10/14 06:00:11 charter
|
|
|
|
|
* Option manipulation and some basic SCSI commands done; the basics
|
|
|
|
|
* for scanning are written but there are bugs. A full scan always hangs
|
|
|
|
|
* the SCSI driver, and preview mode scans complete but it isn't clear
|
|
|
|
|
* whether any meaningful data is received.
|
|
|
|
|
*
|
|
|
|
|
* Revision 1.1 1997/10/13 02:25:54 charter
|
|
|
|
|
* Initial revision
|
|
|
|
|
* */
|