kopia lustrzana https://gitlab.com/sane-project/backends
Added sm3840 backend (from "Earle F. Philhower, III"
<earlephilhower@yahoo.com>).merge-requests/1/head
rodzic
46d59a14aa
commit
316d7553e4
2
AUTHORS
2
AUTHORS
|
@ -65,6 +65,7 @@ Backends:
|
|||
sceptre: Frank Zago (*)
|
||||
sharp: Kazuya Fukuda and Abel Deuring (*)
|
||||
sm3600: Marian Eichholz (*) and Glenn Ramsey
|
||||
sm3840: Earle F. Philhower III
|
||||
snapscan: Kevin Charter, Franck Schneider, Michel Roelofs, Sebastien
|
||||
Sable, Henrik Johansson, Chris Bagwell, and Oliver Schwartz (*)
|
||||
sp15c: Randolph Bentson
|
||||
|
@ -131,6 +132,7 @@ David Huggins-Daines <bn711@freenet.carleton.ca>
|
|||
David Mosberger <David.Mosberger@acm.org>
|
||||
David Stevenson <david.stevenson@zoom.co.uk>
|
||||
Didier Carlier <didier@sema.be>
|
||||
Earle F. Philhower III <earle@ziplabel.com>
|
||||
Eddy De Greef <eddy_de_greef at tiscali dot be>
|
||||
Eugene S. Weiss <yossarian@users.sourceforge.net>
|
||||
Feico W. Dillema <dillema@acm.org>
|
||||
|
|
|
@ -150,7 +150,10 @@ DISTFILES = abaton.c abaton.conf abaton.h agfafocus.c agfafocus.conf \
|
|||
umax_pp_low.c umax_pp_low.h umax_pp_mid.c umax_pp_mid.h umax-scanner.c \
|
||||
umax-scanner.h umax-scsidef.h umax-uc1200s.c umax-uc1200se.c umax-uc1260.c \
|
||||
umax-uc630.c umax-uc840.c umax-ug630.c umax-ug80.c umax-usb.c v4l.c \
|
||||
v4l.conf v4l-frequencies.h v4l.h
|
||||
v4l.conf v4l-frequencies.h v4l.h \
|
||||
sm3840.c sm3840_lib.c sm3840_params.h sm3840_scan.c sm3840.h \
|
||||
sm3840_lib.h sm3840-s.c
|
||||
|
||||
|
||||
|
||||
.PHONY: all clean depend dist distclean install uninstall
|
||||
|
@ -394,6 +397,9 @@ libsane-sharp.la: ../sanei/sanei_config2.lo
|
|||
libsane-sharp.la: ../sanei/sanei_constrain_value.lo
|
||||
libsane-sharp.la: ../sanei/sanei_scsi.lo
|
||||
libsane-sm3600.la: ../sanei/sanei_constrain_value.lo
|
||||
libsane-sm3840.la: ../sanei/sanei_config2.lo
|
||||
libsane-sm3840.la: ../sanei/sanei_constrain_value.lo
|
||||
libsane-sm3840.la: ../sanei/sanei_usb.lo
|
||||
libsane-snapscan.la: ../sanei/sanei_config2.lo
|
||||
libsane-snapscan.la: ../sanei/sanei_constrain_value.lo
|
||||
libsane-snapscan.la: ../sanei/sanei_scsi.lo
|
||||
|
|
|
@ -46,6 +46,7 @@ s9036
|
|||
sceptre
|
||||
sharp
|
||||
sm3600
|
||||
sm3840
|
||||
snapscan
|
||||
sp15c
|
||||
#st400
|
||||
|
|
|
@ -0,0 +1,747 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
ScanMaker 3840 Backend
|
||||
Copyright (C) 2005 Earle F. Philhower, III
|
||||
earle@ziplabel.com - http://www.ziplabel.com
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
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.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include "../include/sane/config.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../include/sane/sane.h"
|
||||
#include "../include/sane/saneopts.h"
|
||||
|
||||
#define BACKENDNAME sm3840
|
||||
#include "../include/sane/sanei_backend.h"
|
||||
#include "../include/sane/sanei_usb.h"
|
||||
#include "../include/sane/sanei_config.h"
|
||||
|
||||
#include "sm3840.h"
|
||||
|
||||
#include "sm3840_scan.c"
|
||||
#include "sm3840_lib.c"
|
||||
|
||||
static double sm3840_unit_convert (SANE_Int val);
|
||||
|
||||
static int num_devices;
|
||||
static SM3840_Device *first_dev;
|
||||
static SM3840_Scan *first_handle;
|
||||
static const SANE_Device **devlist = 0;
|
||||
|
||||
static const SANE_String_Const mode_list[] = {
|
||||
SANE_I18N ("Gray"), SANE_I18N ("Color"),
|
||||
0
|
||||
};
|
||||
|
||||
static const SANE_Word resolution_list[] = {
|
||||
4, 1200, 600, 300, 150
|
||||
};
|
||||
|
||||
static const SANE_Word bpp_list[] = {
|
||||
2, 8, 16
|
||||
};
|
||||
|
||||
static const SANE_Range x_range = {
|
||||
SANE_FIX (0),
|
||||
SANE_FIX (215.91), /* 8.5 inches */
|
||||
SANE_FIX (0)
|
||||
};
|
||||
|
||||
static const SANE_Range y_range = {
|
||||
SANE_FIX (0),
|
||||
SANE_FIX (297.19), /* 11.7 inches */
|
||||
SANE_FIX (0)
|
||||
};
|
||||
|
||||
static const SANE_Range brightness_range = {
|
||||
1,
|
||||
4096,
|
||||
1.0
|
||||
};
|
||||
|
||||
static const SANE_Range contrast_range = {
|
||||
SANE_FIX (0.1),
|
||||
SANE_FIX (9.9),
|
||||
SANE_FIX (0.1)
|
||||
};
|
||||
|
||||
static const SANE_Range lamp_range = {
|
||||
1,
|
||||
15,
|
||||
1
|
||||
};
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int
|
||||
min (int a, int b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
|
||||
SANE_Int * len)
|
||||
{
|
||||
SM3840_Scan *s = handle;
|
||||
|
||||
DBG (2, "+sane-read:%p %p %d %p\n", (unsigned char *) s, buf, max_len,
|
||||
(unsigned char *) len);
|
||||
DBG (2,
|
||||
"+sane-read:remain:%d offset:%d linesleft:%d linebuff:%p linesread:%d\n",
|
||||
s->remaining, s->offset, s->linesleft, s->line_buffer, s->linesread);
|
||||
|
||||
if (!s->scanning)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
if (!s->remaining)
|
||||
{
|
||||
if (!s->linesleft)
|
||||
{
|
||||
*len = 0;
|
||||
s->scanning = 0;
|
||||
/* Move to home position */
|
||||
reset_scanner ((usb_dev_handle *) s->udev);
|
||||
/* Send lamp timeout */
|
||||
set_lamp_timer ((usb_dev_handle *) s->udev, s->sm3840_params.lamp);
|
||||
|
||||
/* Free memory */
|
||||
if (s->save_scan_line)
|
||||
free (s->save_scan_line);
|
||||
s->save_scan_line = NULL;
|
||||
if (s->save_dpi1200_remap)
|
||||
free (s->save_dpi1200_remap);
|
||||
s->save_dpi1200_remap = NULL;
|
||||
if (s->save_color_remap)
|
||||
free (s->save_color_remap);
|
||||
s->save_color_remap = NULL;
|
||||
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
|
||||
record_line ((s->linesread == 0) ? 1 : 0,
|
||||
(usb_dev_handle *) s->udev,
|
||||
s->line_buffer,
|
||||
s->sm3840_params.dpi,
|
||||
s->sm3840_params.scanpix,
|
||||
s->sm3840_params.gray,
|
||||
(s->sm3840_params.bpp == 16) ? 1 : 0,
|
||||
&s->save_i,
|
||||
&s->save_scan_line,
|
||||
&s->save_dpi1200_remap, &s->save_color_remap);
|
||||
s->remaining = s->sm3840_params.linelen;
|
||||
s->offset = 0;
|
||||
s->linesread++;
|
||||
s->linesleft--;
|
||||
}
|
||||
|
||||
memcpy (buf, s->offset + s->line_buffer, min (max_len, s->remaining));
|
||||
|
||||
*len = min (max_len, s->remaining);
|
||||
s->offset += min (max_len, s->remaining);
|
||||
s->remaining -= min (max_len, s->remaining);
|
||||
|
||||
DBG (2, "-sane_read\n");
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void
|
||||
sane_cancel (SANE_Handle h)
|
||||
{
|
||||
SM3840_Scan *s = h;
|
||||
|
||||
DBG (2, "trying to cancel...\n");
|
||||
if (s->scanning)
|
||||
{
|
||||
if (!s->cancelled)
|
||||
{
|
||||
/* Move to home position */
|
||||
reset_scanner ((usb_dev_handle *) s->udev);
|
||||
/* Send lamp timeout */
|
||||
set_lamp_timer ((usb_dev_handle *) s->udev, s->sm3840_params.lamp);
|
||||
|
||||
/* Free memory */
|
||||
if (s->save_scan_line)
|
||||
free (s->save_scan_line);
|
||||
s->save_scan_line = NULL;
|
||||
if (s->save_dpi1200_remap)
|
||||
free (s->save_dpi1200_remap);
|
||||
s->save_dpi1200_remap = NULL;
|
||||
if (s->save_color_remap)
|
||||
free (s->save_color_remap);
|
||||
s->save_color_remap = NULL;
|
||||
|
||||
s->scanning = 0;
|
||||
s->cancelled = SANE_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_start (SANE_Handle handle)
|
||||
{
|
||||
SM3840_Scan *s = handle;
|
||||
SANE_Status status;
|
||||
|
||||
/* First make sure we have a current parameter set. Some of the
|
||||
* parameters will be overwritten below, but that's OK. */
|
||||
DBG (2, "sane_start\n");
|
||||
status = sane_get_parameters (s, 0);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
DBG (1, "Got params again...\n");
|
||||
|
||||
s->scanning = SANE_TRUE;
|
||||
s->cancelled = 0;
|
||||
|
||||
s->line_buffer = malloc (s->sm3840_params.linelen);
|
||||
s->remaining = 0;
|
||||
s->offset = 0;
|
||||
s->linesleft = s->sm3840_params.scanlines;
|
||||
s->linesread = 0;
|
||||
|
||||
s->save_i = 0;
|
||||
s->save_scan_line = NULL;
|
||||
s->save_dpi1200_remap = NULL;
|
||||
s->save_color_remap = NULL;
|
||||
|
||||
setup_scan ((usb_dev_handle *) s->udev, &(s->sm3840_params));
|
||||
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
static double
|
||||
sm3840_unit_convert (SANE_Int val)
|
||||
{
|
||||
double d;
|
||||
d = SANE_UNFIX (val);
|
||||
d /= MM_PER_INCH;
|
||||
return d;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
||||
{
|
||||
SM3840_Scan *s = handle;
|
||||
|
||||
DBG (2, "sane_get_parameters\n");
|
||||
if (!s->scanning)
|
||||
{
|
||||
memset (&s->sane_params, 0, sizeof (s->sane_params));
|
||||
/* Copy from options to sm3840_params */
|
||||
s->sm3840_params.gray =
|
||||
(!strcasecmp (s->value[OPT_MODE].s, SANE_I18N ("Gray"))) ? 1 : 0;
|
||||
s->sm3840_params.dpi = s->value[OPT_RESOLUTION].w;
|
||||
s->sm3840_params.bpp = s->value[OPT_BIT_DEPTH].w;
|
||||
s->sm3840_params.gain = SANE_UNFIX (s->value[OPT_CONTRAST].w);
|
||||
s->sm3840_params.offset = s->value[OPT_BRIGHTNESS].w;
|
||||
s->sm3840_params.lamp = s->value[OPT_LAMP_TIMEOUT].w;
|
||||
|
||||
s->sm3840_params.top = sm3840_unit_convert (s->value[OPT_TL_Y].w);
|
||||
s->sm3840_params.left = sm3840_unit_convert (s->value[OPT_TL_X].w);
|
||||
s->sm3840_params.width =
|
||||
sm3840_unit_convert (s->value[OPT_BR_X].w) - s->sm3840_params.left;
|
||||
s->sm3840_params.height =
|
||||
sm3840_unit_convert (s->value[OPT_BR_Y].w) - s->sm3840_params.top;
|
||||
|
||||
/* Legalize and calculate pixel sizes */
|
||||
prepare_params (&(s->sm3840_params));
|
||||
|
||||
/* Copy into sane_params */
|
||||
s->sane_params.pixels_per_line = s->sm3840_params.scanpix;
|
||||
s->sane_params.lines = s->sm3840_params.scanlines;
|
||||
s->sane_params.format =
|
||||
s->sm3840_params.gray ? SANE_FRAME_GRAY : SANE_FRAME_RGB;
|
||||
s->sane_params.bytes_per_line = s->sm3840_params.linelen;
|
||||
s->sane_params.depth = s->sm3840_params.bpp;
|
||||
s->sane_params.last_frame = SANE_TRUE;
|
||||
} /*!scanning */
|
||||
|
||||
if (params)
|
||||
*params = s->sane_params;
|
||||
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_control_option (SANE_Handle handle, SANE_Int option,
|
||||
SANE_Action action, void *val, SANE_Int * info)
|
||||
{
|
||||
SM3840_Scan *s = handle;
|
||||
SANE_Status status = 0;
|
||||
SANE_Word cap;
|
||||
DBG (2, "sane_control_option\n");
|
||||
if (info)
|
||||
*info = 0;
|
||||
if (s->scanning)
|
||||
return SANE_STATUS_DEVICE_BUSY;
|
||||
if (option >= NUM_OPTIONS)
|
||||
return SANE_STATUS_INVAL;
|
||||
cap = s->options_list[option].cap;
|
||||
if (!SANE_OPTION_IS_ACTIVE (cap))
|
||||
return SANE_STATUS_INVAL;
|
||||
if (action == SANE_ACTION_GET_VALUE)
|
||||
{
|
||||
DBG (1, "sane_control_option %d, get value\n", option);
|
||||
switch (option)
|
||||
{
|
||||
/* word options: */
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_BIT_DEPTH:
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_CONTRAST:
|
||||
case OPT_BRIGHTNESS:
|
||||
case OPT_LAMP_TIMEOUT:
|
||||
*(SANE_Word *) val = s->value[option].w;
|
||||
return (SANE_STATUS_GOOD);
|
||||
/* string options: */
|
||||
case OPT_MODE:
|
||||
strcpy (val, s->value[option].s);
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
else if (action == SANE_ACTION_SET_VALUE)
|
||||
{
|
||||
DBG (1, "sane_control_option %d, set value\n", option);
|
||||
if (!SANE_OPTION_IS_SETTABLE (cap))
|
||||
return (SANE_STATUS_INVAL);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return (status);
|
||||
status = sanei_constrain_value (s->options_list + option, val, info);
|
||||
switch (option)
|
||||
{
|
||||
/* (mostly) side-effect-free word options: */
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_BIT_DEPTH:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
if (info)
|
||||
*info |= SANE_INFO_RELOAD_PARAMS;
|
||||
/* fall through */
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_CONTRAST:
|
||||
case OPT_BRIGHTNESS:
|
||||
case OPT_LAMP_TIMEOUT:
|
||||
s->value[option].w = *(SANE_Word *) val;
|
||||
DBG (1, "set brightness to\n");
|
||||
return (SANE_STATUS_GOOD);
|
||||
case OPT_MODE:
|
||||
if (s->value[option].s)
|
||||
free (s->value[option].s);
|
||||
s->value[option].s = strdup (val);
|
||||
if (info)
|
||||
*info |= SANE_INFO_RELOAD_PARAMS;
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
const SANE_Option_Descriptor *
|
||||
sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
||||
{
|
||||
SM3840_Scan *s = handle;
|
||||
DBG (2, "sane_get_option_descriptor\n");
|
||||
if ((unsigned) option >= NUM_OPTIONS)
|
||||
return (0);
|
||||
return (&s->options_list[option]);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
sane_close (SANE_Handle handle)
|
||||
{
|
||||
SM3840_Scan *prev, *s;
|
||||
|
||||
DBG (2, "sane_close\n");
|
||||
/* remove handle from list of open handles: */
|
||||
prev = 0;
|
||||
for (s = first_handle; s; s = s->next)
|
||||
{
|
||||
if (s == handle)
|
||||
break;
|
||||
prev = s;
|
||||
}
|
||||
if (!s)
|
||||
{
|
||||
DBG (1, "close: invalid handle %p\n", handle);
|
||||
return; /* oops, not a handle we know about */
|
||||
}
|
||||
|
||||
if (s->scanning)
|
||||
{
|
||||
sane_cancel (handle);
|
||||
}
|
||||
|
||||
sanei_usb_close (s->udev);
|
||||
|
||||
if (s->line_buffer)
|
||||
free (s->line_buffer);
|
||||
if (s->save_scan_line)
|
||||
free (s->save_scan_line);
|
||||
if (s->save_dpi1200_remap)
|
||||
free (s->save_dpi1200_remap);
|
||||
if (s->save_color_remap)
|
||||
free (s->save_color_remap);
|
||||
|
||||
if (prev)
|
||||
prev->next = s->next;
|
||||
else
|
||||
first_handle = s;
|
||||
free (handle);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void
|
||||
sane_exit (void)
|
||||
{
|
||||
SM3840_Device *next;
|
||||
DBG (2, "sane_exit\n");
|
||||
while (first_dev != NULL)
|
||||
{
|
||||
next = first_dev->next;
|
||||
free (first_dev);
|
||||
first_dev = next;
|
||||
}
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
|
||||
{
|
||||
DBG_INIT ();
|
||||
if (version_code)
|
||||
*version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 0);
|
||||
if (authorize)
|
||||
DBG(2, "Unused authorize\n");
|
||||
|
||||
sanei_usb_init ();
|
||||
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static SANE_Status
|
||||
add_sm3840_device (SANE_String_Const devname)
|
||||
{
|
||||
SM3840_Device *dev;
|
||||
|
||||
dev = calloc (sizeof (*dev), 1);
|
||||
if (!dev)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
|
||||
memset (dev, 0, sizeof (*dev));
|
||||
dev->sane.name = strdup (devname);
|
||||
dev->sane.model = "ScanMaker 3840";
|
||||
dev->sane.vendor = "Microtek";
|
||||
dev->sane.type = "flatbed scanner";
|
||||
++num_devices;
|
||||
dev->next = first_dev;
|
||||
first_dev = dev;
|
||||
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
|
||||
{
|
||||
static const SANE_Device **devlist = 0;
|
||||
SM3840_Device *dev;
|
||||
int i;
|
||||
|
||||
DBG (3, "sane_get_devices (local_only = %d)\n", local_only);
|
||||
|
||||
while (first_dev)
|
||||
{
|
||||
dev = first_dev->next;
|
||||
free (first_dev);
|
||||
first_dev = dev;
|
||||
}
|
||||
first_dev = NULL;
|
||||
num_devices = 0;
|
||||
|
||||
sanei_usb_find_devices (0x05da, 0x30d4, add_sm3840_device);
|
||||
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
devlist = calloc ((num_devices + 1) * sizeof (devlist[0]), 1);
|
||||
if (!devlist)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
i = 0;
|
||||
for (dev = first_dev; i < num_devices; dev = dev->next)
|
||||
devlist[i++] = &dev->sane;
|
||||
devlist[i++] = 0;
|
||||
if (device_list)
|
||||
*device_list = devlist;
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static size_t
|
||||
max_string_size (const SANE_String_Const strings[])
|
||||
{
|
||||
size_t size, max_size = 0;
|
||||
int i;
|
||||
for (i = 0; strings[i]; ++i)
|
||||
{
|
||||
size = strlen (strings[i]) + 1;
|
||||
if (size > max_size)
|
||||
max_size = size;
|
||||
}
|
||||
|
||||
return (max_size);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
initialize_options_list (SM3840_Scan * s)
|
||||
{
|
||||
|
||||
SANE_Int option;
|
||||
DBG (2, "initialize_options_list\n");
|
||||
for (option = 0; option < NUM_OPTIONS; ++option)
|
||||
{
|
||||
s->options_list[option].size = sizeof (SANE_Word);
|
||||
s->options_list[option].cap =
|
||||
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
}
|
||||
|
||||
s->options_list[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
|
||||
s->options_list[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
|
||||
s->options_list[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
|
||||
s->options_list[OPT_NUM_OPTS].type = SANE_TYPE_INT;
|
||||
s->options_list[OPT_NUM_OPTS].unit = SANE_UNIT_NONE;
|
||||
s->options_list[OPT_NUM_OPTS].size = sizeof (SANE_Word);
|
||||
s->options_list[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
|
||||
s->options_list[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE;
|
||||
s->value[OPT_NUM_OPTS].w = NUM_OPTIONS;
|
||||
|
||||
s->options_list[OPT_MODE].name = SANE_NAME_SCAN_MODE;
|
||||
s->options_list[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
|
||||
s->options_list[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
|
||||
s->options_list[OPT_MODE].type = SANE_TYPE_STRING;
|
||||
s->options_list[OPT_MODE].size = max_string_size (mode_list);
|
||||
s->options_list[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
||||
s->options_list[OPT_MODE].constraint.string_list = mode_list;
|
||||
s->value[OPT_MODE].s = strdup (mode_list[1]);
|
||||
|
||||
s->options_list[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
|
||||
s->options_list[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
|
||||
s->options_list[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
|
||||
s->options_list[OPT_RESOLUTION].type = SANE_TYPE_INT;
|
||||
s->options_list[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
|
||||
s->options_list[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
||||
s->options_list[OPT_RESOLUTION].constraint.word_list = resolution_list;
|
||||
s->value[OPT_RESOLUTION].w = 300;
|
||||
|
||||
s->options_list[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
|
||||
s->options_list[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
|
||||
s->options_list[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
|
||||
s->options_list[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
|
||||
s->options_list[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE;
|
||||
s->options_list[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
||||
s->options_list[OPT_BIT_DEPTH].constraint.word_list = bpp_list;
|
||||
s->value[OPT_BIT_DEPTH].w = 8;
|
||||
|
||||
s->options_list[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
|
||||
s->options_list[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
|
||||
s->options_list[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
|
||||
s->options_list[OPT_TL_X].type = SANE_TYPE_FIXED;
|
||||
s->options_list[OPT_TL_X].unit = SANE_UNIT_MM;
|
||||
s->options_list[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->options_list[OPT_TL_X].constraint.range = &x_range;
|
||||
s->value[OPT_TL_X].w = s->options_list[OPT_TL_X].constraint.range->min;
|
||||
s->options_list[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
|
||||
s->options_list[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
|
||||
s->options_list[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
|
||||
s->options_list[OPT_TL_Y].type = SANE_TYPE_FIXED;
|
||||
s->options_list[OPT_TL_Y].unit = SANE_UNIT_MM;
|
||||
s->options_list[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->options_list[OPT_TL_Y].constraint.range = &y_range;
|
||||
s->value[OPT_TL_Y].w = s->options_list[OPT_TL_Y].constraint.range->min;
|
||||
s->options_list[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
|
||||
s->options_list[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
|
||||
s->options_list[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
|
||||
s->options_list[OPT_BR_X].type = SANE_TYPE_FIXED;
|
||||
s->options_list[OPT_BR_X].unit = SANE_UNIT_MM;
|
||||
s->options_list[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->options_list[OPT_BR_X].constraint.range = &x_range;
|
||||
s->value[OPT_BR_X].w = s->options_list[OPT_BR_X].constraint.range->max;
|
||||
s->options_list[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
|
||||
s->options_list[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
|
||||
s->options_list[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
|
||||
s->options_list[OPT_BR_Y].type = SANE_TYPE_FIXED;
|
||||
s->options_list[OPT_BR_Y].unit = SANE_UNIT_MM;
|
||||
s->options_list[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->options_list[OPT_BR_Y].constraint.range = &y_range;
|
||||
s->value[OPT_BR_Y].w = s->options_list[OPT_BR_Y].constraint.range->max;
|
||||
|
||||
s->options_list[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
|
||||
s->options_list[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
|
||||
s->options_list[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
|
||||
s->options_list[OPT_CONTRAST].type = SANE_TYPE_FIXED;
|
||||
s->options_list[OPT_CONTRAST].unit = SANE_UNIT_NONE;
|
||||
s->options_list[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->options_list[OPT_CONTRAST].constraint.range = &contrast_range;
|
||||
s->value[OPT_CONTRAST].w = SANE_FIX (3.5);
|
||||
|
||||
s->options_list[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
|
||||
s->options_list[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
|
||||
s->options_list[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
|
||||
s->options_list[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
|
||||
s->options_list[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
|
||||
s->options_list[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->options_list[OPT_BRIGHTNESS].constraint.range = &brightness_range;
|
||||
s->value[OPT_BRIGHTNESS].w = 1800;
|
||||
|
||||
s->options_list[OPT_LAMP_TIMEOUT].name = "lamp-timeout";
|
||||
s->options_list[OPT_LAMP_TIMEOUT].title = SANE_I18N ("Lamp timeout");
|
||||
s->options_list[OPT_LAMP_TIMEOUT].desc =
|
||||
SANE_I18N ("Minutes until lamp is turned off after scan");
|
||||
s->options_list[OPT_LAMP_TIMEOUT].type = SANE_TYPE_INT;
|
||||
s->options_list[OPT_LAMP_TIMEOUT].unit = SANE_UNIT_NONE;
|
||||
s->options_list[OPT_LAMP_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->options_list[OPT_LAMP_TIMEOUT].constraint.range = &lamp_range;
|
||||
s->value[OPT_LAMP_TIMEOUT].w = 15;
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
||||
{
|
||||
SANE_Status status;
|
||||
SM3840_Device *dev;
|
||||
SM3840_Scan *s;
|
||||
DBG (2, "sane_open\n");
|
||||
|
||||
/* Make sure we have first_dev */
|
||||
sane_get_devices (NULL, 0);
|
||||
if (devicename[0])
|
||||
{
|
||||
for (dev = first_dev; dev; dev = dev->next)
|
||||
if (strcmp (dev->sane.name, devicename) == 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* empty devicename -> use first device */
|
||||
dev = first_dev;
|
||||
}
|
||||
DBG (2, "using device: %s %p\n", dev->sane.name, (unsigned char *)dev);
|
||||
if (!dev)
|
||||
return SANE_STATUS_INVAL;
|
||||
s = calloc (sizeof (*s), 1);
|
||||
if (!s)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
status = sanei_usb_open (dev->sane.name, &(s->udev));
|
||||
|
||||
initialize_options_list (s);
|
||||
s->scanning = 0;
|
||||
/* insert newly opened handle into list of open handles: */
|
||||
s->next = first_handle;
|
||||
first_handle = s;
|
||||
*handle = s;
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
|
||||
{
|
||||
SM3840_Scan *s = handle;
|
||||
DBG (2, "sane_set_io_mode( %p, %d )\n", handle, non_blocking);
|
||||
if (s->scanning)
|
||||
{
|
||||
if (non_blocking == SANE_FALSE)
|
||||
return SANE_STATUS_GOOD;
|
||||
else
|
||||
return (SANE_STATUS_UNSUPPORTED);
|
||||
}
|
||||
else
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
SANE_Status
|
||||
sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
|
||||
{
|
||||
DBG (2, "sane_get_select_fd( %p, %p )\n", (void *) handle, (void *) fd);
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# usb vendor product
|
||||
# Microtek ScanMaker 3840 ID
|
||||
usb 0x05da 0x30d4
|
|
@ -0,0 +1,123 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
ScanMaker 3840 Backend
|
||||
Copyright (C) 2005 Earle F. Philhower, III
|
||||
earle@ziplabel.com - http://www.ziplabel.com
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
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.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef sm3840_h
|
||||
#define sm3840_h
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sane/sane.h>
|
||||
|
||||
|
||||
typedef enum SM3840_Option
|
||||
{
|
||||
OPT_NUM_OPTS = 0,
|
||||
OPT_MODE,
|
||||
OPT_RESOLUTION,
|
||||
OPT_BIT_DEPTH,
|
||||
|
||||
OPT_TL_X, /* top-left x */
|
||||
OPT_TL_Y, /* top-left y */
|
||||
OPT_BR_X, /* bottom-right x */
|
||||
OPT_BR_Y, /* bottom-right y */
|
||||
|
||||
OPT_BRIGHTNESS,
|
||||
OPT_CONTRAST,
|
||||
|
||||
OPT_LAMP_TIMEOUT,
|
||||
|
||||
/* must come last */
|
||||
NUM_OPTIONS
|
||||
} SM3840_Option;
|
||||
|
||||
#include "sm3840_params.h"
|
||||
|
||||
|
||||
typedef struct SM3840_Device
|
||||
{
|
||||
struct SM3840_Device *next;
|
||||
SANE_Device sane;
|
||||
} SM3840_Device;
|
||||
|
||||
|
||||
|
||||
typedef struct SM3840_Scan
|
||||
{
|
||||
struct SM3840_Scan *next;
|
||||
SANE_Option_Descriptor options_list[NUM_OPTIONS];
|
||||
Option_Value value[NUM_OPTIONS];
|
||||
|
||||
SANE_Int udev;
|
||||
|
||||
SANE_Bool scanning;
|
||||
SANE_Bool cancelled;
|
||||
SANE_Parameters sane_params;
|
||||
SM3840_Params sm3840_params;
|
||||
|
||||
SANE_Byte *line_buffer; /* One remapped/etc line */
|
||||
size_t remaining; /* How much of line_buffer is still good? */
|
||||
size_t offset; /* Offset in line_buffer where unread data lives */
|
||||
int linesleft; /* How many lines to read from scanner? */
|
||||
int linesread; /* Total lines returned to SANE */
|
||||
|
||||
/* record_line state parameters */
|
||||
int save_i;
|
||||
unsigned char *save_scan_line;
|
||||
unsigned char *save_dpi1200_remap;
|
||||
unsigned char *save_color_remap;
|
||||
|
||||
} SM3840_Scan;
|
||||
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
#define SM3840_CONFIG_FILE "sm3840.conf"
|
||||
|
||||
#define MM_PER_INCH 25.4
|
||||
|
||||
#define SCAN_BUF_SIZE 65536
|
||||
|
||||
#endif /* sm3840_h */
|
|
@ -0,0 +1,996 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
ScanMaker 3840 Backend
|
||||
Copyright (C) 2005 Earle F. Philhower, III
|
||||
earle@ziplabel.com - http://www.ziplabel.com
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
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.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include "sm3840_lib.h"
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
/* For standalone compilation */
|
||||
static void
|
||||
DBG (int ignored, const char *fmt, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start (a, fmt);
|
||||
vfprintf (stderr, fmt, a);
|
||||
va_end (a);
|
||||
}
|
||||
#else
|
||||
/* For SANE compilation, convert libusb to sanei_usb */
|
||||
static int
|
||||
my_usb_bulk_write (usb_dev_handle * dev, int ep,
|
||||
unsigned char *bytes, int size, int timeout)
|
||||
{
|
||||
SANE_Status status;
|
||||
size_t my_size;
|
||||
|
||||
timeout = timeout;
|
||||
ep = ep;
|
||||
my_size = size;
|
||||
status =
|
||||
sanei_usb_write_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
my_size = -1;
|
||||
return my_size;
|
||||
}
|
||||
|
||||
static int
|
||||
my_usb_bulk_read (usb_dev_handle * dev, int ep,
|
||||
unsigned char *bytes, int size, int timeout)
|
||||
{
|
||||
SANE_Status status;
|
||||
size_t my_size;
|
||||
|
||||
timeout = timeout;
|
||||
ep = ep;
|
||||
my_size = size;
|
||||
status =
|
||||
sanei_usb_read_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
my_size = -1;
|
||||
return my_size;
|
||||
}
|
||||
|
||||
static int
|
||||
my_usb_control_msg (usb_dev_handle * dev, int requesttype,
|
||||
int request, int value, int index,
|
||||
unsigned char *bytes, int size, int timeout)
|
||||
{
|
||||
SANE_Status status;
|
||||
|
||||
timeout = timeout;
|
||||
status = sanei_usb_control_msg ((SANE_Int) dev, (SANE_Int) requesttype,
|
||||
(SANE_Int) request, (SANE_Int) value,
|
||||
(SANE_Int) index, (SANE_Int) size,
|
||||
(SANE_Byte *) bytes);
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Sanitize and convert scan parameters from inches to pixels */
|
||||
static void
|
||||
prepare_params (SM3840_Params * params)
|
||||
{
|
||||
if (params->gray)
|
||||
params->gray = 1;
|
||||
if (params->dpi != 1200 && params->dpi != 600 && params->dpi != 300
|
||||
&& params->dpi != 150)
|
||||
params->dpi = 150;
|
||||
if (params->bpp != 8 && params->bpp != 16)
|
||||
params->bpp = 8;
|
||||
|
||||
/* Sanity check input sizes */
|
||||
if (params->top < 0)
|
||||
params->top = 0;
|
||||
if (params->left < 0)
|
||||
params->left = 0;
|
||||
if (params->width < 0)
|
||||
params->width = 0;
|
||||
if (params->height < 0)
|
||||
params->height = 0;
|
||||
if ((params->top + params->height) > 11.7)
|
||||
params->height = 11.7 - params->top;
|
||||
if ((params->left + params->width) > 8.5)
|
||||
params->width = 8.5 - params->left;
|
||||
|
||||
params->topline = params->top * params->dpi;
|
||||
params->scanlines = params->height * params->dpi;
|
||||
params->leftpix = params->left * params->dpi;
|
||||
params->leftpix &= ~1; /* Always start on even pixel boundary for remap */
|
||||
/* Scanpix always a multiple of 128 */
|
||||
params->scanpix = params->width * params->dpi;
|
||||
params->scanpix = (params->scanpix + 127) & ~127;
|
||||
|
||||
/* Sanity check outputs... */
|
||||
if (params->topline < 0)
|
||||
params->topline = 0;
|
||||
if (params->scanlines < 1)
|
||||
params->scanlines = 1;
|
||||
if (params->leftpix < 0)
|
||||
params->leftpix = 0;
|
||||
if (params->scanpix < 128)
|
||||
params->scanpix = 128;
|
||||
|
||||
/* Some handy calculations */
|
||||
params->linelen =
|
||||
params->scanpix * (params->bpp / 8) * (params->gray ? 1 : 3);
|
||||
}
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
usb_dev_handle *
|
||||
find_device (unsigned int idVendor, unsigned int idProduct)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
|
||||
usb_init ();
|
||||
usb_find_busses ();
|
||||
usb_find_devices ();
|
||||
|
||||
for (bus = usb_get_busses (); bus; bus = bus->next)
|
||||
for (dev = bus->devices; dev; dev = dev->next)
|
||||
if (dev->descriptor.idVendor == idVendor &&
|
||||
dev->descriptor.idProduct == idProduct)
|
||||
return usb_open (dev);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
idle_ab (usb_dev_handle * udev)
|
||||
{
|
||||
int len, i;
|
||||
unsigned char buff[8] = { 0x64, 0x65, 0x16, 0x17, 0x64, 0x65, 0x44, 0x45 };
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
len = usb_control_msg (udev, 0x40, 0x0c, 0x0090, 0x0000, buff + i,
|
||||
0x0001, wr_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* CW: 40 04 00b0 0000 <len> : <reg1> <value1> <reg2> <value2> ... */
|
||||
static void
|
||||
write_regs (usb_dev_handle * udev, int regs, unsigned char reg1,
|
||||
unsigned char val1,
|
||||
... /*unsigned char reg, unsigned char val, ... */ )
|
||||
{
|
||||
unsigned char buff[512];
|
||||
va_list marker;
|
||||
int len, i;
|
||||
|
||||
va_start (marker, val1);
|
||||
buff[0] = reg1;
|
||||
buff[1] = val1;
|
||||
for (i = 1; i < regs; i++)
|
||||
{
|
||||
buff[i * 2] = va_arg (marker, int);
|
||||
buff[i * 2 + 1] = va_arg (marker, int);
|
||||
}
|
||||
va_end (marker);
|
||||
|
||||
len = usb_control_msg (udev, 0x40, 0x04, 0x00b0, 0x0000, buff,
|
||||
regs * 2, wr_timeout);
|
||||
}
|
||||
|
||||
static int
|
||||
write_vctl (usb_dev_handle * udev, int request, int value,
|
||||
int index, unsigned char byte)
|
||||
{
|
||||
return usb_control_msg (udev, 0x40, request, value, index,
|
||||
&byte, 1, wr_timeout);
|
||||
}
|
||||
|
||||
static int
|
||||
read_vctl (usb_dev_handle * udev, int request, int value,
|
||||
int index, unsigned char *byte)
|
||||
{
|
||||
return usb_control_msg (udev, 0xc0, request, value, index,
|
||||
byte, 1, wr_timeout);
|
||||
}
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
/* Copy from a USB data pipe to a file with optional header */
|
||||
static void
|
||||
record_head (usb_dev_handle * udev, char *fname, int bytes, char *header)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char buff[65536];
|
||||
int len;
|
||||
int toread;
|
||||
|
||||
fp = fopen (fname, "wb");
|
||||
if (header)
|
||||
fprintf (fp, "%s", header);
|
||||
do
|
||||
{
|
||||
toread = (bytes > 65536) ? 65536 : bytes;
|
||||
len = usb_bulk_read (udev, 1, buff, toread, rd_timeout);
|
||||
if (len > 0)
|
||||
{
|
||||
fwrite (buff, len, 1, fp);
|
||||
bytes -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG (2, "TIMEOUT\n");
|
||||
}
|
||||
}
|
||||
while (bytes);
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
/* Copy from a USB data pipe to a file without header */
|
||||
static void
|
||||
record (usb_dev_handle * udev, char *fname, int bytes)
|
||||
{
|
||||
record_head (udev, fname, bytes, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
max (int a, int b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
|
||||
#define DPI1200SHUFFLE 6
|
||||
static void
|
||||
record_line (int reset,
|
||||
usb_dev_handle * udev,
|
||||
unsigned char *storeline,
|
||||
int dpi, int scanpix, int gray, int bpp16,
|
||||
int *save_i,
|
||||
unsigned char **save_scan_line,
|
||||
unsigned char **save_dpi1200_remap,
|
||||
unsigned char **save_color_remap)
|
||||
{
|
||||
int len;
|
||||
unsigned char *scan_line, *dpi1200_remap;
|
||||
unsigned char *color_remap;
|
||||
int i;
|
||||
int red_delay, blue_delay, green_delay;
|
||||
int j;
|
||||
int linelen;
|
||||
int pixsize;
|
||||
unsigned char *ptrcur, *ptrprev;
|
||||
unsigned char *savestoreline;
|
||||
int lineptr, outline, bufflines;
|
||||
|
||||
i = *save_i;
|
||||
scan_line = *save_scan_line;
|
||||
dpi1200_remap = *save_dpi1200_remap;
|
||||
color_remap = *save_color_remap;
|
||||
|
||||
pixsize = (gray ? 1 : 3) * (bpp16 ? 2 : 1);
|
||||
linelen = scanpix * pixsize;
|
||||
|
||||
if (gray)
|
||||
{
|
||||
red_delay = 0;
|
||||
blue_delay = 0;
|
||||
green_delay = 0;
|
||||
}
|
||||
else if (dpi == 150)
|
||||
{
|
||||
red_delay = 0;
|
||||
blue_delay = 6;
|
||||
green_delay = 3;
|
||||
}
|
||||
else if (dpi == 300)
|
||||
{
|
||||
red_delay = 0;
|
||||
blue_delay = 12;
|
||||
green_delay = 6;
|
||||
}
|
||||
else if (dpi == 600)
|
||||
{
|
||||
red_delay = 0;
|
||||
blue_delay = 24;
|
||||
green_delay = 12;
|
||||
}
|
||||
else /*(dpi==1200) */
|
||||
{
|
||||
red_delay = 0;
|
||||
blue_delay = 48;
|
||||
green_delay = 24;
|
||||
}
|
||||
|
||||
bufflines = max (max (red_delay, blue_delay), green_delay) + 1;
|
||||
|
||||
if (reset)
|
||||
{
|
||||
if (dpi1200_remap)
|
||||
free (dpi1200_remap);
|
||||
if (scan_line)
|
||||
free (scan_line);
|
||||
if (color_remap)
|
||||
free (color_remap);
|
||||
|
||||
*save_color_remap = color_remap =
|
||||
(unsigned char *) malloc (bufflines * linelen);
|
||||
|
||||
*save_scan_line = scan_line = (unsigned char *) calloc (linelen, 1);
|
||||
if (dpi == 1200)
|
||||
*save_dpi1200_remap = dpi1200_remap =
|
||||
(unsigned char *) calloc (linelen, DPI1200SHUFFLE);
|
||||
else
|
||||
*save_dpi1200_remap = dpi1200_remap = NULL;
|
||||
|
||||
*save_i = i = 0; /* i is our linenumber */
|
||||
}
|
||||
|
||||
while (1)
|
||||
{ /* We'll exit inside the loop... */
|
||||
len = usb_bulk_read (udev, 1, scan_line, linelen, rd_timeout);
|
||||
if (dpi == 1200)
|
||||
{
|
||||
ptrcur = dpi1200_remap + (linelen * (i % DPI1200SHUFFLE));
|
||||
ptrprev =
|
||||
dpi1200_remap +
|
||||
(linelen * ((i - (DPI1200SHUFFLE - 2)) % DPI1200SHUFFLE));
|
||||
}
|
||||
else
|
||||
{
|
||||
ptrcur = scan_line;
|
||||
ptrprev = NULL;
|
||||
}
|
||||
if (gray)
|
||||
{
|
||||
memcpy (ptrcur, scan_line, linelen);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pixsize = bpp16 ? 2 : 1;
|
||||
int pix = linelen / (3 * pixsize);
|
||||
unsigned char *outbuff = ptrcur;
|
||||
|
||||
outline = i;
|
||||
lineptr = i % bufflines;
|
||||
|
||||
memcpy (color_remap + linelen * lineptr, scan_line, linelen);
|
||||
|
||||
outline++;
|
||||
if (outline > bufflines)
|
||||
{
|
||||
int redline = (outline + red_delay) % bufflines;
|
||||
int greenline = (outline + green_delay) % bufflines;
|
||||
int blueline = (outline + blue_delay) % bufflines;
|
||||
unsigned char *rp, *gp, *bp;
|
||||
|
||||
rp = color_remap + linelen * redline;
|
||||
gp = color_remap + linelen * greenline + 1 * pixsize;
|
||||
bp = color_remap + linelen * blueline + 2 * pixsize;
|
||||
|
||||
for (j = 0; j < pix; j++)
|
||||
{
|
||||
if (outbuff)
|
||||
{
|
||||
*(outbuff++) = *rp;
|
||||
if (pixsize == 2)
|
||||
*(outbuff++) = *(rp + 1);
|
||||
*(outbuff++) = *gp;
|
||||
if (pixsize == 2)
|
||||
*(outbuff++) = *(gp + 1);
|
||||
*(outbuff++) = *bp;
|
||||
if (pixsize == 2)
|
||||
*(outbuff++) = *(bp + 1);
|
||||
}
|
||||
rp += 3 * pixsize;
|
||||
gp += 3 * pixsize;
|
||||
bp += 3 * pixsize;
|
||||
}
|
||||
}
|
||||
lineptr = (lineptr + 1) % bufflines;
|
||||
}
|
||||
|
||||
if (dpi != 1200)
|
||||
{
|
||||
if (i > blue_delay)
|
||||
{
|
||||
savestoreline = storeline;
|
||||
for (j = 0; j < scanpix; j++)
|
||||
{
|
||||
memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize,
|
||||
pixsize);
|
||||
storeline += pixsize;
|
||||
}
|
||||
if (dpi == 150)
|
||||
{
|
||||
/* 150 DPI skips every 4th returned line */
|
||||
if (i % 4)
|
||||
{
|
||||
i++;
|
||||
*save_i = i;
|
||||
if (bpp16)
|
||||
fix_endian_short ((unsigned short *) storeline,
|
||||
scanpix);
|
||||
return;
|
||||
}
|
||||
storeline = savestoreline;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
*save_i = i;
|
||||
if (bpp16)
|
||||
fix_endian_short ((unsigned short *) storeline, scanpix);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* dpi==1200 */
|
||||
{
|
||||
if (i > (DPI1200SHUFFLE + blue_delay))
|
||||
{
|
||||
for (j = 0; j < scanpix; j++)
|
||||
{
|
||||
if (1 == (j & 1))
|
||||
memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize,
|
||||
pixsize);
|
||||
else
|
||||
memcpy (storeline, ptrprev + linelen - (j + 1) * pixsize,
|
||||
pixsize);
|
||||
storeline += pixsize;
|
||||
} /* end for */
|
||||
i++;
|
||||
*save_i = i;
|
||||
if (bpp16)
|
||||
fix_endian_short ((unsigned short *) storeline, scanpix);
|
||||
return;
|
||||
} /* end if >dpi1200shuffle */
|
||||
} /* end if dpi1200 */
|
||||
i++;
|
||||
} /* end for */
|
||||
}
|
||||
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
/* Record an image to a file with remapping/reordering/etc. */
|
||||
void
|
||||
record_image (usb_dev_handle * udev, char *fname, int dpi,
|
||||
int scanpix, int scanlines, int gray, char *head, int bpp16)
|
||||
{
|
||||
FILE *fp;
|
||||
int i;
|
||||
int save_i;
|
||||
unsigned char *save_scan_line;
|
||||
unsigned char *save_dpi1200_remap;
|
||||
unsigned char *save_color_remap;
|
||||
unsigned char *storeline;
|
||||
|
||||
save_i = 0;
|
||||
save_scan_line = save_dpi1200_remap = save_color_remap = NULL;
|
||||
storeline =
|
||||
(unsigned char *) malloc (scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1));
|
||||
|
||||
fp = fopen (fname, "wb");
|
||||
if (head)
|
||||
fprintf (fp, "%s", head);
|
||||
|
||||
for (i = 0; i < scanlines; i++)
|
||||
{
|
||||
record_line ((i == 0) ? 1 : 0, udev, storeline, dpi, scanpix, gray,
|
||||
bpp16, &save_i, &save_scan_line, &save_dpi1200_remap,
|
||||
&save_color_remap);
|
||||
fwrite (storeline, scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1), 1, fp);
|
||||
}
|
||||
fclose (fp);
|
||||
if (save_scan_line)
|
||||
free (save_scan_line);
|
||||
if (save_dpi1200_remap)
|
||||
free (save_dpi1200_remap);
|
||||
if (save_color_remap)
|
||||
free (save_color_remap);
|
||||
free (storeline);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
record_mem (usb_dev_handle * udev, unsigned char **dest, int bytes)
|
||||
{
|
||||
unsigned char *mem;
|
||||
unsigned char buff[65536];
|
||||
int len;
|
||||
|
||||
mem = (unsigned char *) malloc (bytes);
|
||||
*dest = mem;
|
||||
do
|
||||
{
|
||||
len =
|
||||
usb_bulk_read (udev, 1, buff, bytes > 65536 ? 65536 : bytes,
|
||||
rd_timeout);
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy (mem, buff, len);
|
||||
bytes -= len;
|
||||
mem += len;
|
||||
}
|
||||
}
|
||||
while (bytes);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
reset_scanner (usb_dev_handle * udev)
|
||||
{
|
||||
unsigned char rd_byte;
|
||||
|
||||
DBG (2, "+reset_scanner\n");
|
||||
write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff,
|
||||
0xa2, 0xff);
|
||||
write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
|
||||
write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00,
|
||||
0x88, 0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00,
|
||||
0xc2, 0x00, 0xc3, 0x00, 0xc4, 0x00, 0xc5, 0x00,
|
||||
0xc6, 0x00, 0xc7, 0x00, 0xc8, 0x00, 0xc0, 0x00);
|
||||
write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f,
|
||||
0xcf, 0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06,
|
||||
0xc4, 0xff, 0xc5, 0x40, 0xc6, 0x8c, 0xc7, 0xdc,
|
||||
0xc8, 0x20, 0xc0, 0x72, 0x89, 0xff, 0x86, 0xff);
|
||||
write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82,
|
||||
0x85, 0xaf, 0x83, 0x00, 0x93, 0x00);
|
||||
write_regs (udev, 3, 0xa8, 0x0a, 0x8c, 0x08, 0x94, 0x00);
|
||||
write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0b);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0f);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x05);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
DBG (2, "-reset_scanner\n");
|
||||
}
|
||||
|
||||
static void
|
||||
poll1 (usb_dev_handle * udev)
|
||||
{
|
||||
unsigned char rd_byte;
|
||||
DBG (2, "+poll1\n");
|
||||
do
|
||||
{
|
||||
write_regs (udev, 1, 0x97, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
}
|
||||
while (0 == (rd_byte & 0x40));
|
||||
DBG (2, "-poll1\n");
|
||||
}
|
||||
|
||||
static void
|
||||
poll2 (usb_dev_handle * udev)
|
||||
{
|
||||
unsigned char rd_byte;
|
||||
DBG (2, "+poll2\n");
|
||||
do
|
||||
{
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
}
|
||||
while (0 == (rd_byte & 0x02));
|
||||
DBG (2, "-poll2\n");
|
||||
}
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
static void
|
||||
check_buttons (usb_dev_handle * udev, int *scan, int *print, int *mail)
|
||||
{
|
||||
unsigned char rd_byte;
|
||||
|
||||
write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
if (scan)
|
||||
{
|
||||
if (0 == (rd_byte & 1))
|
||||
*scan = 1;
|
||||
else
|
||||
*scan = 0;
|
||||
}
|
||||
if (print)
|
||||
{
|
||||
if (0 == (rd_byte & 2))
|
||||
*print = 1;
|
||||
else
|
||||
*print = 0;
|
||||
}
|
||||
if (mail)
|
||||
{
|
||||
if (0 == (rd_byte & 4))
|
||||
*mail = 1;
|
||||
else
|
||||
*mail = 0;
|
||||
}
|
||||
write_regs (udev, 1, 0x97, 0x0b);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 1, 0x97, 0x0f);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 1, 0x97, 0x05);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
idle_ab (udev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
lut (int val, double gain, int offset)
|
||||
{
|
||||
/* int offset = 1800; */
|
||||
/* double exponent = 3.5; */
|
||||
return (offset + 8192.0 * (pow ((8192.0 - val) / 8192.0, gain)));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calc_lightmap (unsigned short *buff,
|
||||
unsigned short *storage, int index, int dpi,
|
||||
double gain, int offset)
|
||||
{
|
||||
int val, line;
|
||||
int px = 5632;
|
||||
int i;
|
||||
|
||||
line = px * 3;
|
||||
|
||||
for (i = 0; i < px; i++)
|
||||
{
|
||||
if ((i >= 2) && (i <= (px - 2)))
|
||||
{
|
||||
val = 0;
|
||||
val += 1 * buff[i * 3 + index - 3 * 2];
|
||||
val += 3 * buff[i * 3 + index - 3 * 1];
|
||||
val += 5 * buff[i * 3 + index + 3 * 0];
|
||||
val += 3 * buff[i * 3 + index + 3 * 1];
|
||||
val += 1 * buff[i * 3 + index + 3 * 2];
|
||||
val += 2 * buff[i * 3 + index - 3 * 1 + line];
|
||||
val += 3 * buff[i * 3 + index + 3 * 0 + line];
|
||||
val += 2 * buff[i * 3 + index + 3 * 1 + line];
|
||||
val += 1 * buff[i * 3 + index + 3 * 0 + 2 * line];
|
||||
val /= 21;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = 1 * buff[i * 3 + index];
|
||||
}
|
||||
|
||||
val = val >> 3;
|
||||
if (val > 8191)
|
||||
val = 8191;
|
||||
val = lut (val, gain, offset);
|
||||
|
||||
if (val > 8191)
|
||||
val = 8191;
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
storage[i * (dpi == 1200 ? 2 : 1)] = val;
|
||||
if (dpi == 1200)
|
||||
storage[i * 2 + 1] = val;
|
||||
}
|
||||
|
||||
fix_endian_short (storage, (dpi == 1200) ? i * 2 : i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*#define VALMAP 0x1fff */
|
||||
/*#define SCANMAP 0x2000*/
|
||||
#define RAWPIXELS600 7320
|
||||
#define RAWPIXELS1200 14640
|
||||
|
||||
static void
|
||||
select_pixels (unsigned short *map, int dpi, int start, int end)
|
||||
{
|
||||
int i;
|
||||
int skip, offset;
|
||||
unsigned short VALMAP = 0x1fff;
|
||||
unsigned short SCANMAP = 0x2000;
|
||||
|
||||
fix_endian_short (&VALMAP, 1);
|
||||
fix_endian_short (&SCANMAP, 1);
|
||||
|
||||
/* Clear the pixel-on flags for all bits */
|
||||
for (i = 0; i < ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600); i++)
|
||||
map[i] &= VALMAP;
|
||||
|
||||
/* 300 and 150 have subsampling */
|
||||
if (dpi == 300)
|
||||
skip = -2;
|
||||
else if (dpi == 150)
|
||||
skip = -4;
|
||||
else
|
||||
skip = -1;
|
||||
|
||||
/* 1200 has 2x pixels so start at 2x the offset */
|
||||
if (dpi == 1200)
|
||||
offset = 234 + (8.5 * 1200);
|
||||
else
|
||||
offset = 117 + (8.5 * 600);
|
||||
|
||||
if (0 == (offset & 1))
|
||||
offset++;
|
||||
|
||||
DBG (2, "offset=%d start=%d skip=%d\n", offset, start, skip);
|
||||
|
||||
for (i = 0; i < end; i++)
|
||||
{
|
||||
int x;
|
||||
x = offset + (start * skip) + (i * skip);
|
||||
if (x < 0 || x > ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600))
|
||||
DBG (2, "ERR %d\n", x);
|
||||
else
|
||||
map[x] |= SCANMAP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_lightmap_white (unsigned short *map, int dpi, int color)
|
||||
{
|
||||
int i;
|
||||
unsigned short VALMAP = 0x1fff;
|
||||
unsigned short SCANMAP = 0x2000;
|
||||
|
||||
fix_endian_short (&VALMAP, 1);
|
||||
fix_endian_short (&SCANMAP, 1);
|
||||
|
||||
if (dpi != 1200)
|
||||
{
|
||||
memset (map, 0, RAWPIXELS600 * 2);
|
||||
if (color != 0)
|
||||
return; /* Only 1st has enables... */
|
||||
for (i = 0; i < 22; i++)
|
||||
map[7 + i] = SCANMAP; /* Get some black... */
|
||||
for (i = 0; i < 1024; i++)
|
||||
map[2048 + i] = SCANMAP; /* And some white... */
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (map, 0, RAWPIXELS1200 * 2);
|
||||
if (color != 0)
|
||||
return;
|
||||
for (i = 16; i < 61; i++)
|
||||
map[i] = SCANMAP;
|
||||
for (i = 4076; i < 6145; i++)
|
||||
map[i] = SCANMAP;
|
||||
/* 3rd is all clear */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_lamp_timer (usb_dev_handle * udev, int timeout_in_mins)
|
||||
{
|
||||
write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82,
|
||||
0x85, 0xaf, 0x83, 0x00, 0x93, 0x00);
|
||||
write_regs (udev, 3, 0xa8, timeout_in_mins * 2, 0x8c, 0x08, 0x94, 0x00);
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0x26, 0x83, 0x00, 0x8d, 0xff);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_lut8 (double *poly, int skip, unsigned char *dest)
|
||||
{
|
||||
int i;
|
||||
double sum, x;
|
||||
if (!poly || !dest)
|
||||
return;
|
||||
for (i = 0; i < 8192; i += skip)
|
||||
{
|
||||
sum = poly[0];
|
||||
x = (double) i;
|
||||
sum += poly[1] * x;
|
||||
x = x * i;
|
||||
sum += poly[2] * x;
|
||||
x = x * i;
|
||||
sum += poly[3] * x;
|
||||
x = x * i;
|
||||
sum += poly[4] * x;
|
||||
x = x * i;
|
||||
sum += poly[5] * x;
|
||||
x = x * i;
|
||||
sum += poly[6] * x;
|
||||
x = x * i;
|
||||
sum += poly[7] * x;
|
||||
x = x * i;
|
||||
sum += poly[8] * x;
|
||||
x = x * i;
|
||||
sum += poly[9] * x;
|
||||
x = x * i;
|
||||
if (sum < 0)
|
||||
sum = 0;
|
||||
if (sum > 255)
|
||||
sum = 255;
|
||||
*dest = (unsigned char) sum;
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
download_lut8 (usb_dev_handle * udev, int dpi, int incolor)
|
||||
{
|
||||
double color[10] = { 0.0, 1.84615261590892E-01, -2.19613868292657E-04,
|
||||
1.79549523214101E-07, -8.69378513113239E-11,
|
||||
2.56694911984996E-14, -4.67288886157239E-18,
|
||||
5.11622894146250E-22, -3.08729724411991E-26,
|
||||
7.88581670873938E-31
|
||||
};
|
||||
double gray[10] = { 0.0, 1.73089945056694E-01, -1.39794924306080E-04,
|
||||
9.70266873814926E-08, -4.57503008236968E-11,
|
||||
1.37092321631794E-14, -2.54395068387198E-18,
|
||||
2.82432084125966E-22, -1.71787408822688E-26,
|
||||
4.40306800664567E-31
|
||||
};
|
||||
unsigned char *lut;
|
||||
int len;
|
||||
|
||||
DBG (2, "+download_lut8\n");
|
||||
switch (dpi)
|
||||
{
|
||||
case 150:
|
||||
case 300:
|
||||
case 600:
|
||||
lut = (unsigned char *) malloc (4096);
|
||||
if (!lut)
|
||||
return;
|
||||
|
||||
if (!incolor)
|
||||
{
|
||||
calculate_lut8 (gray, 2, lut);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff,
|
||||
0xb4, 0x2f, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
calculate_lut8 (color, 2, lut);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x10, 0xb2, 0x07, 0xb3, 0xff,
|
||||
0xb4, 0x1f, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff,
|
||||
0xb4, 0x2f, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x30, 0xb2, 0x07, 0xb3, 0xff,
|
||||
0xb4, 0x3f, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1200:
|
||||
default:
|
||||
lut = (unsigned char *) malloc (8192);
|
||||
if (!lut)
|
||||
return;
|
||||
|
||||
if (!incolor)
|
||||
{
|
||||
calculate_lut8 (gray, 1, lut);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff,
|
||||
0xb4, 0x5f, 0xb5, 0x06);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
calculate_lut8 (color, 1, lut);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x06, 0xb3, 0xff,
|
||||
0xb4, 0x3f, 0xb5, 0x06);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff,
|
||||
0xb4, 0x5f, 0xb5, 0x06);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x60, 0xb2, 0x06, 0xb3, 0xff,
|
||||
0xb4, 0x7f, 0xb5, 0x06);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
|
||||
len = usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
free (lut);
|
||||
DBG (2, "-download_lut8\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_gain_black (usb_dev_handle * udev,
|
||||
int r_gain, int g_gain, int b_gain,
|
||||
int r_black, int g_black, int b_black)
|
||||
{
|
||||
write_regs (udev, 1, 0x80, 0x00);
|
||||
write_regs (udev, 1, 0x80, 0x01);
|
||||
write_regs (udev, 1, 0x04, 0x80);
|
||||
write_regs (udev, 1, 0x04, 0x00);
|
||||
write_regs (udev, 1, 0x00, 0x00);
|
||||
write_regs (udev, 1, 0x01, 0x03);
|
||||
write_regs (udev, 1, 0x02, 0x04);
|
||||
write_regs (udev, 1, 0x03, 0x11);
|
||||
write_regs (udev, 1, 0x05, 0x00);
|
||||
write_regs (udev, 1, 0x28, r_gain);
|
||||
write_regs (udev, 1, 0x29, g_gain);
|
||||
write_regs (udev, 1, 0x2a, b_gain);
|
||||
write_regs (udev, 1, 0x20, r_black);
|
||||
write_regs (udev, 1, 0x21, g_black);
|
||||
write_regs (udev, 1, 0x22, b_black);
|
||||
write_regs (udev, 1, 0x24, 0x00);
|
||||
write_regs (udev, 1, 0x25, 0x00);
|
||||
write_regs (udev, 1, 0x26, 0x00);
|
||||
}
|
||||
|
||||
/* Handle short endianness issues */
|
||||
static void
|
||||
fix_endian_short (unsigned short *data, int count)
|
||||
{
|
||||
unsigned short testvalue = 255;
|
||||
unsigned char *firstbyte = (unsigned char *) &testvalue;
|
||||
int i;
|
||||
|
||||
if (*firstbyte == 255)
|
||||
return; /* INTC endianness */
|
||||
|
||||
DBG (2, "swapping endiannes...\n");
|
||||
for (i = 0; i < count; i++)
|
||||
data[i] = ((data[i] >> 8) & 0x00ff) | ((data[i] << 8) & 0xff00);
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
ScanMaker 3840 Backend
|
||||
Copyright (C) 2005 Earle F. Philhower, III
|
||||
earle@ziplabel.com - http://www.ziplabel.com
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
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.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
#include <usb.h>
|
||||
static usb_dev_handle *find_device (unsigned int idVendor,
|
||||
unsigned int idProduct);
|
||||
|
||||
#else
|
||||
#include "../include/sane/sanei_usb.h"
|
||||
|
||||
#ifndef USBWRAPPER
|
||||
#define USBWRAPPER
|
||||
|
||||
#define usb_dev_handle SANE_Int
|
||||
#define usb_control_msg my_usb_control_msg
|
||||
#define usb_bulk_read my_usb_bulk_read
|
||||
#define usb_bulk_write my_usb_bulk_write
|
||||
static int my_usb_bulk_write (usb_dev_handle * dev, int ep,
|
||||
unsigned char *bytes,
|
||||
int size, int timeout);
|
||||
static int my_usb_bulk_read (usb_dev_handle * dev, int ep,
|
||||
unsigned char *bytes,
|
||||
int size, int timeout);
|
||||
static int my_usb_control_msg (usb_dev_handle * dev, int requesttype,
|
||||
int request, int value, int index,
|
||||
unsigned char *bytes,
|
||||
int size, int timeout);
|
||||
#endif /* USBWRAPPER */
|
||||
|
||||
#endif
|
||||
|
||||
#include "sm3840_params.h"
|
||||
|
||||
static void idle_ab (usb_dev_handle * udev);
|
||||
static void write_regs (usb_dev_handle * udev, int regs, unsigned char reg1,
|
||||
unsigned char val1,
|
||||
... /*unsigned char reg, unsigned char val, ... */ );
|
||||
static int write_vctl (usb_dev_handle * udev, int request, int value,
|
||||
int index, unsigned char byte);
|
||||
static int read_vctl (usb_dev_handle * udev, int request, int value,
|
||||
int index, unsigned char *byte);
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
static void record (usb_dev_handle * udev, char *fname, int bytes);
|
||||
static void record_image (usb_dev_handle * udev, char *fname, int dpi,
|
||||
int scanpix, int scanlines, int gray, char *head,
|
||||
int bpp16);
|
||||
static void check_buttons (usb_dev_handle * udev, int *scan, int *print,
|
||||
int *mail);
|
||||
static void record_head (usb_dev_handle * udev, char *fname, int bytes,
|
||||
char *header);
|
||||
#endif
|
||||
|
||||
static void poll1 (usb_dev_handle * udev);
|
||||
static void poll2 (usb_dev_handle * udev);
|
||||
|
||||
static void reset_scanner (usb_dev_handle * udev);
|
||||
|
||||
|
||||
static void set_lightmap_white (unsigned short *map, int dpi, int color);
|
||||
|
||||
static void calc_lightmap (unsigned short *buff,
|
||||
unsigned short *storage, int index, int dpi,
|
||||
double gain, int offset);
|
||||
static void select_pixels (unsigned short *map, int dpi, int start, int end);
|
||||
|
||||
static void record_mem (usb_dev_handle * udev, unsigned char **dest,
|
||||
int bytes);
|
||||
static void set_lamp_timer (usb_dev_handle * udev, int timeout_in_mins);
|
||||
|
||||
static void set_gain_black (usb_dev_handle * udev,
|
||||
int r_gain, int g_gain, int b_gain,
|
||||
int r_black, int g_black, int b_black);
|
||||
|
||||
static void idle_ab (usb_dev_handle * udev);
|
||||
static void write_regs (usb_dev_handle * udev, int regs, unsigned char reg1,
|
||||
unsigned char val1,
|
||||
... /*unsigned char reg, unsigned char val, ... */ );
|
||||
static int write_vctl (usb_dev_handle * udev, int request, int value,
|
||||
int index, unsigned char byte);
|
||||
static int read_vctl (usb_dev_handle * udev, int request, int value,
|
||||
int index, unsigned char *byte);
|
||||
|
||||
static void download_lut8 (usb_dev_handle * udev, int dpi, int incolor);
|
||||
|
||||
static void record_line (int reset,
|
||||
usb_dev_handle * udev,
|
||||
unsigned char *storeline,
|
||||
int dpi, int scanpix, int gray, int bpp16,
|
||||
int *save_i,
|
||||
unsigned char **save_scan_line,
|
||||
unsigned char **save_dpi1200_remap,
|
||||
unsigned char **save_color_remap);
|
||||
|
||||
|
||||
static void prepare_params (SM3840_Params * params);
|
||||
|
||||
static void fix_endian_short (unsigned short *data, int count);
|
||||
|
||||
#define rd_timeout 10000
|
||||
#define wr_timeout 10000
|
|
@ -0,0 +1,69 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
ScanMaker 3840 Backend
|
||||
Copyright (C) 2005 Earle F. Philhower, III
|
||||
earle@ziplabel.com - http://www.ziplabel.com
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
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.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SM3840_Params
|
||||
#define _SM3840_Params
|
||||
typedef struct SM3840_Params
|
||||
{
|
||||
int gray; /* 0, 1 */
|
||||
int dpi; /* 150, 300, 600, 1200 */
|
||||
int bpp; /* 8, 16 */
|
||||
|
||||
double gain; /* 0.01...9.9 */
|
||||
int offset; /* 0..4095 */
|
||||
|
||||
int lamp; /* 1..15 mins */
|
||||
|
||||
/* Input to configure(), in inches */
|
||||
double top, left;
|
||||
double width, height;
|
||||
|
||||
/* Output from configure(), in pixels */
|
||||
int topline;
|
||||
int scanlines;
|
||||
int leftpix;
|
||||
int scanpix;
|
||||
int linelen; /* bytes per line */
|
||||
} SM3840_Params;
|
||||
#endif
|
|
@ -0,0 +1,938 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
ScanMaker 3840 Backend
|
||||
Copyright (C) 2005 Earle F. Philhower, III
|
||||
earle@ziplabel.com - http://www.ziplabel.com
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
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.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "sm3840_lib.h"
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
static void setup_scan (usb_dev_handle * udev, SM3840_Params * p,
|
||||
char *stname, int raw, int nohead);
|
||||
#else
|
||||
static void setup_scan (usb_dev_handle * udev, SM3840_Params * p);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
|
||||
#include "sm3840_lib.c"
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
int gray = 0;
|
||||
int dpi = 1200;
|
||||
int bpp16 = 0;
|
||||
int raw = 0;
|
||||
int nohead = 0;
|
||||
double gain = 3.5;
|
||||
int offset = 1800;
|
||||
usb_dev_handle *udev;
|
||||
|
||||
char *stname;
|
||||
double topin, botin, leftin, rightin;
|
||||
int topline, scanlines, leftpix, scanpix;
|
||||
|
||||
stname = NULL;
|
||||
topin = 0.0;
|
||||
botin = 11.7;
|
||||
leftin = 0.0;
|
||||
rightin = 8.5;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp (argv[i], "-300"))
|
||||
dpi = 300;
|
||||
else if (!strcmp (argv[i], "-600"))
|
||||
dpi = 600;
|
||||
else if (!strcmp (argv[i], "-1200"))
|
||||
dpi = 1200;
|
||||
else if (!strcmp (argv[i], "-150"))
|
||||
dpi = 150;
|
||||
else if (!strcmp (argv[i], "-top"))
|
||||
topin = atof (argv[++i]);
|
||||
else if (!strcmp (argv[i], "-bot"))
|
||||
botin = atof (argv[++i]);
|
||||
else if (!strcmp (argv[i], "-left"))
|
||||
leftin = atof (argv[++i]);
|
||||
else if (!strcmp (argv[i], "-right"))
|
||||
rightin = atof (argv[++i]);
|
||||
else if (!strcmp (argv[i], "-gain"))
|
||||
gain = atof (argv[++i]);
|
||||
else if (!strcmp (argv[i], "-offset"))
|
||||
offset = atoi (argv[++i]);
|
||||
else if (!strcmp (argv[i], "-gray"))
|
||||
gray = 1;
|
||||
else if (!strcmp (argv[i], "-16bpp"))
|
||||
bpp16 = 1;
|
||||
else if (!strcmp (argv[i], "-raw"))
|
||||
raw = 1;
|
||||
else if (!strcmp (argv[i], "-nohead"))
|
||||
nohead = 1;
|
||||
else
|
||||
stname = argv[i];
|
||||
}
|
||||
|
||||
SM3840_Params params;
|
||||
params.gray = gray;
|
||||
params.dpi = dpi;
|
||||
params.bpp = bpp16 ? 16 : 8;
|
||||
params.gain = gain;
|
||||
params.offset = offset;
|
||||
params.lamp = 15;
|
||||
params.top = topin;
|
||||
params.left = leftin;
|
||||
params.height = botin - topin;
|
||||
params.width = rightin - leftin;
|
||||
|
||||
prepare_params (¶ms);
|
||||
udev = find_device (0x05da, 0x30d4);
|
||||
if (!udev)
|
||||
fprintf (stderr, "Unable to open scanner.\n");
|
||||
else
|
||||
setup_scan (udev, ¶ms, stname, raw, nohead);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
static void
|
||||
setup_scan (usb_dev_handle * udev, SM3840_Params * p,
|
||||
char *stname, int raw, int nohead)
|
||||
#else
|
||||
static void
|
||||
setup_scan (usb_dev_handle * udev, SM3840_Params * p)
|
||||
#endif
|
||||
{
|
||||
int gray = p->gray ? 1 : 0;
|
||||
int dpi = p->dpi;
|
||||
int bpp16 = (p->bpp == 16) ? 1 : 0;
|
||||
double gain = p->gain;
|
||||
int offset = p->offset;
|
||||
int topline = p->topline;
|
||||
int scanlines = p->scanlines;
|
||||
int leftpix = p->leftpix;
|
||||
int scanpix = p->scanpix;
|
||||
int len;
|
||||
unsigned char hello[2] = { 0x55, 0xaa };
|
||||
unsigned char howdy[3];
|
||||
unsigned short *whitebalance;
|
||||
int whitebalancesize = (dpi == 1200) ? 12672 : 6528;
|
||||
unsigned short *whitemap;
|
||||
int whitemapsize = (dpi == 1200) ? 29282 : 14642;
|
||||
unsigned short *whitescan;
|
||||
unsigned short *lightmap;
|
||||
unsigned int topreg, botreg;
|
||||
int redreg, greenreg, bluereg, donered, donegreen, doneblue;
|
||||
int rgreg = 0x00;
|
||||
int ggreg = 0x00;
|
||||
int bgreg = 0x00;
|
||||
int i, j;
|
||||
int red, green, blue;
|
||||
unsigned char rd_byte;
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
char fname[64];
|
||||
char head[128];
|
||||
|
||||
len = usb_set_configuration (udev, 1);
|
||||
len = usb_claim_interface (udev, 0);
|
||||
len = usb_clear_halt (udev, 1);
|
||||
len = usb_clear_halt (udev, 2);
|
||||
len = usb_clear_halt (udev, 3);
|
||||
#endif
|
||||
DBG (2, "params.gray = %d;\n", p->gray);
|
||||
DBG (2, "params.dpi = %d\n", p->dpi);
|
||||
DBG (2, "params.bpp = %d\n", p->bpp);
|
||||
DBG (2, "params.gain = %f\n", p->gain);
|
||||
DBG (2, "params.offset = %d\n", p->offset);
|
||||
DBG (2, "params.lamp = %d\n", p->lamp);
|
||||
DBG (2, "params.top = %f\n", p->top);
|
||||
DBG (2, "params.left = %f\n", p->left);
|
||||
DBG (2, "params.height = %f\n", p->height);
|
||||
DBG (2, "params.width = %f\n", p->width);
|
||||
|
||||
DBG (2, "params.topline = %d\n", p->topline);
|
||||
DBG (2, "params.scanlines = %d\n", p->scanlines);
|
||||
DBG (2, "params.leftpix = %d\n", p->leftpix);
|
||||
DBG (2, "params.scanpix = %d\n", p->scanpix);
|
||||
|
||||
DBG (2, "params.linelen = %d\n", p->linelen);
|
||||
|
||||
reset_scanner (udev);
|
||||
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0b);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0f);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x05);
|
||||
write_vctl (udev, 0x0b, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85,
|
||||
0x00, 0x83, 0x00, 0x93, 0x00);
|
||||
write_regs (udev, 1, 0xa8, 0x80);
|
||||
write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0b);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0f);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x05);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xfe, 0x83, 0x00, 0x8d, 0xff);
|
||||
write_regs (udev, 1, 0x97, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
|
||||
0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
write_regs (udev, 1, 0x94, 0x51);
|
||||
write_regs (udev, 1, 0xb0, 0x00);
|
||||
write_regs (udev, 1, 0xb1, 0x00);
|
||||
write_regs (udev, 1, 0xb2, 0x00);
|
||||
write_regs (udev, 1, 0xb3, 0x00);
|
||||
write_regs (udev, 1, 0xb4, 0x10);
|
||||
write_regs (udev, 1, 0xb5, 0x1f);
|
||||
write_regs (udev, 1, 0xb0, 0x00);
|
||||
write_regs (udev, 1, 0xb1, 0x00);
|
||||
write_regs (udev, 1, 0xb2, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x0002, 0x0002, 0x00);
|
||||
len = usb_bulk_write (udev, 2, hello, 2, wr_timeout);
|
||||
write_regs (udev, 1, 0xb0, 0x00);
|
||||
write_regs (udev, 1, 0xb1, 0x00);
|
||||
write_regs (udev, 1, 0xb2, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x0003, 0x0003, 0x00);
|
||||
len = usb_bulk_read (udev, 1, howdy, 3, rd_timeout);
|
||||
write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0b);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0f);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x05);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xfe, 0x83, 0x00, 0x8d, 0xff);
|
||||
write_regs (udev, 1, 0x97, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
|
||||
0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
|
||||
0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
|
||||
0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
|
||||
0x00, 0xc0, 0x00);
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
|
||||
write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
|
||||
0xf7);
|
||||
write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x16);
|
||||
write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x00, 0x9d, 0x00, 0x9e,
|
||||
0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00, 0xa6,
|
||||
0x00, 0xa7, 0x00);
|
||||
|
||||
set_gain_black (udev, 0x01, 0x01, 0x01, 0xaa, 0xaa, 0xaa);
|
||||
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x02, 0x98,
|
||||
0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x03, 0x98, 0x00, 0x99,
|
||||
0x00, 0x9a, 0x00);
|
||||
write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x98, 0x83, 0x82, 0x85, 0x3a);
|
||||
write_regs (udev, 1, 0x9d, 0x80);
|
||||
write_regs (udev, 1, 0x9d, 0x00);
|
||||
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 1, 0x94, 0x51);
|
||||
else
|
||||
write_regs (udev, 1, 0x94, 0x61);
|
||||
|
||||
whitemap = (unsigned short *) malloc (whitemapsize);
|
||||
|
||||
set_lightmap_white (whitemap, dpi, 0);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x06, 0xb3, 0xff, 0xb4,
|
||||
0xff, 0xb5, 0x06);
|
||||
else
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0x7f, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
|
||||
len =
|
||||
usb_bulk_write (udev, 2, (unsigned char *) whitemap, whitemapsize,
|
||||
wr_timeout);
|
||||
|
||||
set_lightmap_white (whitemap, dpi, 1);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0x7f, 0xb5, 0x07);
|
||||
else
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0xbf, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
|
||||
len =
|
||||
usb_bulk_write (udev, 2, (unsigned char *) whitemap, whitemapsize,
|
||||
wr_timeout);
|
||||
|
||||
set_lightmap_white (whitemap, dpi, 2);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0xff, 0xb5, 0x07);
|
||||
else
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0xc0, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0xff, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
|
||||
len =
|
||||
usb_bulk_write (udev, 2, (unsigned char *) whitemap, whitemapsize,
|
||||
wr_timeout);
|
||||
|
||||
free (whitemap);
|
||||
|
||||
/* Move to head... */
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 1, 0x97, 0x00);
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
|
||||
0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
|
||||
0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
|
||||
0x00, 0xc0, 0x00);
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f, 0xcf,
|
||||
0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06, 0xc4, 0xff, 0xc5,
|
||||
0x40, 0xc6, 0x8c, 0xc7, 0xdc, 0xc8, 0x20, 0xc0, 0x72, 0x89,
|
||||
0xff, 0x86, 0xff);
|
||||
poll1 (udev);
|
||||
|
||||
write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85, 0x00);
|
||||
write_regs (udev, 1, 0x9d, 0x80);
|
||||
write_regs (udev, 1, 0x9d, 0x00);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0x77,
|
||||
0xb9, 0x1e);
|
||||
else
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0x3b,
|
||||
0xb9, 0x1f);
|
||||
write_regs (udev, 5, 0xc0, 0x00, 0x84, 0x00, 0x80, 0xa1, 0xcf, 0x04, 0x82,
|
||||
0x00);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x01, 0xbd, 0x01, 0x88, 0xa4, 0xc1, 0x02, 0xc2, 0x00,
|
||||
0xc3, 0x02, 0xc4, 0x01, 0xc5, 0x01, 0xc6, 0xa3, 0xc7, 0xa4,
|
||||
0xc8, 0x04, 0xc0, 0xd2, 0x89, 0x05, 0x86, 0x00);
|
||||
else
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x01, 0xbd, 0x01, 0x88, 0xd0, 0xc1, 0x01, 0xc2, 0x00,
|
||||
0xc3, 0x04, 0xc4, 0x01, 0xc5, 0x01, 0xc6, 0xcf, 0xc7, 0xd0,
|
||||
0xc8, 0x14, 0xc0, 0xd1, 0x89, 0x0a, 0x86, 0x00);
|
||||
write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80, 0xbf,
|
||||
0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
|
||||
write_regs (udev, 1, 0xbe, 0x0d);
|
||||
write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
|
||||
whitebalance = (unsigned short *) malloc (whitebalancesize);
|
||||
len = usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
|
||||
write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
|
||||
len =
|
||||
usb_bulk_read (udev, 1, (unsigned char *) whitebalance, whitebalancesize,
|
||||
rd_timeout);
|
||||
write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
redreg = greenreg = bluereg = 0x80;
|
||||
red = green = blue = 0;
|
||||
donered = donegreen = doneblue = 0;
|
||||
DBG (2, "setting blackpoint\n");
|
||||
for (j = 0; (j < 16) && !(donered && donegreen && doneblue); j++)
|
||||
{
|
||||
set_gain_black (udev, 0x01, 0x01, 0x01, redreg, greenreg, bluereg);
|
||||
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0x77, 0xb9, 0x1e);
|
||||
else
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0x3b, 0xb9, 0x1f);
|
||||
write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
|
||||
write_regs (udev, 1, 0xbe, 0x0d);
|
||||
write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
|
||||
len = usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
|
||||
write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
|
||||
len =
|
||||
usb_bulk_read (udev, 1, (unsigned char *) whitebalance,
|
||||
whitebalancesize, rd_timeout);
|
||||
if (!donered)
|
||||
{
|
||||
red = (whitebalance[0] + whitebalance[3] + whitebalance[6]) / 3;
|
||||
if (red > 0x1000)
|
||||
redreg += 0x10;
|
||||
else if (red > 0x500)
|
||||
redreg += 0x08;
|
||||
else if (red > 0x0010)
|
||||
redreg++;
|
||||
else
|
||||
donered = 1;
|
||||
}
|
||||
if (!donegreen)
|
||||
{
|
||||
green = (whitebalance[1] + whitebalance[4] + whitebalance[7]) / 3;
|
||||
if (green > 0x1000)
|
||||
greenreg += 0x10;
|
||||
else if (green > 0x0500)
|
||||
greenreg += 0x08;
|
||||
else if (green > 0x0010)
|
||||
greenreg++;
|
||||
else
|
||||
donegreen = 1;
|
||||
}
|
||||
if (!doneblue)
|
||||
{
|
||||
blue = (whitebalance[2] + whitebalance[5] + whitebalance[8]) / 3;
|
||||
if (blue > 0x1000)
|
||||
bluereg += 0x10;
|
||||
else if (blue > 0x0500)
|
||||
bluereg += 0x08;
|
||||
else if (blue > 0x0010)
|
||||
bluereg++;
|
||||
else
|
||||
doneblue = 1;
|
||||
}
|
||||
DBG (2, "red=%d(%d)%02x, green=%d(%d)%02x, blue=%d(%d)%02x\n",
|
||||
red, donered, redreg, green, donegreen, greenreg,
|
||||
blue, doneblue, bluereg);
|
||||
write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
}
|
||||
DBG (2, "setting whitepoint\n");
|
||||
donegreen = donered = doneblue = 0;
|
||||
for (j = 0; (j < 16) && !(donered && donegreen && doneblue); j++)
|
||||
{
|
||||
set_gain_black (udev, rgreg, ggreg, bgreg, redreg, greenreg, bluereg);
|
||||
|
||||
if (dpi == 1200)
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0x3b,
|
||||
0xb9, 0x1f);
|
||||
if (dpi == 1200)
|
||||
idle_ab (udev);
|
||||
write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
|
||||
write_regs (udev, 1, 0xbe, 0x0d);
|
||||
write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
|
||||
len = usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
|
||||
write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
|
||||
len =
|
||||
usb_bulk_read (udev, 1, (unsigned char *) whitebalance,
|
||||
whitebalancesize, rd_timeout);
|
||||
if (!donered)
|
||||
{
|
||||
red =
|
||||
(whitebalance[180 * 3 + 0] + whitebalance[180 * 3 + 3] +
|
||||
whitebalance[180 * 3 + 6]) / 3;
|
||||
if (red < 0x5000)
|
||||
rgreg += 0x02;
|
||||
else if (red < 0x8000)
|
||||
rgreg += 0x01;
|
||||
else
|
||||
donered = 1;
|
||||
}
|
||||
if (!donegreen)
|
||||
{
|
||||
green =
|
||||
(whitebalance[180 * 3 + 1] + whitebalance[180 * 3 + 4] +
|
||||
whitebalance[180 * 3 + 7]) / 3;
|
||||
if (green < 0x5000)
|
||||
ggreg += 0x02;
|
||||
else if (green < 0x8000)
|
||||
ggreg += 0x01;
|
||||
else
|
||||
donegreen = 1;
|
||||
}
|
||||
if (!doneblue)
|
||||
{
|
||||
blue =
|
||||
(whitebalance[180 * 3 + 2] + whitebalance[180 * 3 + 5] +
|
||||
whitebalance[180 * 3 + 8]) / 3;
|
||||
if (blue < 0x5000)
|
||||
bgreg += 0x02;
|
||||
else if (blue < 0x8000)
|
||||
bgreg += 0x01;
|
||||
else
|
||||
doneblue = 1;
|
||||
}
|
||||
DBG (2, "red=%d(%d)%02x, green=%d(%d)%02x, blue=%d(%d)%02x\n",
|
||||
red, donered, rgreg, green, donegreen, ggreg, blue, doneblue,
|
||||
bgreg);
|
||||
write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
}
|
||||
free (whitebalance);
|
||||
|
||||
/* One step down for optimal contrast... */
|
||||
if (rgreg)
|
||||
rgreg--;
|
||||
if (bgreg)
|
||||
bgreg--;
|
||||
if (ggreg)
|
||||
ggreg--;
|
||||
|
||||
|
||||
write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
|
||||
0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
|
||||
0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
|
||||
0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
|
||||
0x00, 0xc0, 0x00);
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
|
||||
write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
|
||||
0xf7);
|
||||
write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x16);
|
||||
write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x00, 0x9d, 0x00, 0x9e,
|
||||
0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00, 0xa6,
|
||||
0x00, 0xa7, 0x00);
|
||||
set_gain_black (udev, rgreg, ggreg, bgreg, redreg, greenreg, bluereg);
|
||||
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x02, 0x98,
|
||||
0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x03, 0x98, 0x00, 0x99,
|
||||
0x00, 0x9a, 0x00);
|
||||
write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x98, 0x83, 0x82, 0x85, 0x3a);
|
||||
write_regs (udev, 1, 0x9d, 0x80);
|
||||
write_regs (udev, 1, 0x9d, 0x00);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 1, 0x94, 0x71);
|
||||
else
|
||||
write_regs (udev, 1, 0x94, 0x61);
|
||||
|
||||
write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85, 0x00);
|
||||
write_regs (udev, 1, 0x9d, 0x80);
|
||||
write_regs (udev, 1, 0x9d, 0x00);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0xbf,
|
||||
0xb9, 0x17);
|
||||
else
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8, 0xdf,
|
||||
0xb9, 0x1b);
|
||||
write_regs (udev, 6, 0xc0, 0x00, 0x84, 0x00, 0x84, 0xb4, 0x80, 0xe1, 0xcf,
|
||||
0x04, 0x82, 0x00);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x08, 0x88, 0xa4, 0xc1, 0x02, 0xc2, 0x00,
|
||||
0xc3, 0x02, 0xc4, 0x20, 0xc5, 0x08, 0xc6, 0x96, 0xc7, 0xa4,
|
||||
0xc8, 0x06, 0xc0, 0xd2, 0x89, 0x24, 0x86, 0x01);
|
||||
else
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2, 0x00,
|
||||
0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3, 0xc7, 0xd0,
|
||||
0xc8, 0x1c, 0xc0, 0xd1, 0x89, 0x24, 0x86, 0x01);
|
||||
write_regs (udev, 8, 0xbb, 0x05, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80, 0xbf,
|
||||
0x00, 0x90, 0x40, 0x91, 0x00, 0x83, 0x82);
|
||||
write_regs (udev, 1, 0xbe, 0x1d);
|
||||
write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
|
||||
len = usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
|
||||
write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
|
||||
record_mem (udev, (unsigned char **) (void *)&whitescan,
|
||||
(5632 * 2 * 3 * (dpi == 1200 ? 2 : 1)) * 4);
|
||||
write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
|
||||
0xff);
|
||||
write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
|
||||
write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0b);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x0f);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x05);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
|
||||
write_regs (udev, 1, 0x97, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 1, 0x97, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
|
||||
read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
|
||||
write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
|
||||
0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
|
||||
0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
|
||||
0x00, 0xc0, 0x00);
|
||||
write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f, 0xcf,
|
||||
0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06, 0xc4, 0xff, 0xc5,
|
||||
0x40, 0xc6, 0x8c, 0xc7, 0xdc, 0xc8, 0x20, 0xc0, 0x72, 0x89,
|
||||
0xff, 0x86, 0xff);
|
||||
poll1 (udev);
|
||||
|
||||
/* ready scan position */
|
||||
/* 1/3" of unscannable area at top... */
|
||||
if (dpi == 300)
|
||||
topreg = 120 * 4;
|
||||
else if (dpi == 600)
|
||||
topreg = 139 * 4;
|
||||
else if (dpi == 1200)
|
||||
topreg = 152 * 4;
|
||||
else /*if (dpi == 150) */
|
||||
topreg = 120 * 4;
|
||||
topreg += topline * (1200 / dpi);
|
||||
|
||||
write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
|
||||
0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
|
||||
0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
|
||||
0x00, 0xc0, 0x00);
|
||||
write_regs (udev, 14, 0x84, 0xb4, 0x80, 0xe1, 0xcf, 0x04, 0xc1, 0x02, 0xc2,
|
||||
0x00, 0xc3, 0x07, 0xc4, 0xff, 0xc5, 0x40, 0xc6, 0x8c, 0xc7,
|
||||
0xdc, 0xc8, 0x20, 0xc0, 0x72, 0x89, topreg & 255, 0x86,
|
||||
255 & (topreg >> 8));
|
||||
write_regs (udev, 1, 0x97, 0x00);
|
||||
poll2 (udev);
|
||||
|
||||
write_regs (udev, 8, 0x80, 0x00, 0x84, 0x00, 0xbe, 0x00, 0xc0, 0x00, 0x86,
|
||||
0x00, 0x89, 0x00, 0x94, 0x00, 0x01, 0x02);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
|
||||
write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
|
||||
write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88,
|
||||
0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
|
||||
0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8,
|
||||
0x00, 0xc0, 0x00);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0x24, 0x83, 0x00, 0x8d, 0xff);
|
||||
else
|
||||
write_regs (udev, 4, 0x83, 0x20, 0x8d, 0xff, 0x83, 0x00, 0x8d, 0xff);
|
||||
if (dpi != 1200)
|
||||
write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2,
|
||||
0xf7);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x2c);
|
||||
else
|
||||
write_regs (udev, 4, 0x83, 0x22, 0x87, 0x01, 0x83, 0x02, 0x87, 0x16);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x40, 0x9d, 0x00,
|
||||
0x9e, 0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00,
|
||||
0xa6, 0x00, 0xa7, 0x00);
|
||||
else
|
||||
write_regs (udev, 11, 0xa0, 0x00, 0x9c, 0x00, 0x9f, 0x00, 0x9d, 0x00,
|
||||
0x9e, 0x00, 0xa0, 0x00, 0xce, 0x0c, 0x83, 0x20, 0xa5, 0x00,
|
||||
0xa6, 0x00, 0xa7, 0x00);
|
||||
|
||||
set_gain_black (udev, rgreg, ggreg, bgreg, redreg, greenreg, bluereg);
|
||||
if (!bpp16)
|
||||
{
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0xc7, 0x99, 0x99, 0x9a, 0xd5,
|
||||
0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x02, 0x98, 0xc8, 0x99, 0x99, 0x9a, 0xd3, 0x9b, 0x03,
|
||||
0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x94, 0x99, 0x67, 0x9a, 0x83,
|
||||
0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x02, 0x98, 0x7e, 0x99, 0x5d, 0x9a, 0x7d, 0x9b, 0x03,
|
||||
0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
|
||||
else
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0xb3, 0x99, 0x72, 0x9a, 0x9d,
|
||||
0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x02, 0x98, 0xa3, 0x99, 0x6f, 0x9a, 0x94, 0x9b, 0x03,
|
||||
0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0xb9, 0x99, 0x7a, 0x9a, 0xd6,
|
||||
0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x02, 0x98, 0xbc, 0x99, 0x7c, 0x9a, 0xd3, 0x9b, 0x03,
|
||||
0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x9c, 0x99, 0x5f, 0x9a, 0x87,
|
||||
0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x02, 0x98, 0x97, 0x99, 0x58, 0x9a, 0x81, 0x9b, 0x03,
|
||||
0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
|
||||
else
|
||||
write_regs (udev, 16, 0x9b, 0x00, 0x98, 0x9d, 0x99, 0x79, 0x9a, 0x8e,
|
||||
0x9b, 0x01, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b,
|
||||
0x02, 0x98, 0x89, 0x99, 0x71, 0x9a, 0x80, 0x9b, 0x03,
|
||||
0x98, 0x00, 0x99, 0x00, 0x9a, 0x00);
|
||||
}
|
||||
write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x98, 0x83, 0x82, 0x85, 0x3a);
|
||||
write_regs (udev, 1, 0x9d, 0x80);
|
||||
write_regs (udev, 1, 0x9d, 0x00);
|
||||
if (!bpp16)
|
||||
{
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 1, 0x94, 0x51);
|
||||
else
|
||||
write_regs (udev, 1, 0x94, 0x41);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 1, 0x94, 0x71);
|
||||
else
|
||||
write_regs (udev, 1, 0x94, 0x61);
|
||||
}
|
||||
lightmap = (unsigned short *) malloc (whitemapsize);
|
||||
calc_lightmap (whitescan, lightmap, 0, dpi, gain, offset);
|
||||
select_pixels (lightmap, dpi, leftpix, scanpix);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x06, 0xb3, 0xff, 0xb4,
|
||||
0xff, 0xb5, 0x06);
|
||||
else
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0x7f, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
|
||||
len =
|
||||
usb_bulk_write (udev, 2, (unsigned char *) lightmap, whitemapsize,
|
||||
wr_timeout);
|
||||
|
||||
calc_lightmap (whitescan, lightmap, 1, dpi, gain, offset);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0x7f, 0xb5, 0x07);
|
||||
else
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0xbf, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
|
||||
if (gray)
|
||||
for (i = 0; i < whitemapsize / 2; i++)
|
||||
lightmap[i] |= 0xc000;
|
||||
len =
|
||||
usb_bulk_write (udev, 2, (unsigned char *) lightmap, whitemapsize,
|
||||
wr_timeout);
|
||||
|
||||
calc_lightmap (whitescan, lightmap, 2, dpi, gain, offset);
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x80, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0xff, 0xb5, 0x07);
|
||||
else
|
||||
write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0xc0, 0xb2, 0x07, 0xb3, 0xff, 0xb4,
|
||||
0xff, 0xb5, 0x07);
|
||||
write_vctl (udev, 0x0c, 0x0002, whitemapsize, 0x00);
|
||||
len =
|
||||
usb_bulk_write (udev, 2, (unsigned char *) lightmap, whitemapsize,
|
||||
wr_timeout);
|
||||
|
||||
free (whitescan);
|
||||
free (lightmap);
|
||||
|
||||
if (!bpp16)
|
||||
download_lut8 (udev, dpi, gray ? 0 : 1);
|
||||
|
||||
write_regs (udev, 4, 0x83, 0xa2, 0x85, 0x01, 0x83, 0x82, 0x85, 0x00);
|
||||
write_regs (udev, 1, 0x9d, 0x80);
|
||||
write_regs (udev, 1, 0x9d, 0x00);
|
||||
|
||||
if (!bpp16)
|
||||
{
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0x1f, 0xb5, 0x06, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0x43, 0xb9, 0x2d);
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0x0f, 0xb5, 0x07, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0xe0, 0xb9, 0x37);
|
||||
else
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0x0f, 0xb5, 0x07, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0x90, 0xb9, 0x37);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dpi == 1200)
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0x87, 0xb9, 0x18);
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0xc1, 0xb9, 0x1e);
|
||||
else
|
||||
write_regs (udev, 10, 0xb0, 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0xff,
|
||||
0xb4, 0xff, 0xb5, 0x03, 0xb6, 0x01, 0xb7, 0x00, 0xb8,
|
||||
0x21, 0xb9, 0x1e);
|
||||
}
|
||||
|
||||
/* [86,89] controls number of 300dpi steps to scan */
|
||||
botreg = scanlines * (1200 / dpi) + 400;
|
||||
write_regs (udev, 6, 0xc0, 0x00, 0x84, 0x00, 0x84, 0xb4, 0x80, 0xe1, 0xcf,
|
||||
0x04, 0x82, 0x00);
|
||||
|
||||
if (!bpp16)
|
||||
{
|
||||
if (dpi == 300)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
|
||||
0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
|
||||
0xc7, 0xd0, 0xc8, 0x12, 0xc0, 0xd1, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
else if (dpi == 600)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
|
||||
0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
|
||||
0xc7, 0xd0, 0xc8, 0x16, 0xc0, 0xd1, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
else if (dpi == 1200)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x08, 0x88, 0xa4, 0xc1, 0x02, 0xc2,
|
||||
0x00, 0xc3, 0x02, 0xc4, 0x20, 0xc5, 0x08, 0xc6, 0x96,
|
||||
0xc7, 0xa4, 0xc8, 0x06, 0xc0, 0xd2, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x06, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x1c, 0xbd, 0x08, 0x88, 0xe0, 0xc1, 0x01, 0xc2,
|
||||
0x00, 0xc3, 0x03, 0xc4, 0x1c, 0xc5, 0x08, 0xc6, 0xd7,
|
||||
0xc7, 0xe0, 0xc8, 0x11, 0xc0, 0xd1, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
|
||||
if (dpi == 300)
|
||||
write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
|
||||
else if (dpi == 600)
|
||||
write_regs (udev, 8, 0xbb, 0x02, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
|
||||
else if (dpi == 1200)
|
||||
write_regs (udev, 8, 0xbb, 0x02, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 8, 0xbb, 0x00, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x20, 0x91, 0x00, 0x83, 0x82);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dpi == 300)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
|
||||
0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
|
||||
0xc7, 0xd0, 0xc8, 0x13, 0xc0, 0xd1, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x06, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x1c, 0xbd, 0x08, 0x88, 0xe0, 0xc1, 0x01, 0xc2,
|
||||
0x00, 0xc3, 0x03, 0xc4, 0x1c, 0xc5, 0x08, 0xc6, 0xd7,
|
||||
0xc7, 0xe0, 0xc8, 0x12, 0xc0, 0xd1, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
else if (dpi == 1200)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x02, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x08, 0x88, 0xa4, 0xc1, 0x02, 0xc2,
|
||||
0x00, 0xc3, 0x02, 0xc4, 0x20, 0xc5, 0x08, 0xc6, 0x96,
|
||||
0xc7, 0xa4, 0xc8, 0x0c, 0xc0, 0xd2, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
else if (dpi == 600)
|
||||
write_regs (udev, 18, 0x83, 0xa2, 0x85, 0x04, 0x83, 0x82, 0x85, 0x00,
|
||||
0xbc, 0x20, 0xbd, 0x10, 0x88, 0xd0, 0xc1, 0x01, 0xc2,
|
||||
0x00, 0xc3, 0x04, 0xc4, 0x20, 0xc5, 0x10, 0xc6, 0xc3,
|
||||
0xc7, 0xd0, 0xc8, 0x1a, 0xc0, 0xd1, 0x89, botreg & 255,
|
||||
0x86, 255 & (botreg >> 8));
|
||||
|
||||
if (dpi == 300)
|
||||
write_regs (udev, 8, 0xbb, 0x02, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
|
||||
else if (dpi == 150)
|
||||
write_regs (udev, 8, 0xbb, 0x01, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
|
||||
else if (dpi == 1200)
|
||||
write_regs (udev, 8, 0xbb, 0x05, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
|
||||
else if (dpi == 600)
|
||||
write_regs (udev, 8, 0xbb, 0x04, 0x9b, 0x24, 0x8b, 0x00, 0x8e, 0x80,
|
||||
0xbf, 0x00, 0x90, 0x70, 0x91, 0x00, 0x83, 0x82);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (gray)
|
||||
write_regs (udev, 1, 0xbe, 0x05);
|
||||
else
|
||||
write_regs (udev, 1, 0xbe, 0x0d);
|
||||
write_vctl (udev, 0x0c, 0x0003, 0x0001, 0x00);
|
||||
len = usb_bulk_read (udev, 1, &rd_byte, 1, rd_timeout);
|
||||
write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
|
||||
|
||||
#ifndef BACKENDNAME
|
||||
sprintf (fname, "%d.%s", dpi, gray ? "pgm" : "ppm");
|
||||
if (stname)
|
||||
strcpy (fname, stname);
|
||||
sprintf (head, "P%d\n%d %d\n%d\n", gray ? 5 : 6, scanpix, scanlines,
|
||||
bpp16 ? 65535 : 255);
|
||||
if (nohead)
|
||||
head[0] = 0;
|
||||
if (!raw)
|
||||
record_image (udev, fname, dpi, scanpix, scanlines, gray, head, bpp16);
|
||||
else
|
||||
record_head (udev, fname,
|
||||
scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1) * scanlines, "");
|
||||
|
||||
reset_scanner (udev);
|
||||
idle_ab (udev);
|
||||
set_lamp_timer (udev, 5);
|
||||
#endif
|
||||
}
|
|
@ -9639,9 +9639,9 @@ fi;
|
|||
|
||||
if test "${ac_cv_header_usb_h}" = "yes" && test "$USE_LIBUSB" = "yes" ; then
|
||||
|
||||
echo "$as_me:$LINENO: checking for usb_get_busses in -lusb" >&5
|
||||
echo $ECHO_N "checking for usb_get_busses in -lusb... $ECHO_C" >&6
|
||||
if test "${ac_cv_lib_usb_usb_get_busses+set}" = set; then
|
||||
echo "$as_me:$LINENO: checking for usb_interrupt_read in -lusb" >&5
|
||||
echo $ECHO_N "checking for usb_interrupt_read in -lusb... $ECHO_C" >&6
|
||||
if test "${ac_cv_lib_usb_usb_interrupt_read+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
|
@ -9659,11 +9659,11 @@ extern "C"
|
|||
#endif
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char usb_get_busses ();
|
||||
char usb_interrupt_read ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
usb_get_busses ();
|
||||
usb_interrupt_read ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
@ -9689,20 +9689,20 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
|||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lib_usb_usb_get_busses=yes
|
||||
ac_cv_lib_usb_usb_interrupt_read=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_usb_usb_get_busses=no
|
||||
ac_cv_lib_usb_usb_interrupt_read=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lib_usb_usb_get_busses" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_usb_usb_get_busses" >&6
|
||||
if test $ac_cv_lib_usb_usb_get_busses = yes; then
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lib_usb_usb_interrupt_read" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_usb_usb_interrupt_read" >&6
|
||||
if test $ac_cv_lib_usb_usb_interrupt_read = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBUSB 1
|
||||
_ACEOF
|
||||
|
@ -9711,7 +9711,7 @@ _ACEOF
|
|||
|
||||
fi
|
||||
|
||||
if test "${ac_cv_lib_usb_usb_get_busses}" = "yes" ; then
|
||||
if test "${ac_cv_lib_usb_usb_interrupt_read}" = "yes" ; then
|
||||
HAVE_LIBUSB="yes"
|
||||
fi
|
||||
fi
|
||||
|
@ -25618,7 +25618,7 @@ echo "$as_me: Manually selected backends: ${BACKENDS}" >&6;}
|
|||
microtek2 mustek mustek_usb nec pie plustek \
|
||||
plustek_pp ricoh s9036 sceptre sharp \
|
||||
sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u \
|
||||
artec_eplus48u ma1509 ibm hp5400 u12 snapscan niash"
|
||||
artec_eplus48u ma1509 ibm hp5400 u12 snapscan niash sm3840"
|
||||
|
||||
if test "${sane_cv_use_libjpeg}" != "yes"; then
|
||||
echo "*** disabling DC210 backend (failed to find JPEG library)"
|
||||
|
|
|
@ -299,7 +299,7 @@ else
|
|||
microtek2 mustek mustek_usb nec pie plustek \
|
||||
plustek_pp ricoh s9036 sceptre sharp \
|
||||
sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u \
|
||||
artec_eplus48u ma1509 ibm hp5400 u12 snapscan niash"
|
||||
artec_eplus48u ma1509 ibm hp5400 u12 snapscan niash sm3840"
|
||||
|
||||
if test "${sane_cv_use_libjpeg}" != "yes"; then
|
||||
echo "*** disabling DC210 backend (failed to find JPEG library)"
|
||||
|
|
|
@ -52,7 +52,7 @@ SECT5 = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 \
|
|||
sane-teco1.5 sane-teco2.5 sane-teco3.5 sane-test.5 sane-sp15c.5 \
|
||||
sane-coolscan2.5 sane-hpsj5s.5 sane-gt68xx.5 sane-artec_eplus48u.5 \
|
||||
sane-ma1509.5 sane-ibm.5 sane-hp5400.5 sane-plustek_pp.5 sane-u12.5 \
|
||||
sane-niash.5
|
||||
sane-niash.5 sane-sm3840.5
|
||||
SECT7 = sane.7
|
||||
SECT8 = saned.8
|
||||
MANPAGES = $(SECT1) $(SECT5) $(SECT7) $(SECT8)
|
||||
|
@ -103,7 +103,7 @@ DISTFILES = Makefile.in backend-writing.txt descriptions.txt \
|
|||
sane-teco1.man sane-teco2.man sane-teco3.man sane-test.man sane-sp15c.man \
|
||||
sane-hpsj5s.man gamma4scanimage.man sane-gt68xx.man sane-artec_eplus48u.man \
|
||||
sane-ma1509.man sane-ibm.man sane-hp5400.man sane-plustek_pp.man \
|
||||
sane-u12.man sane-niash.man
|
||||
sane-u12.man sane-niash.man sane-sm3840.man
|
||||
|
||||
.PHONY: all clean depend dist distclean html html-man install \
|
||||
sane-html uninstall
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
;
|
||||
; SANE Backend specification file
|
||||
;
|
||||
; It's basically emacs-lisp --- so ";" indicates comment to end of line.
|
||||
; All syntactic elements are keyword tokens, followed by a string or
|
||||
; keyword argument, as specified.
|
||||
;
|
||||
; ":backend" *must* be specified.
|
||||
; All other information is optional (but what good is the file without it?).
|
||||
;
|
||||
; See doc/descriptions.txt for details.
|
||||
|
||||
:backend "sm3840" ; name of backend
|
||||
:version "1.0" ; version of backend (or "unmaintained")
|
||||
:new :yes ; Is the backend new to this SANE release?
|
||||
; :yes or :no
|
||||
:manpage "sane-sm3840" ; name of manpage (if it exists)
|
||||
:url "http://www.ziplabel.com/sm3840/" ; backend's web page
|
||||
:comment "This reverse-engineered backend supports the USB ScanMaker 3840 model"
|
||||
; comment about the backend
|
||||
|
||||
:devicetype :scanner ; start of a list of devices....
|
||||
; other types: :stillcam, :vidcam,
|
||||
; :meta, :api
|
||||
|
||||
:mfg "Microtek" ; name a manufacturer
|
||||
:url "http://www.microtek.com/" ; manufacturer's URL
|
||||
:comment "Microtek makes a wide variety of devices."
|
||||
; comment about the manufacturer
|
||||
|
||||
:model "ScanMaker 3840" ; name models for above-specified mfg.
|
||||
:status :good ; :minimal, :basic, :good, :complete
|
||||
; :untested, or :unsupported
|
||||
:interface "USB" ; interface type of the device:
|
||||
; "SCSI", "USB", "Parport (EPP)",
|
||||
; "Parport (SPP)", "Parport (ECP)",
|
||||
; "Serial port", "IEEE-1394", "JetDirect",
|
||||
; or "Proprietary".
|
||||
:comment "8 and 16 bit, color and grayscale" ; comment about the model
|
||||
|
||||
; :comment and :url specifiers are optional after :mfg, :model, :desc,
|
||||
; and at the top-level.
|
||||
|
||||
; :status specifier is optional after :model and at the top-level
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
.TH sane-sm3840 5 "Feb 6, 2005" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
||||
.IX sane-sm3840
|
||||
.SH NAME
|
||||
sane-sm3840 \- SANE backend for Microtek scanners with SCAN08 USB chip
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B sane-sm3840
|
||||
library implements a SANE (Scanner Access Now Easy) backend that
|
||||
provides access to some Microtek scanners with the SCAN08
|
||||
USB chip.
|
||||
.PP
|
||||
There exist backends for Microtek scanners with SCSI command set.
|
||||
Refer to sane-microtek(5) and sane-microtek2(5) for details.
|
||||
.PP
|
||||
At present, the following
|
||||
scanners are known positively to work with this backend:
|
||||
.PP
|
||||
.RS
|
||||
Vendor Product id: Remark:
|
||||
.br
|
||||
-------- -------------- -----------
|
||||
.br
|
||||
Microtek ScanMaker 3840 all modes ok
|
||||
.RE
|
||||
.PP
|
||||
If you own a Microtek scanner with the SCAN08 chip other than the ones
|
||||
listed above, it may or may not work with SANE. Feel free to contact the
|
||||
backend author (earle@ziplabel.com) to report results with scanners not
|
||||
on the list.
|
||||
|
||||
|
||||
.SH "FRONTEND OPTIONS"
|
||||
.PP
|
||||
The following options are supported by the sm3840-driver:
|
||||
.PP
|
||||
.B --mode color|gray
|
||||
.br
|
||||
Color or grayscale mode.
|
||||
|
||||
.B --resolution 150|300|600|1200
|
||||
.br
|
||||
Pixels per inch for scans.
|
||||
|
||||
.B --depth 8|16
|
||||
.br
|
||||
Note that the least significant bits of 16bpp mode may be noise.
|
||||
|
||||
.B --brightness 1..4096
|
||||
.br
|
||||
Higher numbers increase brightness of returned image.
|
||||
|
||||
.B --contrast 0.1..9.9
|
||||
.br
|
||||
Larger numbers decrease contrast of returned image.
|
||||
|
||||
.B --lamp-timeout 1..15
|
||||
.br
|
||||
Time in minutes until the lamp is turned off after a scan.
|
||||
|
||||
.SH CONFIGURATION
|
||||
This backend does not support a configuration file right now.
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
.I @LIBDIR@/libsane-sm3840.a
|
||||
The static library implementing this backend.
|
||||
.TP
|
||||
.I @LIBDIR@/libsane-sm3840.so
|
||||
The shared library implementing this backend (present on systems that
|
||||
support dynamic loading).
|
||||
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B SANE_DEBUG_SM3840
|
||||
If the library was compiled with debug support enabled, this
|
||||
environment variable controls the debug level for this backend. E.g.,
|
||||
a value of 128 requests all debug output to be printed. Smaller
|
||||
levels reduce verbosity. To see error messages on stderr set
|
||||
SANE_DEBUG_SM3840 to 1.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
sane-microtek2(5), sane-sm3600(5), http://www.ziplabel.com/sm3840
|
||||
|
||||
.SH AUTHOR
|
||||
.br
|
||||
Earle F. Philhower III (earle@ziplabel.com)
|
||||
.br
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
.TH sane 7 "03 Aug 2004" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
||||
.TH sane 7 "20 Feb 2005" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
||||
.IX sane
|
||||
|
||||
.SH NAME
|
||||
|
@ -376,6 +376,11 @@ The SANE sm3600 backend supports the Microtek ScanMaker 3600 USB scanner. See
|
|||
.BR sane\-sm3600 (5)
|
||||
for details.
|
||||
.TP
|
||||
.B sm3840
|
||||
The SANE sm3840 backend suppoert the Microtek ScanMaker 3840 USB scanner. See
|
||||
.BR sane\-sm3840 (5)
|
||||
for details.
|
||||
.TP
|
||||
.B snapscan
|
||||
The snapscan backend supports AGFA SnapScan flatbed scanners. See
|
||||
.BR sane\-snapscan (5)
|
||||
|
@ -804,4 +809,4 @@ David Mosberger-Tang and many many more (see
|
|||
for details). This man page was written by Henning Meier-Geinitz. Quite a lot
|
||||
of text was taken from the
|
||||
.B SANE
|
||||
standard, several man pages, and README files.
|
||||
standard, several man pages, and README files.
|
||||
|
|
Ładowanie…
Reference in New Issue